Browse Source

Merge topic 'cxxmodules-cmp0155-graceful-fallback-without-scanner' into release-3.28

1f507580a1 cmGlobalGenerator: give context about module queries
889aa0354a CMP0155: ignore scanning for sources if no scanner is available

Acked-by: Kitware Robot <[email protected]>
Tested-by: buildbot <[email protected]>
Merge-request: !8925
Brad King 2 years ago
parent
commit
59c3ce4c83

+ 2 - 1
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
 ================

+ 1 - 1
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. </policy/CMP0155>
+   CMP0155: C++ sources in targets with at least C++20 are scanned for imports when supported. </policy/CMP0155>
    CMP0154: Generated files are private by default in targets using file sets. </policy/CMP0154>
    CMP0153: The exec_program command should not be called. </policy/CMP0153>
    CMP0152: file(REAL_PATH) resolves symlinks before collapsing ../ components.  </policy/CMP0152>

+ 4 - 2
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.

+ 13 - 4
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,
@@ -9292,14 +9294,20 @@ 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(
+      cmGlobalGenerator::CxxModuleSupportQuery::Inspect);
   auto const sfProp = sf->GetProperty("CXX_SCAN_FOR_MODULES");
   if (sfProp.IsSet()) {
     return sfProp.IsOn();
@@ -9319,8 +9327,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;

+ 11 - 1
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; }
 

+ 3 - 2
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 */

+ 1 - 1
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;

+ 1 - 1
Source/cmGlobalVisualStudioVersionedGenerator.h

@@ -48,7 +48,7 @@ public:
 
   const char* GetAndroidApplicationTypeRevision() const override;
 
-  bool CheckCxxModuleSupport() override
+  bool CheckCxxModuleSupport(CxxModuleSupportQuery /*query*/) override
   {
     return this->SupportsCxxModuleDyndep();
   }

+ 4 - 4
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)                                         \

+ 0 - 1
Tests/RunCMake/CXXModules/CMP0155-NEW-result.txt

@@ -1 +0,0 @@
-1

+ 0 - 10
Tests/RunCMake/CXXModules/CMP0155-NEW-stderr.txt

@@ -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\.
-)

+ 11 - 0
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)

+ 2 - 2
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

+ 1 - 0
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")