Browse Source

Do not define CMAKE_PARENT_LIST_FILE in CMakeLists.txt

Add policy `CMP0198` for compatibility.

Issue: #25026
Benjamin Buch 5 months ago
parent
commit
41aea12941

+ 8 - 0
Help/manual/cmake-policies.7.rst

@@ -92,6 +92,14 @@ Supported Policies
 
 The following policies are supported.
 
+Policies Introduced by CMake 4.2
+--------------------------------
+
+.. toctree::
+   :maxdepth: 1
+
+   CMP0198: CMAKE_PARENT_LIST_FILE is not defined in CMakeLists.txt. </policy/CMP0198>
+
 Policies Introduced by CMake 4.1
 --------------------------------
 

+ 23 - 0
Help/policy/CMP0198.rst

@@ -0,0 +1,23 @@
+CMP0198
+-------
+
+.. versionadded:: 4.2
+
+:variable:`CMAKE_PARENT_LIST_FILE` is not defined in ``CMakeLists.txt``.
+
+CMake 4.1 and below defined ``CMAKE_PARENT_LIST_FILE`` when processing
+a ``CMakeLists.txt`` even though there is no parent file.  CMake 4.2
+and above prefer to not define ``CMAKE_PARENT_LIST_FILE``.  This policy
+provides compatibility for projects that accidentally relied on the
+old behavior.
+
+The ``OLD`` behavior for this policy is to set
+:variable:`CMAKE_PARENT_LIST_FILE` to :variable:`CMAKE_CURRENT_LIST_FILE`
+when processing a ``CMakeLists.txt``.  The ``NEW`` behavior for this policy
+is to not set :variable:`CMAKE_PARENT_LIST_FILE`.
+
+.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.2
+.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
+.. include:: include/STANDARD_ADVICE.rst
+
+.. include:: include/DEPRECATED.rst

+ 5 - 0
Help/release/dev/cmake-parent-fix.rst

@@ -0,0 +1,5 @@
+cmake-parent-fix
+----------------
+
+* :variable:`CMAKE_PARENT_LIST_FILE` is no longer defined when processing
+  a ``CMakeLists.txt`` file.  See policy :policy:`CMP0198`.

+ 2 - 1
Help/variable/CMAKE_PARENT_LIST_FILE.rst

@@ -8,7 +8,8 @@ While processing a CMake file loaded by :command:`include` or
 including it.
 
 While processing a ``CMakeLists.txt`` file, even in subdirectories,
-this variable has the same value as :variable:`CMAKE_CURRENT_LIST_FILE`.
+this variable is not defined.  See policy :policy:`CMP0198`.
+
 While processing a :option:`cmake -P` script, this variable is not defined
 in the outermost script.
 

+ 38 - 1
Source/cmMakefile.cxx

@@ -1553,7 +1553,23 @@ void cmMakefile::Configure()
   cmSystemTools::MakeDirectory(filesDir);
 
   assert(cmSystemTools::FileExists(currentStart, true));
-  this->AddDefinition(kCMAKE_PARENT_LIST_FILE, currentStart);
+
+  // In the top-most directory, cmake_minimum_required() may not have been
+  // called yet, so ApplyPolicyVersion() may not have handled the default
+  // policy value.  Check them here.
+  if (this->GetPolicyStatus(cmPolicies::CMP0198) == cmPolicies::WARN) {
+    if (cmValue defaultValue =
+          this->GetDefinition("CMAKE_POLICY_DEFAULT_CMP0198")) {
+      if (*defaultValue == "NEW") {
+        this->SetPolicy(cmPolicies::CMP0198, cmPolicies::NEW);
+      } else if (*defaultValue == "OLD") {
+        this->SetPolicy(cmPolicies::CMP0198, cmPolicies::OLD);
+      }
+    }
+  }
+
+  // Set CMAKE_PARENT_LIST_FILE for CMakeLists.txt based on CMP0198 policy
+  this->UpdateParentListFileVariable();
 
 #ifdef CMake_ENABLE_DEBUGGER
   if (this->GetCMakeInstance()->GetDebugAdapter()) {
@@ -4092,6 +4108,12 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
   }
 
   this->StateSnapshot.SetPolicy(id, status);
+
+  // Handle CMAKE_PARENT_LIST_FILE for CMP0198 policy changes
+  if (id == cmPolicies::CMP0198) {
+    this->UpdateParentListFileVariable();
+  }
+
   return true;
 }
 
@@ -4144,6 +4166,21 @@ bool cmMakefile::SetPolicyVersion(std::string const& version_min,
                                         cmPolicies::WarnCompat::On);
 }
 
+void cmMakefile::UpdateParentListFileVariable()
+{
+  // CMP0198 determines CMAKE_PARENT_LIST_FILE behavior in CMakeLists.txt
+  if (this->GetPolicyStatus(cmPolicies::CMP0198) == cmPolicies::NEW) {
+    this->RemoveDefinition(kCMAKE_PARENT_LIST_FILE);
+  } else {
+    std::string currentSourceDir =
+      this->StateSnapshot.GetDirectory().GetCurrentSource();
+    std::string currentStart =
+      this->GetCMakeInstance()->GetCMakeListFile(currentSourceDir);
+
+    this->AddDefinition(kCMAKE_PARENT_LIST_FILE, currentStart);
+  }
+}
+
 cmMakefile::VariablePushPop::VariablePushPop(cmMakefile* m)
   : Makefile(m)
 {

+ 3 - 0
Source/cmMakefile.h

@@ -391,6 +391,9 @@ public:
   void RecordPolicies(cmPolicies::PolicyMap& pm) const;
   //@}
 
+  /** Update CMAKE_PARENT_LIST_FILE based on CMP0198 policy status.  */
+  void UpdateParentListFileVariable();
+
   /** Helper class to push and pop policies automatically.  */
   class PolicyPushPop
   {

+ 3 - 0
Source/cmPolicies.h

@@ -589,6 +589,9 @@ class cmMakefile;
          "The CMakeDetermineVSServicePack module is removed.", 4, 1, 0, WARN) \
   SELECT(POLICY, CMP0197,                                                     \
          "MSVC link -machine: flag is not in CMAKE_*_LINKER_FLAGS.", 4, 1, 0, \
+         WARN)                                                                \
+  SELECT(POLICY, CMP0198,                                                     \
+         "CMAKE_PARENT_LIST_FILE is not defined in CMakeLists.txt.", 4, 2, 0, \
          WARN)
 
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)

+ 6 - 0
Tests/RunCMake/include/CMP0198-NEW-root-stdout.txt

@@ -0,0 +1,6 @@
+-- CMakeLists\.txt: ''.*
+-- CMakeLists\.txt: ''
+-- ParentVariableRoot/include1\.cmake: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'
+-- ParentVariableRoot/include2\.cmake: '[^']*/Tests/RunCMake/include/ParentVariableRoot/include1\.cmake'
+-- ParentVariableRoot/include1\.cmake: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'
+-- CMakeLists\.txt: ''

+ 7 - 0
Tests/RunCMake/include/CMP0198-NEW-subdir-stdout.txt

@@ -0,0 +1,7 @@
+-- ParentVariableSubDir/CMakeLists\.txt: ''
+-- ParentVariableSubDir/include1\.cmake: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/CMakeLists\.txt'
+-- ParentVariableSubDir/Inc/include2.cmake: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/include1\.cmake'
+-- ParentVariableSubDir/include1\.cmake: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/CMakeLists\.txt'
+-- ParentVariableSubDir/Inc/CMakeLists\.txt: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/include1\.cmake'
+-- ParentVariableSubDir/include1\.cmake: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/CMakeLists\.txt'
+-- ParentVariableSubDir/CMakeLists\.txt: ''

+ 2 - 0
Tests/RunCMake/include/CMP0198-NEW-subdir.cmake

@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0198 NEW)
+add_subdirectory(ParentVariableSubDir)

+ 6 - 0
Tests/RunCMake/include/CMP0198-OLD-root-stdout.txt

@@ -0,0 +1,6 @@
+-- CMakeLists\.txt: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'.*
+-- CMakeLists\.txt: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'
+-- ParentVariableRoot/include1\.cmake: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'
+-- ParentVariableRoot/include2\.cmake: '[^']*/Tests/RunCMake/include/ParentVariableRoot/include1\.cmake'
+-- ParentVariableRoot/include1\.cmake: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'
+-- CMakeLists\.txt: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'

+ 7 - 0
Tests/RunCMake/include/CMP0198-OLD-subdir-stdout.txt

@@ -0,0 +1,7 @@
+-- ParentVariableSubDir/CMakeLists\.txt: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/CMakeLists\.txt'
+-- ParentVariableSubDir/include1\.cmake: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/CMakeLists\.txt'
+-- ParentVariableSubDir/Inc/include2.cmake: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/include1\.cmake'
+-- ParentVariableSubDir/include1\.cmake: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/CMakeLists\.txt'
+-- ParentVariableSubDir/Inc/CMakeLists\.txt: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/include1\.cmake'
+-- ParentVariableSubDir/include1\.cmake: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/CMakeLists\.txt'
+-- ParentVariableSubDir/CMakeLists\.txt: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/CMakeLists\.txt'

+ 2 - 0
Tests/RunCMake/include/CMP0198-OLD-subdir.cmake

@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0198 OLD)
+add_subdirectory(ParentVariableSubDir)

+ 6 - 0
Tests/RunCMake/include/CMP0198-WARN-root-stdout.txt

@@ -0,0 +1,6 @@
+-- CMakeLists\.txt: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'.*
+-- CMakeLists\.txt: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'
+-- ParentVariableRoot/include1\.cmake: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'
+-- ParentVariableRoot/include2\.cmake: '[^']*/Tests/RunCMake/include/ParentVariableRoot/include1\.cmake'
+-- ParentVariableRoot/include1\.cmake: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'
+-- CMakeLists\.txt: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'

+ 7 - 0
Tests/RunCMake/include/CMP0198-WARN-subdir-stdout.txt

@@ -0,0 +1,7 @@
+-- ParentVariableSubDir/CMakeLists\.txt: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/CMakeLists\.txt'
+-- ParentVariableSubDir/include1\.cmake: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/CMakeLists\.txt'
+-- ParentVariableSubDir/Inc/include2.cmake: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/include1\.cmake'
+-- ParentVariableSubDir/include1\.cmake: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/CMakeLists\.txt'
+-- ParentVariableSubDir/Inc/CMakeLists\.txt: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/include1\.cmake'
+-- ParentVariableSubDir/include1\.cmake: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/CMakeLists\.txt'
+-- ParentVariableSubDir/CMakeLists\.txt: '[^']*/Tests/RunCMake/include/ParentVariableSubDir/CMakeLists\.txt'

+ 3 - 0
Tests/RunCMake/include/CMP0198-WARN-subdir.cmake

@@ -0,0 +1,3 @@
+# Test CMP0198 WARN behavior with subdirectory: should behave like OLD (no warning issued)
+# Do not set CMP0198 policy explicitly
+add_subdirectory(ParentVariableSubDir)

+ 6 - 0
Tests/RunCMake/include/CMP0198-implicit-NEW-root-stdout.txt

@@ -0,0 +1,6 @@
+-- CMakeLists\.txt: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'.*
+-- CMakeLists\.txt: ''
+-- ParentVariableRoot/include1\.cmake: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'
+-- ParentVariableRoot/include2\.cmake: '[^']*/Tests/RunCMake/include/ParentVariableRoot/include1\.cmake'
+-- ParentVariableRoot/include1\.cmake: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'
+-- CMakeLists\.txt: ''

+ 22 - 2
Tests/RunCMake/include/CMakeLists.txt

@@ -1,9 +1,29 @@
-cmake_minimum_required(VERSION 3.10)
+set(root_test OFF)
+if(RunCMake_TEST STREQUAL "ParentVariableRoot" OR
+   RunCMake_TEST STREQUAL "CMP0198-NEW-root" OR
+   RunCMake_TEST STREQUAL "CMP0198-implicit-NEW-root" OR
+   RunCMake_TEST STREQUAL "CMP0198-OLD-root" OR
+   RunCMake_TEST STREQUAL "CMP0198-WARN-root")
+  set(root_test ON)
+endif()
+
+if(root_test)
+  message(STATUS "CMakeLists.txt: '${CMAKE_PARENT_LIST_FILE}'")
+endif()
+
+if(RunCMake_TEST STREQUAL "CMP0198-implicit-NEW-root")
+  cmake_minimum_required(VERSION 4.1...4.2)
+else()
+  cmake_minimum_required(VERSION 3.10)
+endif()
+
 project(${RunCMake_TEST} NONE)
-if(RunCMake_TEST STREQUAL "ParentVariableRoot")
+
+if(root_test)
   message(STATUS "CMakeLists.txt: '${CMAKE_PARENT_LIST_FILE}'")
   include(ParentVariableRoot/include1.cmake)
   message(STATUS "CMakeLists.txt: '${CMAKE_PARENT_LIST_FILE}'")
   return()
 endif()
+
 include(${RunCMake_TEST}.cmake)

+ 1 - 0
Tests/RunCMake/include/ParentVariableRoot-stdout.txt

@@ -1,3 +1,4 @@
+-- CMakeLists\.txt: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'.*
 -- CMakeLists\.txt: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'
 -- ParentVariableRoot/include1\.cmake: '[^']*/Tests/RunCMake/include/CMakeLists\.txt'
 -- ParentVariableRoot/include2\.cmake: '[^']*/Tests/RunCMake/include/ParentVariableRoot/include1\.cmake'

+ 18 - 0
Tests/RunCMake/include/RunCMakeTest.cmake

@@ -43,3 +43,21 @@ run_cmake(CMP0196-OLD)
 run_cmake(CMP0196-WARN)
 run_cmake(CMP0196-NEW-name)
 run_cmake(CMP0196-NEW-path)
+
+# Warn should silently behave like OLD
+# Test old with implicit and explicit policy setting
+run_cmake(CMP0198-OLD-root)
+run_cmake(CMP0198-WARN-root)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_POLICY_DEFAULT_CMP0198=OLD")
+run_cmake(CMP0198-OLD-root)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_POLICY_DEFAULT_CMP0198=NEW")
+run_cmake(CMP0198-NEW-root)
+unset(RunCMake_TEST_OPTIONS)
+run_cmake(CMP0198-implicit-NEW-root)
+run_cmake(CMP0198-OLD-subdir)
+run_cmake(CMP0198-WARN-subdir)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_POLICY_DEFAULT_CMP0198=OLD")
+run_cmake(CMP0198-OLD-subdir)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_POLICY_DEFAULT_CMP0198=NEW")
+run_cmake(CMP0198-NEW-subdir)
+unset(RunCMake_TEST_OPTIONS)