summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCraig Scott <craig.scott@crascit.com>2024-10-06 08:59:20 (GMT)
committerBrad King <brad.king@kitware.com>2024-10-08 14:07:11 (GMT)
commite5a9ccbcc88ab252cf75f005227cdeb808299266 (patch)
tree6b65eda6b71eead00d56875a3681913c2dbeb15d
parentddf1d2944fe53b0fb0be79621c53d2d235fce07b (diff)
downloadCMake-e5a9ccbcc88ab252cf75f005227cdeb808299266.zip
CMake-e5a9ccbcc88ab252cf75f005227cdeb808299266.tar.gz
CMake-e5a9ccbcc88ab252cf75f005227cdeb808299266.tar.bz2
project: Always set <PROJECT-NAME>_* as normal variables
Re-introduce the behavior originally introduced in CMake 3.30.3 by commit c1ece78d11 (project: non cache <project> prefix variables are also created, 2024-08-27, v3.30.3~2^2), but this time with a policy for compatibility. Issue: #25714 Issue: #26243
-rw-r--r--Help/command/project.rst31
-rw-r--r--Help/manual/cmake-policies.7.rst1
-rw-r--r--Help/policy/CMP0180.rst36
-rw-r--r--Help/release/dev/project-vars-policy.rst7
-rw-r--r--Source/cmPolicies.h5
-rw-r--r--Source/cmProjectCommand.cxx8
-rw-r--r--Tests/RunCMake/project/CMP0180-NEW-stdout.txt16
-rw-r--r--Tests/RunCMake/project/CMP0180-NEW.cmake2
-rw-r--r--Tests/RunCMake/project/CMP0180-OLD-stdout.txt16
-rw-r--r--Tests/RunCMake/project/CMP0180-OLD.cmake2
-rw-r--r--Tests/RunCMake/project/CMP0180.cmake (renamed from Tests/RunCMake/project/SameProjectVarsSubdir.cmake)0
-rw-r--r--Tests/RunCMake/project/CMakeLists.txt6
-rw-r--r--Tests/RunCMake/project/RunCMakeTest.cmake8
-rw-r--r--Tests/RunCMake/project/SameProjectVarsSubdir-stdout.txt9
-rw-r--r--Tests/RunCMake/project/subdir1/CMakeLists.txt7
-rw-r--r--Tests/RunCMake/project/subdir2/CMakeLists.txt1
16 files changed, 120 insertions, 35 deletions
diff --git a/Help/command/project.rst b/Help/command/project.rst
index d220b83..b42a034 100644
--- a/Help/command/project.rst
+++ b/Help/command/project.rst
@@ -44,27 +44,18 @@ Projects should not rely on ``<PROJECT-NAME>_SOURCE_DIR`` or
``<PROJECT-NAME>_BINARY_DIR`` holding a particular value outside of the scope
of the call to ``project()`` or one of its child scopes.
-.. versionchanged:: 3.30.3
+.. versionchanged:: 3.30
``<PROJECT-NAME>_SOURCE_DIR``, ``<PROJECT-NAME>_BINARY_DIR``, and
- ``<PROJECT-NAME>_IS_TOP_LEVEL`` are always set as non-cache variables by
- ``project(<PROJECT-NAME> ...)``.
-
-.. versionchanged:: 3.30.4
- The variables ``<PROJECT-NAME>_SOURCE_DIR``, ``<PROJECT-NAME>_BINARY_DIR``,
- and ``<PROJECT-NAME>_IS_TOP_LEVEL`` are only set as non-cache variables if
- they are already set as cache or non-cache variables when
- ``project(<PROJECT-NAME> ...)`` is called.
- Note that this logic is flawed, as it can result in different behavior
- between the first and subsequent runs because cache variables won't exist
- on the first run, but they will on subsequent runs.
-
-.. versionchanged:: 3.30.5
- The variables ``<PROJECT-NAME>_SOURCE_DIR``, ``<PROJECT-NAME>_BINARY_DIR``,
- and ``<PROJECT-NAME>_IS_TOP_LEVEL`` are only set as non-cache variables if
- they are already set as non-cache variables when
- ``project(<PROJECT-NAME> ...)`` is called.
- Unlike the flawed behavior of 3.30.4, non-cache variables will not be set
- if only cache variables of the same name are set.
+ ``<PROJECT-NAME>_IS_TOP_LEVEL``, if already set as normal variables when
+ ``project(<PROJECT-NAME> ...)`` is called, are updated by the call.
+ Cache entries by the same names are always set as before.
+ See release notes for 3.30.3, 3.30.4, and 3.30.5 for details.
+
+.. versionchanged:: 3.31
+ ``<PROJECT-NAME>_SOURCE_DIR``, ``<PROJECT-NAME>_BINARY_DIR``, and
+ ``<PROJECT-NAME>_IS_TOP_LEVEL`` are always set as normal variables by
+ ``project(<PROJECT-NAME> ...)``. See policy :policy:`CMP0180`.
+ Cache entries by the same names are always set as before.
Options
^^^^^^^
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index c6fcc1f..c62fb48 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -57,6 +57,7 @@ Policies Introduced by CMake 3.31
.. toctree::
:maxdepth: 1
+ CMP0180: project() always sets <PROJECT-NAME>_* as normal variables. </policy/CMP0180>
CMP0179: De-duplication of static libraries on link lines keeps first occurrence. </policy/CMP0179>
CMP0178: Test command lines preserve empty arguments. </policy/CMP0178>
CMP0177: install() DESTINATION paths are normalized. </policy/CMP0177>
diff --git a/Help/policy/CMP0180.rst b/Help/policy/CMP0180.rst
new file mode 100644
index 0000000..f69c0bc
--- /dev/null
+++ b/Help/policy/CMP0180.rst
@@ -0,0 +1,36 @@
+CMP0180
+-------
+
+.. versionadded:: 3.31
+
+:command:`project` always sets ``<PROJECT-NAME>_*`` as normal variables.
+
+In CMake 3.29 and below, the :command:`project` command set
+:variable:`<PROJECT-NAME>_SOURCE_DIR`, :variable:`<PROJECT-NAME>_BINARY_DIR`,
+and :variable:`<PROJECT-NAME>_IS_TOP_LEVEL` as cache entries, but not as
+normal variables. CMake 3.30 started setting them as normal variables,
+but only if they are already set as normal variables. This was needed to
+preserve support for some :module:`FetchContent` use cases under policy
+:policy:`CMP0169`'s NEW behavior, while also preserving behavior of nested
+directories that call :command:`project` with the same project name.
+See release notes for 3.30.3, 3.30.4, and 3.30.5 for details.
+
+CMake 3.31 and later prefer to always set ``<PROJECT-NAME>_SOURCE_DIR``,
+``<PROJECT-NAME>_BINARY_DIR``, and ``<PROJECT-NAME>_IS_TOP_LEVEL``, as both
+cache entries and normal variables, regardless of what cache or normal
+variables already exist. This policy provides compatibility for projects
+that have not been updated to expect this behavior.
+
+The ``OLD`` behavior for this policy will only set normal variables for
+``<PROJECT-NAME>_SOURCE_DIR``, ``<PROJECT-NAME>_BINARY_DIR``, and
+``<PROJECT-NAME>_IS_TOP_LEVEL`` if there is already a normal variable by that
+name when :command:`project` is called.
+The ``NEW`` behavior for this policy will always set normal variables for
+``<PROJECT-NAME>_SOURCE_DIR``, ``<PROJECT-NAME>_BINARY_DIR``, and
+``<PROJECT-NAME>_IS_TOP_LEVEL`` when :command:`project` is called.
+
+.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 3.31
+.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
+.. include:: STANDARD_ADVICE.txt
+
+.. include:: DEPRECATED.txt
diff --git a/Help/release/dev/project-vars-policy.rst b/Help/release/dev/project-vars-policy.rst
new file mode 100644
index 0000000..02287aa
--- /dev/null
+++ b/Help/release/dev/project-vars-policy.rst
@@ -0,0 +1,7 @@
+project-vars-policy
+-------------------
+
+* The :command:`project` command now always sets
+ :variable:`<PROJECT-NAME>_SOURCE_DIR`, :variable:`<PROJECT-NAME>_BINARY_DIR`,
+ and :variable:`<PROJECT-NAME>_IS_TOP_LEVEL` as both normal variables and
+ cache entries. See policy :policy:`CMP0180`.
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 55fce2e..dbd6ce8 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -549,7 +549,10 @@ class cmMakefile;
SELECT(POLICY, CMP0179, \
"De-duplication of static libraries on link lines keeps first " \
"occurrence.", \
- 3, 31, 0, cmPolicies::WARN)
+ 3, 31, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0180, \
+ "project() always sets <PROJECT-NAME>_* as normal variables.", 3, \
+ 31, 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/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index 90c1042..5d854cd 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -58,11 +58,13 @@ bool cmProjectCommand(std::vector<std::string> const& args,
mf.SetProjectName(projectName);
+ cmPolicies::PolicyStatus cmp0180 = mf.GetPolicyStatus(cmPolicies::CMP0180);
+
std::string varName = cmStrCat(projectName, "_BINARY_DIR"_s);
bool nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName);
mf.AddCacheDefinition(varName, mf.GetCurrentBinaryDirectory(),
"Value Computed by CMake", cmStateEnums::STATIC);
- if (nonCacheVarAlreadySet) {
+ if (cmp0180 == cmPolicies::NEW || nonCacheVarAlreadySet) {
mf.AddDefinition(varName, mf.GetCurrentBinaryDirectory());
}
@@ -70,7 +72,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,
nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName);
mf.AddCacheDefinition(varName, mf.GetCurrentSourceDirectory(),
"Value Computed by CMake", cmStateEnums::STATIC);
- if (nonCacheVarAlreadySet) {
+ if (cmp0180 == cmPolicies::NEW || nonCacheVarAlreadySet) {
mf.AddDefinition(varName, mf.GetCurrentSourceDirectory());
}
@@ -85,7 +87,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,
nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName);
mf.AddCacheDefinition(varName, mf.IsRootMakefile() ? "ON" : "OFF",
"Value Computed by CMake", cmStateEnums::STATIC);
- if (nonCacheVarAlreadySet) {
+ if (cmp0180 == cmPolicies::NEW || nonCacheVarAlreadySet) {
mf.AddDefinition(varName, mf.IsRootMakefile() ? "ON" : "OFF");
}
diff --git a/Tests/RunCMake/project/CMP0180-NEW-stdout.txt b/Tests/RunCMake/project/CMP0180-NEW-stdout.txt
new file mode 100644
index 0000000..34e5d49
--- /dev/null
+++ b/Tests/RunCMake/project/CMP0180-NEW-stdout.txt
@@ -0,0 +1,16 @@
+(-- )?From subdir1:
+ CMP0180-NEW_SOURCE_DIR = [^
+]+/project/subdir1
+ CMP0180-NEW_BINARY_DIR = [^
+]+/project/CMP0180-NEW-build/subdir1
+ CMP0180-NEW_IS_TOP_LEVEL = OFF
+(-- )?From subdir2:
+ CMP0180-NEW_SOURCE_DIR = [^
+]+/project
+ CMP0180-NEW_BINARY_DIR = [^
+]+/project/CMP0180-NEW-build
+ CMP0180-NEW_IS_TOP_LEVEL = ON
+(-- )? sub2proj_SOURCE_DIR = [^
+]+/project/subdir2
+ sub2proj_BINARY_DIR = [^
+]+/project/CMP0180-NEW-build/subdir2
diff --git a/Tests/RunCMake/project/CMP0180-NEW.cmake b/Tests/RunCMake/project/CMP0180-NEW.cmake
new file mode 100644
index 0000000..71f8b84
--- /dev/null
+++ b/Tests/RunCMake/project/CMP0180-NEW.cmake
@@ -0,0 +1,2 @@
+# CMP0180 is handled in CMakeLists.txt
+include(CMP0180.cmake)
diff --git a/Tests/RunCMake/project/CMP0180-OLD-stdout.txt b/Tests/RunCMake/project/CMP0180-OLD-stdout.txt
new file mode 100644
index 0000000..4ef55a4
--- /dev/null
+++ b/Tests/RunCMake/project/CMP0180-OLD-stdout.txt
@@ -0,0 +1,16 @@
+(-- )?From subdir1:
+ CMP0180-OLD_SOURCE_DIR = [^
+]+/project/subdir1
+ CMP0180-OLD_BINARY_DIR = [^
+]+/project/CMP0180-OLD-build/subdir1
+ CMP0180-OLD_IS_TOP_LEVEL = OFF
+(-- )?From subdir2:
+ CMP0180-OLD_SOURCE_DIR = [^
+]+/project/subdir1
+ CMP0180-OLD_BINARY_DIR = [^
+]+/project/CMP0180-OLD-build/subdir1
+ CMP0180-OLD_IS_TOP_LEVEL = OFF
+(-- )? sub2proj_SOURCE_DIR = [^
+]+/project/subdir2
+ sub2proj_BINARY_DIR = [^
+]+/project/CMP0180-OLD-build/subdir2
diff --git a/Tests/RunCMake/project/CMP0180-OLD.cmake b/Tests/RunCMake/project/CMP0180-OLD.cmake
new file mode 100644
index 0000000..71f8b84
--- /dev/null
+++ b/Tests/RunCMake/project/CMP0180-OLD.cmake
@@ -0,0 +1,2 @@
+# CMP0180 is handled in CMakeLists.txt
+include(CMP0180.cmake)
diff --git a/Tests/RunCMake/project/SameProjectVarsSubdir.cmake b/Tests/RunCMake/project/CMP0180.cmake
index 36a7960..36a7960 100644
--- a/Tests/RunCMake/project/SameProjectVarsSubdir.cmake
+++ b/Tests/RunCMake/project/CMP0180.cmake
diff --git a/Tests/RunCMake/project/CMakeLists.txt b/Tests/RunCMake/project/CMakeLists.txt
index 7ddd81d..28146c4 100644
--- a/Tests/RunCMake/project/CMakeLists.txt
+++ b/Tests/RunCMake/project/CMakeLists.txt
@@ -4,6 +4,12 @@ elseif(RunCMake_TEST MATCHES "^CMP0048")
cmake_minimum_required(VERSION 2.8.12) # old enough to not set CMP0048
else()
cmake_minimum_required(VERSION 3.10)
+ # CMP0180 needs to be set before the project() call for these tests
+ if("x${RunCMake_TEST}" STREQUAL "xCMP0180-NEW")
+ cmake_policy(SET CMP0180 NEW)
+ elseif("x${RunCMake_TEST}" STREQUAL "xCMP0180-OLD")
+ cmake_policy(SET CMP0180 OLD)
+ endif()
endif()
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake
index ed4b8ba..554cdff 100644
--- a/Tests/RunCMake/project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/project/RunCMakeTest.cmake
@@ -63,9 +63,13 @@ run_cmake(CMP0096-OLD)
run_cmake(CMP0096-NEW)
# We deliberately run these twice to verify behavior of the second CMake run
-run_cmake(SameProjectVarsSubdir)
+run_cmake(CMP0180-OLD)
set(RunCMake_TEST_NO_CLEAN 1)
-run_cmake(SameProjectVarsSubdir)
+run_cmake(CMP0180-OLD)
+set(RunCMake_TEST_NO_CLEAN 0)
+run_cmake(CMP0180-NEW)
+set(RunCMake_TEST_NO_CLEAN 1)
+run_cmake(CMP0180-NEW)
set(RunCMake_TEST_NO_CLEAN 0)
run_cmake(NoMinimumRequired)
diff --git a/Tests/RunCMake/project/SameProjectVarsSubdir-stdout.txt b/Tests/RunCMake/project/SameProjectVarsSubdir-stdout.txt
deleted file mode 100644
index 73dadfd..0000000
--- a/Tests/RunCMake/project/SameProjectVarsSubdir-stdout.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-(-- )? SameProjectVarsSubdir_SOURCE_DIR = [^
-]+/subdir1
- SameProjectVarsSubdir_BINARY_DIR = [^
-]+/subdir1
- SameProjectVarsSubdir_IS_TOP_LEVEL = OFF
-(-- )? sub2proj_SOURCE_DIR = [^
-]+/subdir2
- sub2proj_BINARY_DIR = [^
-]+/subdir2
diff --git a/Tests/RunCMake/project/subdir1/CMakeLists.txt b/Tests/RunCMake/project/subdir1/CMakeLists.txt
index d6be229..d2d3729 100644
--- a/Tests/RunCMake/project/subdir1/CMakeLists.txt
+++ b/Tests/RunCMake/project/subdir1/CMakeLists.txt
@@ -1 +1,8 @@
project(${RunCMake_TEST} LANGUAGES NONE)
+
+message(STATUS
+ "From subdir1:\n"
+ " ${RunCMake_TEST}_SOURCE_DIR = ${${RunCMake_TEST}_SOURCE_DIR}\n"
+ " ${RunCMake_TEST}_BINARY_DIR = ${${RunCMake_TEST}_BINARY_DIR}\n"
+ " ${RunCMake_TEST}_IS_TOP_LEVEL = ${${RunCMake_TEST}_IS_TOP_LEVEL}"
+)
diff --git a/Tests/RunCMake/project/subdir2/CMakeLists.txt b/Tests/RunCMake/project/subdir2/CMakeLists.txt
index c28e0c9..cab547f 100644
--- a/Tests/RunCMake/project/subdir2/CMakeLists.txt
+++ b/Tests/RunCMake/project/subdir2/CMakeLists.txt
@@ -1,4 +1,5 @@
message(STATUS
+ "From subdir2:\n"
" ${RunCMake_TEST}_SOURCE_DIR = ${${RunCMake_TEST}_SOURCE_DIR}\n"
" ${RunCMake_TEST}_BINARY_DIR = ${${RunCMake_TEST}_BINARY_DIR}\n"
" ${RunCMake_TEST}_IS_TOP_LEVEL = ${${RunCMake_TEST}_IS_TOP_LEVEL}"