mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-06 14:19:59 -05:00
file(configure): Order of named options should be specified in any order
Fixes: #20915
This commit is contained in:
+55
-30
@@ -2946,17 +2946,60 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
|
||||
bool HandleConfigureCommand(std::vector<std::string> const& args,
|
||||
cmExecutionStatus& status)
|
||||
{
|
||||
if (args.size() < 5) {
|
||||
status.SetError("Incorrect arguments to CONFIGURE subcommand.");
|
||||
struct Arguments
|
||||
{
|
||||
std::string Output;
|
||||
std::string Content;
|
||||
bool EscapeQuotes = false;
|
||||
bool AtOnly = false;
|
||||
std::string NewlineStyle;
|
||||
};
|
||||
|
||||
static auto const parser =
|
||||
cmArgumentParser<Arguments>{}
|
||||
.Bind("OUTPUT"_s, &Arguments::Output)
|
||||
.Bind("CONTENT"_s, &Arguments::Content)
|
||||
.Bind("ESCAPE_QUOTES"_s, &Arguments::EscapeQuotes)
|
||||
.Bind("@ONLY"_s, &Arguments::AtOnly)
|
||||
.Bind("NEWLINE_STYLE"_s, &Arguments::NewlineStyle);
|
||||
|
||||
std::vector<std::string> unrecognizedArguments;
|
||||
std::vector<std::string> keywordsMissingArguments;
|
||||
std::vector<std::string> parsedKeywords;
|
||||
auto parsedArgs =
|
||||
parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
|
||||
&keywordsMissingArguments, &parsedKeywords);
|
||||
|
||||
auto argIt = unrecognizedArguments.begin();
|
||||
if (argIt != unrecognizedArguments.end()) {
|
||||
status.SetError(
|
||||
cmStrCat("CONFIGURE Unrecognized argument: \"", *argIt, "\""));
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
return false;
|
||||
}
|
||||
if (args[1] != "OUTPUT") {
|
||||
status.SetError("Incorrect arguments to CONFIGURE subcommand.");
|
||||
return false;
|
||||
|
||||
std::vector<std::string> mandatoryOptions{ "OUTPUT", "CONTENT" };
|
||||
for (auto const& e : mandatoryOptions) {
|
||||
const bool optionHasNoValue =
|
||||
std::find(keywordsMissingArguments.begin(),
|
||||
keywordsMissingArguments.end(),
|
||||
e) != keywordsMissingArguments.end();
|
||||
if (optionHasNoValue) {
|
||||
status.SetError(cmStrCat("CONFIGURE ", e, " option needs a value."));
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (args[3] != "CONTENT") {
|
||||
status.SetError("Incorrect arguments to CONFIGURE subcommand.");
|
||||
return false;
|
||||
|
||||
for (auto const& e : mandatoryOptions) {
|
||||
const bool optionGiven =
|
||||
std::find(parsedKeywords.begin(), parsedKeywords.end(), e) !=
|
||||
parsedKeywords.end();
|
||||
if (!optionGiven) {
|
||||
status.SetError(cmStrCat("CONFIGURE ", e, " option is mandatory."));
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string errorMessage;
|
||||
@@ -2966,28 +3009,9 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool escapeQuotes = false;
|
||||
bool atOnly = false;
|
||||
for (unsigned int i = 5; i < args.size(); ++i) {
|
||||
if (args[i] == "@ONLY") {
|
||||
atOnly = true;
|
||||
} else if (args[i] == "ESCAPE_QUOTES") {
|
||||
escapeQuotes = true;
|
||||
} else if (args[i] == "NEWLINE_STYLE" || args[i] == "LF" ||
|
||||
args[i] == "UNIX" || args[i] == "CRLF" || args[i] == "WIN32" ||
|
||||
args[i] == "DOS") {
|
||||
/* Options handled by NewLineStyle member above. */
|
||||
} else {
|
||||
status.SetError(
|
||||
cmStrCat("CONFIGURE Unrecognized argument \"", args[i], "\""));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for generator expressions
|
||||
const std::string input = args[4];
|
||||
std::string outputFile = cmSystemTools::CollapseFullPath(
|
||||
args[2], status.GetMakefile().GetCurrentBinaryDirectory());
|
||||
parsedArgs.Output, status.GetMakefile().GetCurrentBinaryDirectory());
|
||||
|
||||
std::string::size_type pos = outputFile.find_first_of("<>");
|
||||
if (pos != std::string::npos) {
|
||||
@@ -3036,12 +3060,13 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
|
||||
fout.SetCopyIfDifferent(true);
|
||||
|
||||
// copy input to output and expand variables from input at the same time
|
||||
std::stringstream sin(input, std::ios::in);
|
||||
std::stringstream sin(parsedArgs.Content, std::ios::in);
|
||||
std::string inLine;
|
||||
std::string outLine;
|
||||
while (cmSystemTools::GetLineFromStream(sin, inLine)) {
|
||||
outLine.clear();
|
||||
makeFile.ConfigureString(inLine, outLine, atOnly, escapeQuotes);
|
||||
makeFile.ConfigureString(inLine, outLine, parsedArgs.AtOnly,
|
||||
parsedArgs.EscapeQuotes);
|
||||
fout << outLine << newLineCharacters;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
set(file_name ${CMAKE_CURRENT_BINARY_DIR}/atonly.txt)
|
||||
set(var_a "a")
|
||||
set(var_b "b")
|
||||
file(CONFIGURE
|
||||
OUTPUT ${file_name}
|
||||
CONTENT "-->@var_a@<-- -->${var_b}<--"
|
||||
@ONLY
|
||||
)
|
||||
file(READ ${file_name} file_content)
|
||||
if(NOT file_content STREQUAL "-->a<-- -->${var_b}<--")
|
||||
message(FATAL_ERROR "@ONLY doesn't work")
|
||||
endif()
|
||||
@@ -1,4 +0,0 @@
|
||||
CMake Error at BadArg.cmake:[0-9]+ \(file\):
|
||||
file Incorrect arguments to CONFIGURE subcommand.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Error at BadArgContent.cmake:[0-9]+ \(file\):
|
||||
file CONFIGURE CONTENT option needs a value.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
@@ -0,0 +1 @@
|
||||
file(CONFIGURE CONTENT)
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Error at BadArgOutput.cmake:[0-9]+ \(file\):
|
||||
file CONFIGURE OUTPUT option needs a value.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
@@ -0,0 +1,12 @@
|
||||
set(file_name ${CMAKE_CURRENT_BINARY_DIR}/escape_quotes.txt)
|
||||
set(var "\t")
|
||||
set(ref "${var}")
|
||||
file(CONFIGURE
|
||||
CONTENT "-->@ref@<--"
|
||||
OUTPUT ${file_name}
|
||||
ESCAPE_QUOTES
|
||||
)
|
||||
file(READ ${file_name} file_content)
|
||||
if(NOT file_content MATCHES "^-->\t<--$")
|
||||
message(FATAL_ERROR "ESCAPE_QUOTES doesn't work")
|
||||
endif()
|
||||
@@ -1,10 +1,14 @@
|
||||
include(RunCMake)
|
||||
|
||||
run_cmake(AngleBracketsContent)
|
||||
run_cmake(BadArg)
|
||||
run_cmake(BadArgOutput)
|
||||
run_cmake(BadArgContent)
|
||||
run_cmake(BadArgGeneratorExpressionOutput)
|
||||
run_cmake(UnrecognizedArgs)
|
||||
run_cmake(DirOutput)
|
||||
run_cmake(NewLineStyle-NoArg)
|
||||
run_cmake(NewLineStyle-ValidArg)
|
||||
run_cmake(NewLineStyle-WrongArg)
|
||||
run_cmake(SubDir)
|
||||
run_cmake(AtOnly)
|
||||
run_cmake(EscapeQuotes)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Error at UnrecognizedArgs.cmake:[0-9]+ \(file\):
|
||||
file CONFIGURE Unrecognized argument: "INPUT"
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:[0-9]+ \(include\)
|
||||
@@ -0,0 +1 @@
|
||||
file(CONFIGURE INPUT)
|
||||
Reference in New Issue
Block a user