diff --git a/Help/command/project.rst b/Help/command/project.rst index 14a553ad3c9..b1c7dbf3188 100644 --- a/Help/command/project.rst +++ b/Help/command/project.rst @@ -44,11 +44,27 @@ Projects should not rely on ``_SOURCE_DIR`` or ``_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 + ``_SOURCE_DIR``, ``_BINARY_DIR``, and + ``_IS_TOP_LEVEL`` are always set as non-cache variables by + ``project( ...)``. + .. versionchanged:: 3.30.4 - If the variables ``_SOURCE_DIR``, - ``_BINARY_DIR``, or ``_IS_TOP_LEVEL`` are - already set as non-cache variables when ``project( ...)`` - is called, the ``project()`` command will overwrite the previous values. + The variables ``_SOURCE_DIR``, ``_BINARY_DIR``, + and ``_IS_TOP_LEVEL`` are only set as non-cache variables if + they are already set as cache or non-cache variables when + ``project( ...)`` 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 ``_SOURCE_DIR``, ``_BINARY_DIR``, + and ``_IS_TOP_LEVEL`` are only set as non-cache variables if + they are already set as non-cache variables when + ``project( ...)`` 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. Options ^^^^^^^ diff --git a/Help/release/3.30.rst b/Help/release/3.30.rst index 4cd2b442eda..32345bef73b 100644 --- a/Help/release/3.30.rst +++ b/Help/release/3.30.rst @@ -277,7 +277,24 @@ Changes made since CMake 3.30.0 include the following. * The :command:`project()` command now sets :variable:`_SOURCE_DIR`, :variable:`_BINARY_DIR`, and :variable:`_IS_TOP_LEVEL` as normal variables only if they - are already set as normal variables when :command:`project` is invoked. - Cache entries by the same names are always set as before. + are already set as cache or non-cache variables when :command:`project` is + invoked. Cache entries by the same names are always set as before. This refines 3.30.3's behavior change to restore behavior of nested - directories that call :command:`project` with the same project name. + directories that call :command:`project` with the same project name, + but the implementation in this release is flawed (this release note has + been retoractively updated). It can result in different behavior between + the first and subsequent runs. Do not use CMake 3.30.4 if your project + contains nested calls to :command:`project` with the same project name + and you use these variables. + +3.30.5 +------ + +* The :command:`project()` command now sets + :variable:`_SOURCE_DIR`, :variable:`_BINARY_DIR`, + and :variable:`_IS_TOP_LEVEL` as non-cache variables only if + they are already set as non-cache variables when :command:`project` is + invoked. Cache entries by the same names are always set as before. + This refines 3.30.3's behavior change to restore behavior of nested + directories that call :command:`project` with the same project name, + and it addresses the bug in the implementation introduced in 3.30.4. diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a3aaaacfb2e..f76aec40c48 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 30) -set(CMake_VERSION_PATCH 4) +set(CMake_VERSION_PATCH 5) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index da92ea679dc..90c10423853 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -59,7 +59,7 @@ bool cmProjectCommand(std::vector const& args, mf.SetProjectName(projectName); std::string varName = cmStrCat(projectName, "_BINARY_DIR"_s); - bool nonCacheVarAlreadySet = mf.IsDefinitionSet(varName); + bool nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName); mf.AddCacheDefinition(varName, mf.GetCurrentBinaryDirectory(), "Value Computed by CMake", cmStateEnums::STATIC); if (nonCacheVarAlreadySet) { @@ -67,7 +67,7 @@ bool cmProjectCommand(std::vector const& args, } varName = cmStrCat(projectName, "_SOURCE_DIR"_s); - nonCacheVarAlreadySet = mf.IsDefinitionSet(varName); + nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName); mf.AddCacheDefinition(varName, mf.GetCurrentSourceDirectory(), "Value Computed by CMake", cmStateEnums::STATIC); if (nonCacheVarAlreadySet) { @@ -82,7 +82,7 @@ bool cmProjectCommand(std::vector const& args, mf.AddDefinitionBool("PROJECT_IS_TOP_LEVEL", mf.IsRootMakefile()); varName = cmStrCat(projectName, "_IS_TOP_LEVEL"_s); - nonCacheVarAlreadySet = mf.IsDefinitionSet(varName); + nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName); mf.AddCacheDefinition(varName, mf.IsRootMakefile() ? "ON" : "OFF", "Value Computed by CMake", cmStateEnums::STATIC); if (nonCacheVarAlreadySet) { diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake index e6e1bdb0cd2..ed4b8ba5d11 100644 --- a/Tests/RunCMake/project/RunCMakeTest.cmake +++ b/Tests/RunCMake/project/RunCMakeTest.cmake @@ -45,7 +45,6 @@ run_cmake(ProjectIsTopLevel) run_cmake(ProjectIsTopLevelMultiple) run_cmake(ProjectIsTopLevelSubdirectory) run_cmake(ProjectTwice) -run_cmake(SameProjectVarsSubdir) run_cmake(VersionAndLanguagesEmpty) run_cmake(VersionEmpty) run_cmake(VersionInvalid) @@ -63,4 +62,10 @@ run_cmake(CMP0096-WARN) run_cmake(CMP0096-OLD) run_cmake(CMP0096-NEW) +# We deliberately run these twice to verify behavior of the second CMake run +run_cmake(SameProjectVarsSubdir) +set(RunCMake_TEST_NO_CLEAN 1) +run_cmake(SameProjectVarsSubdir) +set(RunCMake_TEST_NO_CLEAN 0) + run_cmake(NoMinimumRequired)