project: add COMPAT_VERSION keyword

Fixes: #26893
This commit is contained in:
Vito Gamberini
2025-04-22 07:00:06 -04:00
parent 468270d8ac
commit 0138df29dc
25 changed files with 189 additions and 15 deletions

View File

@@ -17,6 +17,7 @@
#include "cmArgumentParser.h"
#include "cmArgumentParserTypes.h"
#include "cmExecutionStatus.h"
#include "cmExperimental.h"
#include "cmList.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
@@ -36,6 +37,7 @@ struct ProjectArguments : ArgumentParser::ParseResult
{
cm::optional<std::string> ProjectName;
cm::optional<std::string> Version;
cm::optional<std::string> CompatVersion;
cm::optional<std::string> Description;
cm::optional<std::string> HomepageURL;
cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Languages;
@@ -61,22 +63,30 @@ bool cmProjectCommand(std::vector<std::string> const& args,
std::vector<cm::string_view> missingValueKeywords;
std::vector<cm::string_view> parsedKeywords;
ProjectArguments prArgs;
ProjectArgumentParser{}
.BindKeywordMissingValue(missingValueKeywords)
ProjectArgumentParser parser;
parser.BindKeywordMissingValue(missingValueKeywords)
.BindParsedKeywords(parsedKeywords)
.Bind(0, prArgs.ProjectName)
.Bind("VERSION"_s, prArgs.Version)
.Bind("DESCRIPTION"_s, prArgs.Description)
.Bind("HOMEPAGE_URL"_s, prArgs.HomepageURL)
.Bind("LANGUAGES"_s, prArgs.Languages)
.Parse(args, &unparsedArgs, 0);
.Bind("LANGUAGES"_s, prArgs.Languages);
cmMakefile& mf = status.GetMakefile();
bool enableCompatVersion = cmExperimental::HasSupportEnabled(
mf, cmExperimental::Feature::ExportPackageInfo);
if (enableCompatVersion) {
parser.Bind("COMPAT_VERSION"_s, prArgs.CompatVersion);
}
parser.Parse(args, &unparsedArgs, 0);
if (!prArgs.ProjectName) {
status.SetError("PROJECT called with incorrect number of arguments");
return false;
}
cmMakefile& mf = status.GetMakefile();
if (mf.IsRootMakefile() &&
!mf.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
mf.IssueMessage(
@@ -168,13 +178,21 @@ bool cmProjectCommand(std::vector<std::string> const& args,
prArgs.Languages->emplace_back("NONE");
}
if (prArgs.CompatVersion && !prArgs.Version) {
mf.IssueMessage(MessageType::FATAL_ERROR,
"project with COMPAT_VERSION must also provide VERSION.");
cmSystemTools::SetFatalErrorOccurred();
return true;
}
cmsys::RegularExpression vx(
R"(^([0-9]+(\.[0-9]+(\.[0-9]+(\.[0-9]+)?)?)?)?$)");
constexpr std::size_t MAX_VERSION_COMPONENTS = 4u;
std::string version_string;
std::array<std::string, MAX_VERSION_COMPONENTS> version_components;
if (prArgs.Version) {
cmsys::RegularExpression vx(
R"(^([0-9]+(\.[0-9]+(\.[0-9]+(\.[0-9]+)?)?)?)?$)");
if (!vx.find(*prArgs.Version)) {
std::string e =
R"(VERSION ")" + *prArgs.Version + R"(" format invalid.)";
@@ -215,19 +233,41 @@ bool cmProjectCommand(std::vector<std::string> const& args,
}
}
auto create_variables = [&](cm::string_view var, std::string const& val) {
if (prArgs.CompatVersion) {
if (!vx.find(*prArgs.CompatVersion)) {
std::string e =
R"(COMPAT_VERSION ")" + *prArgs.CompatVersion + R"(" format invalid.)";
mf.IssueMessage(MessageType::FATAL_ERROR, e);
cmSystemTools::SetFatalErrorOccurred();
return true;
}
if (cmSystemTools::VersionCompareGreater(*prArgs.CompatVersion,
*prArgs.Version)) {
mf.IssueMessage(MessageType::FATAL_ERROR,
"COMPAT_VERSION must be less than or equal to VERSION");
cmSystemTools::SetFatalErrorOccurred();
return true;
}
}
auto createVariables = [&](cm::string_view var, std::string const& val) {
mf.AddDefinition(cmStrCat("PROJECT_"_s, var), val);
mf.AddDefinition(cmStrCat(*prArgs.ProjectName, "_"_s, var), val);
TopLevelCMakeVarCondSet(mf, cmStrCat("CMAKE_PROJECT_"_s, var), val);
};
create_variables("VERSION"_s, version_string);
create_variables("VERSION_MAJOR"_s, version_components[0]);
create_variables("VERSION_MINOR"_s, version_components[1]);
create_variables("VERSION_PATCH"_s, version_components[2]);
create_variables("VERSION_TWEAK"_s, version_components[3]);
create_variables("DESCRIPTION"_s, prArgs.Description.value_or(""));
create_variables("HOMEPAGE_URL"_s, prArgs.HomepageURL.value_or(""));
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]);
createVariables("DESCRIPTION"_s, prArgs.Description.value_or(""));
createVariables("HOMEPAGE_URL"_s, prArgs.HomepageURL.value_or(""));
if (enableCompatVersion) {
createVariables("COMPAT_VERSION"_s, prArgs.CompatVersion.value_or(""));
}
if (unparsedArgs.empty() && !prArgs.Languages) {
// if no language is specified do c and c++