From 889aa0354aa533dce0e96334401267aa30bff215 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 27 Oct 2023 22:43:37 -0400 Subject: CMP0155: ignore scanning for sources if no scanner is available This allows for a more graceful transition for projects using C++20 without scanner support (e.g., Clang 15 or GCC 13). While newer compilers will (needlessly) scan, it allows C++20-using projects to use older compilers without having to set `CMAKE_CXX_SCAN_FOR_MODULES` to support newer CMake minimum versions. Fixes: #25357 --- Help/manual/cmake-cxxmodules.7.rst | 3 ++- Help/manual/cmake-policies.7.rst | 2 +- Help/policy/CMP0155.rst | 6 ++++-- Source/cmGeneratorTarget.cxx | 10 ++++++++-- Source/cmPolicies.h | 8 ++++---- Tests/RunCMake/CXXModules/CMP0155-NEW-result.txt | 1 - Tests/RunCMake/CXXModules/CMP0155-NEW-stderr.txt | 10 ---------- Tests/RunCMake/CXXModules/CMP0155-NEW-with-rule.cmake | 11 +++++++++++ Tests/RunCMake/CXXModules/CMP0155-NEW.cmake | 4 ++-- Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 1 + 10 files changed, 33 insertions(+), 23 deletions(-) delete mode 100644 Tests/RunCMake/CXXModules/CMP0155-NEW-result.txt delete mode 100644 Tests/RunCMake/CXXModules/CMP0155-NEW-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/CMP0155-NEW-with-rule.cmake diff --git a/Help/manual/cmake-cxxmodules.7.rst b/Help/manual/cmake-cxxmodules.7.rst index 99915e3..b4c9cf1 100644 --- a/Help/manual/cmake-cxxmodules.7.rst +++ b/Help/manual/cmake-cxxmodules.7.rst @@ -27,7 +27,8 @@ following queries. The first query that provides a yes/no answer is used. - If the :prop_tgt:`CXX_SCAN_FOR_MODULES` target property is set, its value will be used. Set the :variable:`CMAKE_CXX_SCAN_FOR_MODULES` variable to initialize this property on all targets as they are created. -- Otherwise, the source file will be scanned. See policy :policy:`CMP0155`. +- Otherwise, the source file will be scanned if the compiler and generator + support scanning. See policy :policy:`CMP0155`. Compiler Support ================ diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 047dfd1..46707ff 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,7 +57,7 @@ Policies Introduced by CMake 3.28 .. toctree:: :maxdepth: 1 - CMP0155: C++ sources in targets with at least C++20 are scanned for imports. + CMP0155: C++ sources in targets with at least C++20 are scanned for imports when supported. CMP0154: Generated files are private by default in targets using file sets. CMP0153: The exec_program command should not be called. CMP0152: file(REAL_PATH) resolves symlinks before collapsing ../ components. diff --git a/Help/policy/CMP0155.rst b/Help/policy/CMP0155.rst index 2dafadf..8b741cb 100644 --- a/Help/policy/CMP0155.rst +++ b/Help/policy/CMP0155.rst @@ -3,7 +3,8 @@ CMP0155 .. versionadded:: 3.28 -C++ sources in targets with at least C++20 are scanned for imports. +C++ sources in targets with at least C++20 are scanned for imports +when supported. CMake 3.27 and below assume that C++ sources do not ``import`` modules. CMake 3.28 and above prefer to assume that C++ sources in targets using C++20 @@ -16,7 +17,8 @@ support. The ``OLD`` behavior for this policy is to assume that C++ 20 and newer sources do not import modules. The ``NEW`` behavior for this policy is to -assume that C++ 20 and newer files may import modules, and need to be scanned. +assume that C++ 20 and newer files may import modules if the compiler +understands how to scan for their dependencies, and need to be scanned. This policy was introduced in CMake version 3.28. Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 2ea18bd..a9225dc 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -9292,14 +9292,19 @@ bool cmGeneratorTarget::NeedDyndepForSource(std::string const& lang, return true; } + bool haveRule = false; switch (this->HaveCxxModuleSupport(config)) { case Cxx20SupportLevel::MissingCxx: case Cxx20SupportLevel::NoCxx20: return false; case Cxx20SupportLevel::MissingRule: + break; case Cxx20SupportLevel::Supported: + haveRule = true; break; } + bool haveGeneratorSupport = + this->GetGlobalGenerator()->CheckCxxModuleSupport(); auto const sfProp = sf->GetProperty("CXX_SCAN_FOR_MODULES"); if (sfProp.IsSet()) { return sfProp.IsOn(); @@ -9319,8 +9324,9 @@ bool cmGeneratorTarget::NeedDyndepForSource(std::string const& lang, case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: case cmPolicies::NEW: - // The NEW behavior is to scan the source. - policyAnswer = true; + // The NEW behavior is to scan the source if the compiler supports + // scanning and the generator supports it. + policyAnswer = haveRule && haveGeneratorSupport; break; } return policyAnswer; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 1ea2ce2..8838de4 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -470,10 +470,10 @@ class cmMakefile; POLICY, CMP0154, \ "Generated files are private by default in targets using file sets.", 3, \ 28, 0, cmPolicies::WARN) \ - SELECT( \ - POLICY, CMP0155, \ - "C++ sources in targets with at least C++20 are scanned for imports", 3, \ - 28, 0, cmPolicies::WARN) + SELECT(POLICY, CMP0155, \ + "C++ sources in targets with at least C++20 are scanned for " \ + "imports when supported.", \ + 3, 28, 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/CXXModules/CMP0155-NEW-result.txt b/Tests/RunCMake/CXXModules/CMP0155-NEW-result.txt deleted file mode 100644 index d00491f..0000000 --- a/Tests/RunCMake/CXXModules/CMP0155-NEW-result.txt +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/Tests/RunCMake/CXXModules/CMP0155-NEW-stderr.txt b/Tests/RunCMake/CXXModules/CMP0155-NEW-stderr.txt deleted file mode 100644 index 0843d0b..0000000 --- a/Tests/RunCMake/CXXModules/CMP0155-NEW-stderr.txt +++ /dev/null @@ -1,10 +0,0 @@ -(CMake Error in CMakeLists.txt: - The target named "cmp0155-new" has C\+\+ sources that may use modules, but - the compiler does not provide a way to discover the import graph - dependencies\. See the cmake-cxxmodules\(7\) manual and the - CMAKE_CXX_SCAN_FOR_MODULES variable\. -|CMake Error in CMakeLists.txt: - The target named "cmp0155-new" has C\+\+ sources that may use modules, but - modules are not supported by this generator\. See the cmake-cxxmodules\(7\) - manual and the CMAKE_CXX_SCAN_FOR_MODULES variable\. -) diff --git a/Tests/RunCMake/CXXModules/CMP0155-NEW-with-rule.cmake b/Tests/RunCMake/CXXModules/CMP0155-NEW-with-rule.cmake new file mode 100644 index 0000000..9eda4df --- /dev/null +++ b/Tests/RunCMake/CXXModules/CMP0155-NEW-with-rule.cmake @@ -0,0 +1,11 @@ +enable_language(CXX) +set(CMAKE_CXX_SCANDEP_SOURCE "echo") + +cmake_policy(SET CMP0155 NEW) + +add_executable(cmp0155-new-with-rule + sources/module-use.cxx) +set_target_properties(cmp0155-new-with-rule + PROPERTIES + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED ON) diff --git a/Tests/RunCMake/CXXModules/CMP0155-NEW.cmake b/Tests/RunCMake/CXXModules/CMP0155-NEW.cmake index bea858b..d68775a 100644 --- a/Tests/RunCMake/CXXModules/CMP0155-NEW.cmake +++ b/Tests/RunCMake/CXXModules/CMP0155-NEW.cmake @@ -3,8 +3,8 @@ unset(CMAKE_CXX_SCANDEP_SOURCE) cmake_policy(SET CMP0155 NEW) -add_executable(cmp0155-new - sources/module-use.cxx) +add_library(cmp0155-new + sources/cxx-anchor.cxx) set_target_properties(cmp0155-new PROPERTIES CXX_STANDARD 20 diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index e687e9f..6813d98 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -23,6 +23,7 @@ if ("cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES) run_cmake(NoScanningVariable) run_cmake(CMP0155-OLD) run_cmake(CMP0155-NEW) + run_cmake(CMP0155-NEW-with-rule) endif () if (RunCMake_GENERATOR MATCHES "Ninja") -- cgit v0.12 From 1f507580a13b2883a016cab2f18cf3d6f868d269 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 31 Oct 2023 13:09:36 -0400 Subject: cmGlobalGenerator: give context about module queries Some queries are merely investigating support in order to change behavior. Let the method know so that any internal errors can be skipped over. --- Source/cmGeneratorTarget.cxx | 9 ++++++--- Source/cmGlobalGenerator.h | 12 +++++++++++- Source/cmGlobalNinjaGenerator.cxx | 5 +++-- Source/cmGlobalNinjaGenerator.h | 2 +- Source/cmGlobalVisualStudioVersionedGenerator.h | 2 +- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index a9225dc..f224ec1 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -9190,7 +9190,8 @@ void cmGeneratorTarget::CheckCxxModuleStatus(std::string const& config) const // If the generator doesn't support modules at all, error that we have // sources that require the support. - if (!this->GetGlobalGenerator()->CheckCxxModuleSupport()) { + if (!this->GetGlobalGenerator()->CheckCxxModuleSupport( + cmGlobalGenerator::CxxModuleSupportQuery::Expected)) { this->Makefile->IssueMessage( MessageType::FATAL_ERROR, cmStrCat( @@ -9248,7 +9249,8 @@ bool cmGeneratorTarget::NeedCxxModuleSupport(std::string const& lang, return false; } return this->HaveCxxModuleSupport(config) == Cxx20SupportLevel::Supported && - this->GetGlobalGenerator()->CheckCxxModuleSupport(); + this->GetGlobalGenerator()->CheckCxxModuleSupport( + cmGlobalGenerator::CxxModuleSupportQuery::Inspect); } bool cmGeneratorTarget::NeedDyndep(std::string const& lang, @@ -9304,7 +9306,8 @@ bool cmGeneratorTarget::NeedDyndepForSource(std::string const& lang, break; } bool haveGeneratorSupport = - this->GetGlobalGenerator()->CheckCxxModuleSupport(); + this->GetGlobalGenerator()->CheckCxxModuleSupport( + cmGlobalGenerator::CxxModuleSupportQuery::Inspect); auto const sfProp = sf->GetProperty("CXX_SCAN_FOR_MODULES"); if (sfProp.IsSet()) { return sfProp.IsOn(); diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 6d29dc1..aa54f69 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -156,7 +156,17 @@ public: virtual bool InspectConfigTypeVariables() { return true; } - virtual bool CheckCxxModuleSupport() { return false; } + enum class CxxModuleSupportQuery + { + // Support is expected at the call site. + Expected, + // The call site is querying for support and handles problems by itself. + Inspect, + }; + virtual bool CheckCxxModuleSupport(CxxModuleSupportQuery /*query*/) + { + return false; + } virtual bool IsGNUMakeJobServerAware() const { return false; } diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 7368a6a..d691d88 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -882,13 +882,14 @@ bool cmGlobalNinjaGenerator::CheckLanguages( return true; } -bool cmGlobalNinjaGenerator::CheckCxxModuleSupport() +bool cmGlobalNinjaGenerator::CheckCxxModuleSupport(CxxModuleSupportQuery query) { if (this->NinjaSupportsDyndepsCxx) { return true; } bool const diagnose = !this->DiagnosedCxxModuleNinjaSupport && - !this->CMakeInstance->GetIsInTryCompile(); + !this->CMakeInstance->GetIsInTryCompile() && + query == CxxModuleSupportQuery::Expected; if (diagnose) { std::ostringstream e; /* clang-format off */ diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 56a922c..c5d6901 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -475,7 +475,7 @@ public: bool IsSingleConfigUtility(cmGeneratorTarget const* target) const; - bool CheckCxxModuleSupport() override; + bool CheckCxxModuleSupport(CxxModuleSupportQuery query) override; protected: void Generate() override; diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index 8f0345f..49643ea 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -48,7 +48,7 @@ public: const char* GetAndroidApplicationTypeRevision() const override; - bool CheckCxxModuleSupport() override + bool CheckCxxModuleSupport(CxxModuleSupportQuery /*query*/) override { return this->SupportsCxxModuleDyndep(); } -- cgit v0.12