summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/command/project.rst6
-rw-r--r--Source/cmProjectCommand.cxx33
-rw-r--r--Tests/RunCMake/project/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/project/SameProjectVarsSubdir-stdout.txt9
-rw-r--r--Tests/RunCMake/project/SameProjectVarsSubdir.cmake17
-rw-r--r--Tests/RunCMake/project/subdir1/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/project/subdir2/CMakeLists.txt12
7 files changed, 67 insertions, 12 deletions
diff --git a/Help/command/project.rst b/Help/command/project.rst
index 0188291..08694fd 100644
--- a/Help/command/project.rst
+++ b/Help/command/project.rst
@@ -44,6 +44,12 @@ 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.4
+ If the variables ``<PROJECT-NAME>_SOURCE_DIR``,
+ ``<PROJECT-NAME>_BINARY_DIR``, or ``<PROJECT-NAME>_IS_TOP_LEVEL`` are
+ already set as non-cache variables when ``project(<PROJECT-NAME> ...)``
+ is called, the ``project()`` command will overwrite the previous values.
+
Options
^^^^^^^
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index 13070dd..da92ea6 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -8,6 +8,8 @@
#include <limits>
#include <utility>
+#include <cmext/string_view>
+
#include "cmsys/RegularExpression.hxx"
#include "cmExecutionStatus.h"
@@ -56,17 +58,21 @@ bool cmProjectCommand(std::vector<std::string> const& args,
mf.SetProjectName(projectName);
- mf.AddCacheDefinition(projectName + "_BINARY_DIR",
- mf.GetCurrentBinaryDirectory(),
+ std::string varName = cmStrCat(projectName, "_BINARY_DIR"_s);
+ bool nonCacheVarAlreadySet = mf.IsDefinitionSet(varName);
+ mf.AddCacheDefinition(varName, mf.GetCurrentBinaryDirectory(),
"Value Computed by CMake", cmStateEnums::STATIC);
- mf.AddDefinition(projectName + "_BINARY_DIR",
- mf.GetCurrentBinaryDirectory());
+ if (nonCacheVarAlreadySet) {
+ mf.AddDefinition(varName, mf.GetCurrentBinaryDirectory());
+ }
- mf.AddCacheDefinition(projectName + "_SOURCE_DIR",
- mf.GetCurrentSourceDirectory(),
+ varName = cmStrCat(projectName, "_SOURCE_DIR"_s);
+ nonCacheVarAlreadySet = mf.IsDefinitionSet(varName);
+ mf.AddCacheDefinition(varName, mf.GetCurrentSourceDirectory(),
"Value Computed by CMake", cmStateEnums::STATIC);
- mf.AddDefinition(projectName + "_SOURCE_DIR",
- mf.GetCurrentSourceDirectory());
+ if (nonCacheVarAlreadySet) {
+ mf.AddDefinition(varName, mf.GetCurrentSourceDirectory());
+ }
mf.AddDefinition("PROJECT_BINARY_DIR", mf.GetCurrentBinaryDirectory());
mf.AddDefinition("PROJECT_SOURCE_DIR", mf.GetCurrentSourceDirectory());
@@ -74,11 +80,14 @@ bool cmProjectCommand(std::vector<std::string> 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",
+
+ varName = cmStrCat(projectName, "_IS_TOP_LEVEL"_s);
+ nonCacheVarAlreadySet = mf.IsDefinitionSet(varName);
+ mf.AddCacheDefinition(varName, mf.IsRootMakefile() ? "ON" : "OFF",
"Value Computed by CMake", cmStateEnums::STATIC);
- mf.AddDefinition(projectName + "_IS_TOP_LEVEL",
- mf.IsRootMakefile() ? "ON" : "OFF");
+ if (nonCacheVarAlreadySet) {
+ mf.AddDefinition(varName, mf.IsRootMakefile() ? "ON" : "OFF");
+ }
// Set the CMAKE_PROJECT_NAME variable to be the highest-level
// project name in the tree. If there are two project commands
diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake
index 9c49281..e6e1bdb 100644
--- a/Tests/RunCMake/project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/project/RunCMakeTest.cmake
@@ -45,6 +45,7 @@ run_cmake(ProjectIsTopLevel)
run_cmake(ProjectIsTopLevelMultiple)
run_cmake(ProjectIsTopLevelSubdirectory)
run_cmake(ProjectTwice)
+run_cmake(SameProjectVarsSubdir)
run_cmake(VersionAndLanguagesEmpty)
run_cmake(VersionEmpty)
run_cmake(VersionInvalid)
diff --git a/Tests/RunCMake/project/SameProjectVarsSubdir-stdout.txt b/Tests/RunCMake/project/SameProjectVarsSubdir-stdout.txt
new file mode 100644
index 0000000..73dadfd
--- /dev/null
+++ b/Tests/RunCMake/project/SameProjectVarsSubdir-stdout.txt
@@ -0,0 +1,9 @@
+(-- )? 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/SameProjectVarsSubdir.cmake b/Tests/RunCMake/project/SameProjectVarsSubdir.cmake
new file mode 100644
index 0000000..36a7960
--- /dev/null
+++ b/Tests/RunCMake/project/SameProjectVarsSubdir.cmake
@@ -0,0 +1,17 @@
+add_subdirectory(subdir1)
+
+# Simulate a situation that FetchContent_MakeAvailable() used to be able to
+# create, but that should no longer be possible. If depname_SOURCE_DIR and
+# depname_BINARY_DIR variables are defined as non-cache variables before the
+# project(depname) call, those non-cache variables used to prevent project()
+# from setting those variables itself due to CMP0126 (if set to NEW). This only
+# showed up if the project(depname) call was not in the dependency's top level
+# CMakeLists.txt file, but rather in a subdirectory (googletest is one example
+# that used to do this). Since CMake 3.30.3, the dependency's project() call
+# should set non-cache variables that will make the variable values visible
+# and avoid any masking from variables set before the project() call. We want
+# to verify this 3.30.3+ behavior here and in subdir2.
+set(sub2proj_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+set(sub2proj_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+
+add_subdirectory(subdir2)
diff --git a/Tests/RunCMake/project/subdir1/CMakeLists.txt b/Tests/RunCMake/project/subdir1/CMakeLists.txt
new file mode 100644
index 0000000..d6be229
--- /dev/null
+++ b/Tests/RunCMake/project/subdir1/CMakeLists.txt
@@ -0,0 +1 @@
+project(${RunCMake_TEST} LANGUAGES NONE)
diff --git a/Tests/RunCMake/project/subdir2/CMakeLists.txt b/Tests/RunCMake/project/subdir2/CMakeLists.txt
new file mode 100644
index 0000000..c28e0c9
--- /dev/null
+++ b/Tests/RunCMake/project/subdir2/CMakeLists.txt
@@ -0,0 +1,12 @@
+message(STATUS
+ " ${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}"
+)
+
+project(sub2proj LANGUAGES NONE)
+
+message(STATUS
+ " sub2proj_SOURCE_DIR = ${sub2proj_SOURCE_DIR}\n"
+ " sub2proj_BINARY_DIR = ${sub2proj_BINARY_DIR}"
+)