diff options
-rw-r--r-- | Help/command/project.rst | 6 | ||||
-rw-r--r-- | Source/cmProjectCommand.cxx | 33 | ||||
-rw-r--r-- | Tests/RunCMake/project/RunCMakeTest.cmake | 1 | ||||
-rw-r--r-- | Tests/RunCMake/project/SameProjectVarsSubdir-stdout.txt | 9 | ||||
-rw-r--r-- | Tests/RunCMake/project/SameProjectVarsSubdir.cmake | 17 | ||||
-rw-r--r-- | Tests/RunCMake/project/subdir1/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/project/subdir2/CMakeLists.txt | 12 |
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}" +) |