1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-15 20:46:37 +08:00

project: Revert changes to VERSION handling

In c4d12d7d we changed how the project command handles various variables
and made the behavior consistent across all variables controlled by
the project command. The conditions under which project() modifies the
various VERSION variables are non-intuitive, but can be observed as
side-effects.

Because this behavior is observable, it requires a policy to be changed.
This commit reverts to the previous behavior until a policy is added
and adds a test for that behavior.

Fixes: #27142
This commit is contained in:
Vito Gamberini
2025-09-01 18:08:06 -04:00
parent ba8c4a15f1
commit aa16b8eb9a
5 changed files with 83 additions and 10 deletions

View File

@@ -202,6 +202,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,
std::string version_string;
std::array<std::string, MAX_VERSION_COMPONENTS> version_components;
bool has_version = prArgs.Version.has_value();
if (prArgs.Version) {
if (!vx.find(*prArgs.Version)) {
std::string e =
@@ -267,11 +268,40 @@ bool cmProjectCommand(std::vector<std::string> const& args,
TopLevelCMakeVarCondSet(mf, cmStrCat("CMAKE_PROJECT_"_s, var), val);
};
createVariables("VERSION"_s, version_string);
createVariables("VERSION_MAJOR"_s, version_components[0]);
createVariables("VERSION_MINOR"_s, version_components[1]);
createVariables("VERSION_PATCH"_s, version_components[2]);
createVariables("VERSION_TWEAK"_s, version_components[3]);
// Note, this intentionally doesn't touch cache variables as the legacy
// behavior did not modify cache
auto checkAndClearVariables = [&](cm::string_view var) {
std::vector<std::string> vv = { "PROJECT_", cmStrCat(projectName, "_") };
if (mf.IsRootMakefile()) {
vv.push_back("CMAKE_PROJECT_");
}
for (std::string const& prefix : vv) {
std::string def = cmStrCat(prefix, var);
if (!mf.GetDefinition(def).IsEmpty()) {
mf.AddDefinition(def, "");
}
}
};
// TODO: We should treat VERSION the same as all other project variables, but
// setting it to empty string unconditionally causes various behavior
// changes. It needs a policy. For now, maintain the old behavior and add a
// policy in a future release.
if (has_version) {
createVariables("VERSION"_s, version_string);
createVariables("VERSION_MAJOR"_s, version_components[0]);
createVariables("VERSION_MINOR"_s, version_components[1]);
createVariables("VERSION_PATCH"_s, version_components[2]);
createVariables("VERSION_TWEAK"_s, version_components[3]);
} else {
checkAndClearVariables("VERSION"_s);
checkAndClearVariables("VERSION_MAJOR"_s);
checkAndClearVariables("VERSION_MINOR"_s);
checkAndClearVariables("VERSION_PATCH"_s);
checkAndClearVariables("VERSION_TWEAK"_s);
}
createVariables("COMPAT_VERSION"_s, prArgs.CompatVersion.value_or(""));
createVariables("DESCRIPTION"_s, prArgs.Description.value_or(""));
createVariables("HOMEPAGE_URL"_s, prArgs.HomepageURL.value_or(""));

View File

@@ -14,11 +14,15 @@ function(expect_empty SUFFIX)
endfunction()
project(Omissions LANGUAGES)
expect_empty(VERSION)
expect_empty(VERSION_MAJOR)
expect_empty(VERSION_MINOR)
expect_empty(VERSION_PATCH)
expect_empty(VERSION_TWEAK)
# TODO: Test these when a policy is in place to handle projects expecting
# legacy handling of the version variables
# expect_empty(VERSION)
# expect_empty(VERSION_MAJOR)
# expect_empty(VERSION_MINOR)
# expect_empty(VERSION_PATCH)
# expect_empty(VERSION_TWEAK)
expect_empty(COMPAT_VERSION)
expect_empty(DESCRIPTION)
expect_empty(HOMEPAGE_URL)

View File

@@ -48,6 +48,7 @@ run_cmake(ProjectIsTopLevelMultiple)
run_cmake(ProjectIsTopLevelSubdirectory)
run_cmake(ProjectTwice)
run_cmake(Omissions)
run_cmake(VersionAbsent)
run_cmake(VersionAndLanguagesEmpty)
run_cmake(VersionEmpty)
run_cmake(VersionInvalid)

View File

@@ -0,0 +1,14 @@
# TODO: In the future this should be a policy test, but for now verify version
# variables remain undefined for various configurations.
project(NoVersion LANGUAGES NONE)
foreach(pre "NoVersion_" "PROJECT_" "CMAKE_PROJECT_")
foreach(post "" "_MAJOR" "_MINOR" "_PATCH" "_TWEAK")
if(DEFINED ${pre}VERSION${post})
message(SEND_ERROR "${pre}VERSION${post} is defined when no project version was provided")
endif()
endforeach()
endforeach()
add_subdirectory(VersionSubdir)

View File

@@ -0,0 +1,24 @@
project(WithVersion LANGUAGES NONE VERSION 1.1.1.1)
project(SubdirNoVersion LANGUAGES NONE)
foreach(post "" "_MAJOR" "_MINOR" "_PATCH" "_TWEAK")
if(NOT DEFINED PROJECT_VERSION${post})
message(SEND_ERROR "PROJECT_VERSION${post} is not defined when previous project version was provided")
continue()
endif()
if(NOT PROJECT_VERSION${post} STREQUAL "")
message(SEND_ERROR "PROJECT_VERSION${post} has value '${PROJECT_VERSION${post}}' when empty string is expected")
endif()
endforeach()
if(NOT CMAKE_PROJECT_VERSION STREQUAL "1.1.1.1")
message(SEND_ERROR "CMAKE_PROJECT_VERSION has value '${CMAKE_PROJECT_VERION}' when 1.1.1.1 is expected")
endif()
foreach(post "_MAJOR" "_MINOR" "_PATCH" "_TWEAK")
if(NOT CMAKE_PROJECT_VERSION${post} STREQUAL "1")
message(SEND_ERROR "CMAKE_PROJECT_VERSION${post} has value '${CMAKE_PROJECT_VERSION${post}}' when 1 is expected")
endif()
endforeach()