Add USES_TERMINAL option for custom commands
Teach the add_custom_command and add_custom_target commands a new USES_TERMINAL option. Use it to tell the generator to give the command direct access to the terminal if possible.
This commit is contained in:
parent
ad6ee42627
commit
fe5d6e8c0f
|
@ -18,7 +18,8 @@ The first signature is for adding a custom command to produce an output::
|
|||
[IMPLICIT_DEPENDS <lang1> depend1
|
||||
[<lang2> depend2] ...]
|
||||
[WORKING_DIRECTORY dir]
|
||||
[COMMENT comment] [VERBATIM] [APPEND])
|
||||
[COMMENT comment]
|
||||
[VERBATIM] [APPEND] [USES_TERMINAL])
|
||||
|
||||
This defines a command to generate specified ``OUTPUT`` file(s).
|
||||
A target created in the same directory (``CMakeLists.txt`` file)
|
||||
|
@ -120,6 +121,11 @@ The options are:
|
|||
as a file on disk it should be marked with the :prop_sf:`SYMBOLIC`
|
||||
source file property.
|
||||
|
||||
``USES_TERMINAL``
|
||||
The command will be given direct access to the terminal if possible.
|
||||
With the :generator:`Ninja` generator, this places the command in
|
||||
the ``console`` pool.
|
||||
|
||||
``VERBATIM``
|
||||
All arguments to the commands will be escaped properly for the
|
||||
build tool so that the invoked command receives each argument
|
||||
|
@ -151,7 +157,8 @@ target is already built, the command will not execute.
|
|||
COMMAND command1 [ARGS] [args1...]
|
||||
[COMMAND command2 [ARGS] [args2...] ...]
|
||||
[WORKING_DIRECTORY dir]
|
||||
[COMMENT comment] [VERBATIM])
|
||||
[COMMENT comment]
|
||||
[VERBATIM] [USES_TERMINAL])
|
||||
|
||||
This defines a new command that will be associated with building the
|
||||
specified target. When the command will happen is determined by which
|
||||
|
|
|
@ -9,7 +9,8 @@ Add a target with no output so it will always be built.
|
|||
[COMMAND command2 [args2...] ...]
|
||||
[DEPENDS depend depend depend ... ]
|
||||
[WORKING_DIRECTORY dir]
|
||||
[COMMENT comment] [VERBATIM]
|
||||
[COMMENT comment]
|
||||
[VERBATIM] [USES_TERMINAL]
|
||||
[SOURCES src1 [src2...]])
|
||||
|
||||
Adds a target with the given name that executes the given commands.
|
||||
|
@ -74,6 +75,11 @@ The options are:
|
|||
is platform specific because there is no protection of
|
||||
tool-specific special characters.
|
||||
|
||||
``USES_TERMINAL``
|
||||
The command will be given direct access to the terminal if possible.
|
||||
With the :generator:`Ninja` generator, this places the command in
|
||||
the ``console`` pool.
|
||||
|
||||
``WORKING_DIRECTORY``
|
||||
Execute the command with the given current working directory.
|
||||
If it is a relative path it will be interpreted relative to the
|
||||
|
|
|
@ -35,6 +35,7 @@ bool cmAddCustomCommandCommand
|
|||
std::vector<std::string> depends, outputs, output;
|
||||
bool verbatim = false;
|
||||
bool append = false;
|
||||
bool uses_terminal = false;
|
||||
std::string implicit_depends_lang;
|
||||
cmCustomCommand::ImplicitDependsList implicit_depends;
|
||||
|
||||
|
@ -102,6 +103,10 @@ bool cmAddCustomCommandCommand
|
|||
{
|
||||
append = true;
|
||||
}
|
||||
else if(copy == "USES_TERMINAL")
|
||||
{
|
||||
uses_terminal = true;
|
||||
}
|
||||
else if(copy == "TARGET")
|
||||
{
|
||||
doing = doing_target;
|
||||
|
@ -312,7 +317,7 @@ bool cmAddCustomCommandCommand
|
|||
this->Makefile->AddCustomCommandToTarget(target, no_depends,
|
||||
commandLines, cctype,
|
||||
comment, working.c_str(),
|
||||
escapeOldStyle);
|
||||
escapeOldStyle, uses_terminal);
|
||||
}
|
||||
else if(target.empty())
|
||||
{
|
||||
|
@ -321,7 +326,7 @@ bool cmAddCustomCommandCommand
|
|||
main_dependency,
|
||||
commandLines, comment,
|
||||
working.c_str(), false,
|
||||
escapeOldStyle);
|
||||
escapeOldStyle, uses_terminal);
|
||||
|
||||
// Add implicit dependency scanning requests if any were given.
|
||||
if(!implicit_depends.empty())
|
||||
|
@ -346,6 +351,11 @@ bool cmAddCustomCommandCommand
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (uses_terminal)
|
||||
{
|
||||
this->SetError("USES_TERMINAL may not be used with SOURCE signatures");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool issueMessage = true;
|
||||
|
|
|
@ -48,6 +48,7 @@ bool cmAddCustomTargetCommand
|
|||
std::vector<std::string> depends;
|
||||
std::string working_directory;
|
||||
bool verbatim = false;
|
||||
bool uses_terminal = false;
|
||||
std::string comment_buffer;
|
||||
const char* comment = 0;
|
||||
std::vector<std::string> sources;
|
||||
|
@ -93,6 +94,11 @@ bool cmAddCustomTargetCommand
|
|||
doing = doing_nothing;
|
||||
verbatim = true;
|
||||
}
|
||||
else if(copy == "USES_TERMINAL")
|
||||
{
|
||||
doing = doing_nothing;
|
||||
uses_terminal = true;
|
||||
}
|
||||
else if (copy == "COMMENT")
|
||||
{
|
||||
doing = doing_comment;
|
||||
|
@ -221,12 +227,20 @@ bool cmAddCustomTargetCommand
|
|||
cmSystemTools::CollapseFullPath(working_directory, build_dir);
|
||||
}
|
||||
|
||||
if (commandLines.empty() && uses_terminal)
|
||||
{
|
||||
this->Makefile->IssueMessage(cmake::FATAL_ERROR,
|
||||
"USES_TERMINAL may not be specified without any COMMAND");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add the utility target to the makefile.
|
||||
bool escapeOldStyle = !verbatim;
|
||||
cmTarget* target =
|
||||
this->Makefile->AddUtilityCommand(targetName, excludeFromAll,
|
||||
working_directory.c_str(), depends,
|
||||
commandLines, escapeOldStyle, comment);
|
||||
commandLines, escapeOldStyle, comment,
|
||||
uses_terminal);
|
||||
|
||||
// Add additional user-specified source files to the target.
|
||||
target->AddSources(sources);
|
||||
|
|
|
@ -22,6 +22,7 @@ cmCustomCommand::cmCustomCommand()
|
|||
this->HaveComment = false;
|
||||
this->EscapeOldStyle = true;
|
||||
this->EscapeAllowMakeVars = false;
|
||||
this->UsesTerminal = false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -34,7 +35,8 @@ cmCustomCommand::cmCustomCommand(const cmCustomCommand& r):
|
|||
WorkingDirectory(r.WorkingDirectory),
|
||||
EscapeAllowMakeVars(r.EscapeAllowMakeVars),
|
||||
EscapeOldStyle(r.EscapeOldStyle),
|
||||
Backtrace(r.Backtrace)
|
||||
Backtrace(r.Backtrace),
|
||||
UsesTerminal(r.UsesTerminal)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -56,6 +58,7 @@ cmCustomCommand& cmCustomCommand::operator=(cmCustomCommand const& r)
|
|||
this->EscapeOldStyle = r.EscapeOldStyle;
|
||||
this->ImplicitDepends = r.ImplicitDepends;
|
||||
this->Backtrace = r.Backtrace;
|
||||
this->UsesTerminal = r.UsesTerminal;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -184,3 +187,15 @@ void cmCustomCommand::AppendImplicitDepends(ImplicitDependsList const& l)
|
|||
this->ImplicitDepends.insert(this->ImplicitDepends.end(),
|
||||
l.begin(), l.end());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmCustomCommand::GetUsesTerminal() const
|
||||
{
|
||||
return this->UsesTerminal;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmCustomCommand::SetUsesTerminal(bool b)
|
||||
{
|
||||
this->UsesTerminal = b;
|
||||
}
|
||||
|
|
|
@ -79,6 +79,11 @@ public:
|
|||
void AppendImplicitDepends(ImplicitDependsList const&);
|
||||
ImplicitDependsList const& GetImplicitDepends() const;
|
||||
|
||||
/** Set/Get whether this custom command should be given access to the
|
||||
real console (if possible). */
|
||||
bool GetUsesTerminal() const;
|
||||
void SetUsesTerminal(bool b);
|
||||
|
||||
private:
|
||||
std::vector<std::string> Outputs;
|
||||
std::vector<std::string> Depends;
|
||||
|
@ -90,6 +95,7 @@ private:
|
|||
bool EscapeOldStyle;
|
||||
cmListFileBacktrace Backtrace;
|
||||
ImplicitDependsList ImplicitDepends;
|
||||
bool UsesTerminal;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -885,7 +885,8 @@ cmMakefile::AddCustomCommandToTarget(const std::string& target,
|
|||
cmTarget::CustomCommandType type,
|
||||
const char* comment,
|
||||
const char* workingDir,
|
||||
bool escapeOldStyle) const
|
||||
bool escapeOldStyle,
|
||||
bool uses_terminal) const
|
||||
{
|
||||
// Find the target to which to add the custom command.
|
||||
cmTargets::iterator ti = this->Targets.find(target);
|
||||
|
@ -941,6 +942,7 @@ cmMakefile::AddCustomCommandToTarget(const std::string& target,
|
|||
commandLines, comment, workingDir);
|
||||
cc.SetEscapeOldStyle(escapeOldStyle);
|
||||
cc.SetEscapeAllowMakeVars(true);
|
||||
cc.SetUsesTerminal(uses_terminal);
|
||||
switch(type)
|
||||
{
|
||||
case cmTarget::PRE_BUILD:
|
||||
|
@ -964,7 +966,8 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
|
|||
const char* comment,
|
||||
const char* workingDir,
|
||||
bool replace,
|
||||
bool escapeOldStyle)
|
||||
bool escapeOldStyle,
|
||||
bool uses_terminal)
|
||||
{
|
||||
// Make sure there is at least one output.
|
||||
if(outputs.empty())
|
||||
|
@ -1071,6 +1074,7 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
|
|||
comment, workingDir);
|
||||
cc->SetEscapeOldStyle(escapeOldStyle);
|
||||
cc->SetEscapeAllowMakeVars(true);
|
||||
cc->SetUsesTerminal(uses_terminal);
|
||||
file->SetCustomCommand(cc);
|
||||
this->UpdateOutputToSourceMap(outputs, file);
|
||||
}
|
||||
|
@ -1119,13 +1123,15 @@ cmMakefile::AddCustomCommandToOutput(const std::string& output,
|
|||
const char* comment,
|
||||
const char* workingDir,
|
||||
bool replace,
|
||||
bool escapeOldStyle)
|
||||
bool escapeOldStyle,
|
||||
bool uses_terminal)
|
||||
{
|
||||
std::vector<std::string> outputs;
|
||||
outputs.push_back(output);
|
||||
return this->AddCustomCommandToOutput(outputs, depends, main_dependency,
|
||||
commandLines, comment, workingDir,
|
||||
replace, escapeOldStyle);
|
||||
replace, escapeOldStyle,
|
||||
uses_terminal);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -1242,7 +1248,8 @@ cmMakefile::AddUtilityCommand(const std::string& utilityName,
|
|||
const char* workingDirectory,
|
||||
const std::vector<std::string>& depends,
|
||||
const cmCustomCommandLines& commandLines,
|
||||
bool escapeOldStyle, const char* comment)
|
||||
bool escapeOldStyle, const char* comment,
|
||||
bool uses_terminal)
|
||||
{
|
||||
// Create a target instance for this utility.
|
||||
cmTarget* target = this->AddNewTarget(cmTarget::UTILITY, utilityName);
|
||||
|
@ -1269,7 +1276,7 @@ cmMakefile::AddUtilityCommand(const std::string& utilityName,
|
|||
no_main_dependency,
|
||||
commandLines, comment,
|
||||
workingDirectory, no_replace,
|
||||
escapeOldStyle);
|
||||
escapeOldStyle, uses_terminal);
|
||||
cmSourceFile* sf = target->AddSourceCMP0049(force);
|
||||
|
||||
// The output is not actually created so mark it symbolic.
|
||||
|
|
|
@ -174,7 +174,8 @@ public:
|
|||
const cmCustomCommandLines& commandLines,
|
||||
cmTarget::CustomCommandType type,
|
||||
const char* comment, const char* workingDir,
|
||||
bool escapeOldStyle = true) const;
|
||||
bool escapeOldStyle = true,
|
||||
bool uses_terminal = false) const;
|
||||
cmSourceFile* AddCustomCommandToOutput(
|
||||
const std::vector<std::string>& outputs,
|
||||
const std::vector<std::string>& depends,
|
||||
|
@ -182,7 +183,8 @@ public:
|
|||
const cmCustomCommandLines& commandLines,
|
||||
const char* comment, const char* workingDir,
|
||||
bool replace = false,
|
||||
bool escapeOldStyle = true);
|
||||
bool escapeOldStyle = true,
|
||||
bool uses_terminal = false);
|
||||
cmSourceFile* AddCustomCommandToOutput(
|
||||
const std::string& output,
|
||||
const std::vector<std::string>& depends,
|
||||
|
@ -190,7 +192,8 @@ public:
|
|||
const cmCustomCommandLines& commandLines,
|
||||
const char* comment, const char* workingDir,
|
||||
bool replace = false,
|
||||
bool escapeOldStyle = true);
|
||||
bool escapeOldStyle = true,
|
||||
bool uses_terminal = false);
|
||||
void AddCustomCommandOldStyle(const std::string& target,
|
||||
const std::vector<std::string>& outputs,
|
||||
const std::vector<std::string>& depends,
|
||||
|
@ -237,7 +240,8 @@ public:
|
|||
const std::vector<std::string>& depends,
|
||||
const cmCustomCommandLines& commandLines,
|
||||
bool escapeOldStyle = true,
|
||||
const char* comment = 0);
|
||||
const char* comment = 0,
|
||||
bool uses_terminal = false);
|
||||
|
||||
/**
|
||||
* Add a link library to the build.
|
||||
|
|
|
@ -483,3 +483,26 @@ add_custom_command(
|
|||
COMMAND ${CMAKE_COMMAND} -E touch "${gen_file}")
|
||||
|
||||
add_library(NormDepends "${gen_file}")
|
||||
|
||||
# Test that USES_TERMINAL is parsed correctly.
|
||||
# It seems much more difficult to test that USES_TERMINAL actually gives
|
||||
# the subprocess console access, as test output is piped through CTest,
|
||||
# and CTest itself might not be connected to the console.
|
||||
|
||||
set(gen_file "${gen_path}/bar2.cxx")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${gen_file}"
|
||||
DEPENDS "${gen_path}"
|
||||
COMMAND ${CMAKE_COMMAND} -E touch "${gen_file}"
|
||||
VERBATIM
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
||||
add_library(UseConsole "${gen_file}")
|
||||
|
||||
add_custom_target(UseConsoleTarget ALL
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Custom console target."
|
||||
VERBATIM
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
|
|
@ -6,3 +6,4 @@ run_cmake(BadArgument)
|
|||
run_cmake(NoArguments)
|
||||
run_cmake(NoOutputOrTarget)
|
||||
run_cmake(OutputAndTarget)
|
||||
run_cmake(SourceUsesTerminal)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,4 @@
|
|||
CMake Error at SourceUsesTerminal.cmake:1 \(add_custom_command\):
|
||||
add_custom_command USES_TERMINAL may not be used with SOURCE signatures
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1 @@
|
|||
add_custom_command(SOURCE t TARGET t USES_TERMINAL)
|
|
@ -2,3 +2,4 @@ include(RunCMake)
|
|||
|
||||
run_cmake(NoArguments)
|
||||
run_cmake(BadTargetName)
|
||||
run_cmake(UsesTerminalNoCommand)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,4 @@
|
|||
CMake Error at UsesTerminalNoCommand.cmake:1 \(add_custom_target\):
|
||||
USES_TERMINAL may not be specified without any COMMAND
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1 @@
|
|||
add_custom_target(MyTarget USES_TERMINAL)
|
Loading…
Reference in New Issue