ENH: Added VERBATIM option to ADD_CUSTOM_COMMAND and ADD_CUSTOM_TARGET commands. This option enables full escaping of custom command arguments on all platforms. See bug#3786.
This commit is contained in:
parent
16f8da8b14
commit
d01b6f1281
|
@ -35,6 +35,7 @@ bool cmAddCustomCommandCommand::InitialPass(
|
|||
std::string source, target, comment, main_dependency,
|
||||
working;
|
||||
std::vector<std::string> depends, outputs, output;
|
||||
bool verbatim = false;
|
||||
|
||||
// Accumulate one command line at a time.
|
||||
cmCustomCommandLine currentLine;
|
||||
|
@ -90,6 +91,10 @@ bool cmAddCustomCommandCommand::InitialPass(
|
|||
{
|
||||
cctype = cmTarget::POST_BUILD;
|
||||
}
|
||||
else if(copy == "VERBATIM")
|
||||
{
|
||||
verbatim = true;
|
||||
}
|
||||
else if(copy == "TARGET")
|
||||
{
|
||||
doing = doing_target;
|
||||
|
@ -211,28 +216,31 @@ bool cmAddCustomCommandCommand::InitialPass(
|
|||
}
|
||||
|
||||
// Choose which mode of the command to use.
|
||||
bool escapeOldStyle = !verbatim;
|
||||
if(source.empty() && output.empty())
|
||||
{
|
||||
// Source is empty, use the target.
|
||||
std::vector<std::string> no_depends;
|
||||
this->Makefile->AddCustomCommandToTarget(target.c_str(), no_depends,
|
||||
commandLines, cctype,
|
||||
comment.c_str(), working.c_str());
|
||||
commandLines, cctype,
|
||||
comment.c_str(), working.c_str(),
|
||||
escapeOldStyle);
|
||||
}
|
||||
else if(target.empty())
|
||||
{
|
||||
// Target is empty, use the output.
|
||||
this->Makefile->AddCustomCommandToOutput(output, depends,
|
||||
main_dependency.c_str(),
|
||||
commandLines, comment.c_str(),
|
||||
working.c_str());
|
||||
main_dependency.c_str(),
|
||||
commandLines, comment.c_str(),
|
||||
working.c_str(), false,
|
||||
escapeOldStyle);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the old-style mode for backward compatibility.
|
||||
this->Makefile->AddCustomCommandOldStyle(target.c_str(), outputs, depends,
|
||||
source.c_str(), commandLines,
|
||||
comment.c_str());
|
||||
source.c_str(), commandLines,
|
||||
comment.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ public:
|
|||
" [MAIN_DEPENDENCY depend]\n"
|
||||
" [DEPENDS [depends...]]\n"
|
||||
" [WORKING_DIRECTORY dir]\n"
|
||||
" [COMMENT comment])\n"
|
||||
" [COMMENT comment] [VERBATIM])\n"
|
||||
"This defines a new command that can be executed during the build "
|
||||
"process. The outputs named should be listed as source files in the "
|
||||
"target for which they are to be generated. "
|
||||
|
@ -93,7 +93,7 @@ public:
|
|||
" COMMAND command1 [ARGS] [args1...]\n"
|
||||
" [COMMAND command2 [ARGS] [args2...] ...]\n"
|
||||
" [WORKING_DIRECTORY dir]\n"
|
||||
" [COMMENT comment])\n"
|
||||
" [COMMENT comment] [VERBATIM])\n"
|
||||
"This defines a new command that will be associated with "
|
||||
"building the specified target. When the command will "
|
||||
"happen is determined by which of the following is specified:\n"
|
||||
|
@ -104,7 +104,15 @@ public:
|
|||
"Studio 7 or later. For all other generators PRE_BUILD "
|
||||
"will be treated as PRE_LINK. "
|
||||
"If WORKING_DIRECTORY is specified the command will be executed "
|
||||
"in the directory given.";
|
||||
"in the directory given.\n"
|
||||
"If VERBATIM is given then all the arguments to the commands will be "
|
||||
"passed exactly as specified no matter the build tool used. "
|
||||
"Note that one level of escapes is still used by the CMake language "
|
||||
"processor before ADD_CUSTOM_TARGET even sees the arguments. "
|
||||
"Use of VERBATIM is recommended as it enables correct behavior. "
|
||||
"When VERBATIM is not given the behavior is platform specific. "
|
||||
"In the future VERBATIM may be enabled by default. The only reason "
|
||||
"it is an option is to preserve compatibility with older CMake code.";
|
||||
}
|
||||
|
||||
cmTypeMacro(cmAddCustomCommandCommand, cmCommand);
|
||||
|
|
|
@ -58,12 +58,14 @@ bool cmAddCustomTargetCommand::InitialPass(
|
|||
// Accumulate dependencies.
|
||||
std::vector<std::string> depends;
|
||||
std::string working_directory;
|
||||
bool verbatim = false;
|
||||
|
||||
// Keep track of parser state.
|
||||
enum tdoing {
|
||||
doing_command,
|
||||
doing_depends,
|
||||
doing_working_directory
|
||||
doing_working_directory,
|
||||
doing_verbatim
|
||||
};
|
||||
tdoing doing = doing_command;
|
||||
|
||||
|
@ -92,6 +94,11 @@ bool cmAddCustomTargetCommand::InitialPass(
|
|||
{
|
||||
doing = doing_working_directory;
|
||||
}
|
||||
else if(copy == "VERBATIM")
|
||||
{
|
||||
doing = doing_verbatim;
|
||||
verbatim = true;
|
||||
}
|
||||
else if(copy == "COMMAND")
|
||||
{
|
||||
doing = doing_command;
|
||||
|
@ -141,10 +148,11 @@ bool cmAddCustomTargetCommand::InitialPass(
|
|||
}
|
||||
|
||||
// Add the utility target to the makefile.
|
||||
bool escapeOldStyle = !verbatim;
|
||||
const char* no_output = 0;
|
||||
this->Makefile->AddUtilityCommand(args[0].c_str(), all, no_output,
|
||||
working_directory.c_str(), depends,
|
||||
commandLines);
|
||||
commandLines, escapeOldStyle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -65,8 +65,8 @@ public:
|
|||
return
|
||||
" ADD_CUSTOM_TARGET(Name [ALL] [command1 [args1...]]\n"
|
||||
" [COMMAND command2 [args2...] ...]\n"
|
||||
" [DEPENDS depend depend depend ... ])\n"
|
||||
" [WORKING_DIRECTORY dir]\n"
|
||||
" [DEPENDS depend depend depend ... ]\n"
|
||||
" [WORKING_DIRECTORY dir] [VERBATIM])\n"
|
||||
"Adds a target with the given name that executes the given commands. "
|
||||
"The target has no output file and is ALWAYS CONSIDERED OUT OF DATE "
|
||||
"even if the commands try to create a file with the name of the "
|
||||
|
@ -82,7 +82,15 @@ public:
|
|||
"If WORKING_DIRECTORY is set, then the command will be run in that "
|
||||
"directory. "
|
||||
"Dependencies listed with the DEPENDS argument may reference files "
|
||||
"and outputs of custom commands created with ADD_CUSTOM_COMMAND.";
|
||||
"and outputs of custom commands created with ADD_CUSTOM_COMMAND.\n"
|
||||
"If VERBATIM is given then all the arguments to the commands will be "
|
||||
"passed exactly as specified no matter the build tool used. "
|
||||
"Note that one level of escapes is still used by the CMake language "
|
||||
"processor before ADD_CUSTOM_TARGET even sees the arguments. "
|
||||
"Use of VERBATIM is recommended as it enables correct behavior. "
|
||||
"When VERBATIM is not given the behavior is platform specific. "
|
||||
"In the future VERBATIM may be enabled by default. The only reason "
|
||||
"it is an option is to preserve compatibility with older CMake code.";
|
||||
}
|
||||
|
||||
cmTypeMacro(cmAddCustomTargetCommand, cmCommand);
|
||||
|
|
|
@ -554,7 +554,8 @@ cmMakefile::AddCustomCommandToTarget(const char* target,
|
|||
const cmCustomCommandLines& commandLines,
|
||||
cmTarget::CustomCommandType type,
|
||||
const char* comment,
|
||||
const char* workingDir)
|
||||
const char* workingDir,
|
||||
bool escapeOldStyle)
|
||||
{
|
||||
// Find the target to which to add the custom command.
|
||||
cmTargets::iterator ti = this->Targets.find(target);
|
||||
|
@ -563,6 +564,7 @@ cmMakefile::AddCustomCommandToTarget(const char* target,
|
|||
// Add the command to the appropriate build step for the target.
|
||||
std::vector<std::string> no_output;
|
||||
cmCustomCommand cc(no_output, depends, commandLines, comment, workingDir);
|
||||
cc.SetEscapeOldStyle(escapeOldStyle);
|
||||
switch(type)
|
||||
{
|
||||
case cmTarget::PRE_BUILD:
|
||||
|
@ -598,7 +600,8 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
|
|||
const cmCustomCommandLines& commandLines,
|
||||
const char* comment,
|
||||
const char* workingDir,
|
||||
bool replace)
|
||||
bool replace,
|
||||
bool escapeOldStyle)
|
||||
{
|
||||
// Make sure there is at least one output.
|
||||
if(outputs.empty())
|
||||
|
@ -686,6 +689,7 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
|
|||
cmCustomCommand* cc =
|
||||
new cmCustomCommand(outputs, depends2, commandLines,
|
||||
comment, workingDir);
|
||||
cc->SetEscapeOldStyle(escapeOldStyle);
|
||||
file->SetCustomCommand(cc);
|
||||
}
|
||||
}
|
||||
|
@ -698,13 +702,14 @@ cmMakefile::AddCustomCommandToOutput(const char* output,
|
|||
const cmCustomCommandLines& commandLines,
|
||||
const char* comment,
|
||||
const char* workingDir,
|
||||
bool replace)
|
||||
bool replace,
|
||||
bool escapeOldStyle)
|
||||
{
|
||||
std::vector<std::string> outputs;
|
||||
outputs.push_back(output);
|
||||
this->AddCustomCommandToOutput(outputs, depends, main_dependency,
|
||||
commandLines, comment, workingDir,
|
||||
replace);
|
||||
replace, escapeOldStyle);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -819,7 +824,8 @@ void cmMakefile::AddUtilityCommand(const char* utilityName, bool all,
|
|||
const char* output,
|
||||
const char* workingDirectory,
|
||||
const std::vector<std::string>& depends,
|
||||
const cmCustomCommandLines& commandLines)
|
||||
const cmCustomCommandLines& commandLines,
|
||||
bool escapeOldStyle)
|
||||
{
|
||||
// Create a target instance for this utility.
|
||||
cmTarget target;
|
||||
|
@ -833,6 +839,7 @@ void cmMakefile::AddUtilityCommand(const char* utilityName, bool all,
|
|||
outputs.push_back(output);
|
||||
}
|
||||
cmCustomCommand cc(outputs, depends, commandLines, 0, workingDirectory);
|
||||
cc.SetEscapeOldStyle(escapeOldStyle);
|
||||
target.GetPostBuildCommands().push_back(cc);
|
||||
|
||||
// Add the target to the set of targets.
|
||||
|
|
|
@ -143,19 +143,22 @@ public:
|
|||
const std::vector<std::string>& depends,
|
||||
const cmCustomCommandLines& commandLines,
|
||||
cmTarget::CustomCommandType type,
|
||||
const char* comment, const char* workingDir);
|
||||
const char* comment, const char* workingDir,
|
||||
bool escapeOldStyle = true);
|
||||
void AddCustomCommandToOutput(const std::vector<std::string>& outputs,
|
||||
const std::vector<std::string>& depends,
|
||||
const char* main_dependency,
|
||||
const cmCustomCommandLines& commandLines,
|
||||
const char* comment, const char* workingDir,
|
||||
bool replace = false);
|
||||
bool replace = false,
|
||||
bool escapeOldStyle = true);
|
||||
void AddCustomCommandToOutput(const char* output,
|
||||
const std::vector<std::string>& depends,
|
||||
const char* main_dependency,
|
||||
const cmCustomCommandLines& commandLines,
|
||||
const char* comment, const char* workingDir,
|
||||
bool replace = false);
|
||||
bool replace = false,
|
||||
bool escapeOldStyle = true);
|
||||
void AddCustomCommandOldStyle(const char* target,
|
||||
const std::vector<std::string>& outputs,
|
||||
const std::vector<std::string>& depends,
|
||||
|
@ -192,7 +195,8 @@ public:
|
|||
const char* output,
|
||||
const char* workingDirectory,
|
||||
const std::vector<std::string>& depends,
|
||||
const cmCustomCommandLines& commandLines);
|
||||
const cmCustomCommandLines& commandLines,
|
||||
bool escapeOldStyle = true);
|
||||
|
||||
/**
|
||||
* Add a link library to the build.
|
||||
|
|
|
@ -176,6 +176,17 @@ SET(CHECK_ARGS
|
|||
double\"quote
|
||||
"\\;semi-colons\\;"
|
||||
"semi\\;colon"
|
||||
`back-ticks`
|
||||
back`tick
|
||||
"(parens)"
|
||||
"(lparen"
|
||||
"rparen)"
|
||||
$dollar-signs$
|
||||
dollar$sign
|
||||
&ersands&
|
||||
amper&sand
|
||||
\@two-ats\@
|
||||
one@at
|
||||
"c:/posix/path/with space"
|
||||
"c:\\windows\\path\\with space"
|
||||
"'single quotes with space'"
|
||||
|
@ -184,6 +195,17 @@ SET(CHECK_ARGS
|
|||
"double\"quote with space"
|
||||
"\\;semi-colons with space\\;"
|
||||
"semi\\;colon with space"
|
||||
"`back-ticks` with space"
|
||||
"back`tick with space"
|
||||
"(parens) with space"
|
||||
"(lparen with space"
|
||||
"rparen) with space"
|
||||
"$dollar-signs$ with space"
|
||||
"dollar$sign with space"
|
||||
"&ersands& with space"
|
||||
"amper&sand with space"
|
||||
"\@two-ats\@ with space"
|
||||
"one@at with space"
|
||||
)
|
||||
FOREACH(arg ${CHECK_ARGS})
|
||||
SET(ARG "${arg}")
|
||||
|
@ -199,8 +221,18 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/check_command_line.c.in
|
|||
@ONLY IMMEDIATE)
|
||||
ADD_EXECUTABLE(check_command_line
|
||||
${CMAKE_CURRENT_BINARY_DIR}/check_command_line.c)
|
||||
ADD_CUSTOM_TARGET(do_check_command_line #ALL
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/command_line_check
|
||||
COMMAND ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/check_command_line
|
||||
${CHECK_ARGS}
|
||||
VERBATIM
|
||||
COMMENT "Checking custom command line escapes"
|
||||
)
|
||||
ADD_CUSTOM_TARGET(do_check_command_line ALL
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/command_line_check
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Checking custom target command escapes"
|
||||
COMMAND ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/check_command_line
|
||||
${CHECK_ARGS}
|
||||
VERBATIM
|
||||
)
|
||||
ADD_DEPENDENCIES(do_check_command_line check_command_line)
|
||||
|
|
|
@ -20,7 +20,7 @@ int main(int argc, const char* argv[])
|
|||
}
|
||||
else
|
||||
{
|
||||
printf("[%s]\n", *a);
|
||||
/*printf("[%s]\n", *a);*/
|
||||
}
|
||||
}
|
||||
if(*a || *e)
|
||||
|
@ -28,5 +28,6 @@ int main(int argc, const char* argv[])
|
|||
fprintf(stderr, "Number of arguments does not match expected.\n");
|
||||
return 1;
|
||||
}
|
||||
printf("Command line escapes work!\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue