mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-14 02:08:27 +08:00
add_custom_command: Target-dependent generator expression support
OUTPUT variant with a TARGET given to allow resolving target-based generator expressions wouldn't work because OUTPUT is resolved before generator targets are created, i.e. FindGeneratorTargetToUse() returns nullptr. This is a known limitation, see #21364. Implements #21336.
This commit is contained in:
@@ -338,6 +338,8 @@ will re-run whenever ``in.txt`` changes.
|
|||||||
where ``<config>`` is the build configuration, and then compile the generated
|
where ``<config>`` is the build configuration, and then compile the generated
|
||||||
source as part of a library.
|
source as part of a library.
|
||||||
|
|
||||||
|
.. _`add_custom_command(TARGET)`:
|
||||||
|
|
||||||
Build Events
|
Build Events
|
||||||
^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
@@ -388,6 +390,9 @@ of the following is specified:
|
|||||||
|
|
||||||
This allows to add individual build events for every configuration.
|
This allows to add individual build events for every configuration.
|
||||||
|
|
||||||
|
.. versionadded:: 3.21
|
||||||
|
Support for target-dependent generator expressions.
|
||||||
|
|
||||||
Examples: Build Events
|
Examples: Build Events
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
5
Help/release/dev/add_custom_command-TARGET-genex.rst
Normal file
5
Help/release/dev/add_custom_command-TARGET-genex.rst
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
add_custom_command-TARGET-genex
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
* The :ref:`add_custom_command(TARGET) <add_custom_command(TARGET)>` command
|
||||||
|
gained support for resolving target-dependent generator expressions.
|
@@ -150,3 +150,13 @@ void cmCustomCommand::SetCMP0116Status(cmPolicies::PolicyStatus cmp0116)
|
|||||||
{
|
{
|
||||||
this->CMP0116Status = cmp0116;
|
this->CMP0116Status = cmp0116;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string& cmCustomCommand::GetTarget() const
|
||||||
|
{
|
||||||
|
return this->Target;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmCustomCommand::SetTarget(const std::string& target)
|
||||||
|
{
|
||||||
|
this->Target = target;
|
||||||
|
}
|
||||||
|
@@ -100,6 +100,10 @@ public:
|
|||||||
cmPolicies::PolicyStatus GetCMP0116Status() const;
|
cmPolicies::PolicyStatus GetCMP0116Status() const;
|
||||||
void SetCMP0116Status(cmPolicies::PolicyStatus cmp0116);
|
void SetCMP0116Status(cmPolicies::PolicyStatus cmp0116);
|
||||||
|
|
||||||
|
/** Set/Get the associated target */
|
||||||
|
const std::string& GetTarget() const;
|
||||||
|
void SetTarget(const std::string& target);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> Outputs;
|
std::vector<std::string> Outputs;
|
||||||
std::vector<std::string> Byproducts;
|
std::vector<std::string> Byproducts;
|
||||||
@@ -107,6 +111,7 @@ private:
|
|||||||
cmCustomCommandLines CommandLines;
|
cmCustomCommandLines CommandLines;
|
||||||
cmListFileBacktrace Backtrace;
|
cmListFileBacktrace Backtrace;
|
||||||
cmImplicitDependsList ImplicitDepends;
|
cmImplicitDependsList ImplicitDepends;
|
||||||
|
std::string Target;
|
||||||
std::string Comment;
|
std::string Comment;
|
||||||
std::string WorkingDirectory;
|
std::string WorkingDirectory;
|
||||||
std::string Depfile;
|
std::string Depfile;
|
||||||
|
@@ -29,7 +29,7 @@ namespace {
|
|||||||
std::string EvaluateSplitConfigGenex(
|
std::string EvaluateSplitConfigGenex(
|
||||||
cm::string_view input, cmGeneratorExpression const& ge, cmLocalGenerator* lg,
|
cm::string_view input, cmGeneratorExpression const& ge, cmLocalGenerator* lg,
|
||||||
bool useOutputConfig, std::string const& outputConfig,
|
bool useOutputConfig, std::string const& outputConfig,
|
||||||
std::string const& commandConfig,
|
std::string const& commandConfig, cmGeneratorTarget const* target,
|
||||||
std::set<BT<std::pair<std::string, bool>>>* utils = nullptr)
|
std::set<BT<std::pair<std::string, bool>>>* utils = nullptr)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
@@ -87,7 +87,7 @@ std::string EvaluateSplitConfigGenex(
|
|||||||
// Evaluate this genex in the selected configuration.
|
// Evaluate this genex in the selected configuration.
|
||||||
std::unique_ptr<cmCompiledGeneratorExpression> cge =
|
std::unique_ptr<cmCompiledGeneratorExpression> cge =
|
||||||
ge.Parse(std::string(genex));
|
ge.Parse(std::string(genex));
|
||||||
result += cge->Evaluate(lg, *config);
|
result += cge->Evaluate(lg, *config, target);
|
||||||
|
|
||||||
// Record targets referenced by the genex.
|
// Record targets referenced by the genex.
|
||||||
if (utils) {
|
if (utils) {
|
||||||
@@ -114,7 +114,8 @@ std::vector<std::string> EvaluateDepends(std::vector<std::string> const& paths,
|
|||||||
std::string const& ep =
|
std::string const& ep =
|
||||||
EvaluateSplitConfigGenex(p, ge, lg, /*useOutputConfig=*/true,
|
EvaluateSplitConfigGenex(p, ge, lg, /*useOutputConfig=*/true,
|
||||||
/*outputConfig=*/outputConfig,
|
/*outputConfig=*/outputConfig,
|
||||||
/*commandConfig=*/commandConfig);
|
/*commandConfig=*/commandConfig,
|
||||||
|
/*target=*/nullptr);
|
||||||
cm::append(depends, cmExpandedList(ep));
|
cm::append(depends, cmExpandedList(ep));
|
||||||
}
|
}
|
||||||
for (std::string& p : depends) {
|
for (std::string& p : depends) {
|
||||||
@@ -157,6 +158,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
|
|||||||
: CC(&cc)
|
: CC(&cc)
|
||||||
, OutputConfig(crossConfig ? *crossConfig : config)
|
, OutputConfig(crossConfig ? *crossConfig : config)
|
||||||
, CommandConfig(std::move(config))
|
, CommandConfig(std::move(config))
|
||||||
|
, Target(cc.GetTarget())
|
||||||
, LG(lg)
|
, LG(lg)
|
||||||
, OldStyle(cc.GetEscapeOldStyle())
|
, OldStyle(cc.GetEscapeOldStyle())
|
||||||
, MakeVars(cc.GetEscapeAllowMakeVars())
|
, MakeVars(cc.GetEscapeAllowMakeVars())
|
||||||
@@ -171,6 +173,8 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmGeneratorExpression ge(cc.GetBacktrace());
|
cmGeneratorExpression ge(cc.GetBacktrace());
|
||||||
|
cmGeneratorTarget const* target{ lg->FindGeneratorTargetToUse(
|
||||||
|
this->Target) };
|
||||||
|
|
||||||
const cmCustomCommandLines& cmdlines = this->CC->GetCommandLines();
|
const cmCustomCommandLines& cmdlines = this->CC->GetCommandLines();
|
||||||
for (cmCustomCommandLine const& cmdline : cmdlines) {
|
for (cmCustomCommandLine const& cmdline : cmdlines) {
|
||||||
@@ -180,7 +184,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
|
|||||||
for (std::string const& clarg : cmdline) {
|
for (std::string const& clarg : cmdline) {
|
||||||
std::string parsed_arg = EvaluateSplitConfigGenex(
|
std::string parsed_arg = EvaluateSplitConfigGenex(
|
||||||
clarg, ge, this->LG, useOutputConfig, this->OutputConfig,
|
clarg, ge, this->LG, useOutputConfig, this->OutputConfig,
|
||||||
this->CommandConfig, &this->Utilities);
|
this->CommandConfig, target, &this->Utilities);
|
||||||
if (this->CC->GetCommandExpandLists()) {
|
if (this->CC->GetCommandExpandLists()) {
|
||||||
cm::append(argv, cmExpandedList(parsed_arg));
|
cm::append(argv, cmExpandedList(parsed_arg));
|
||||||
} else {
|
} else {
|
||||||
@@ -249,9 +253,9 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
|
|||||||
|
|
||||||
const std::string& workingdirectory = this->CC->GetWorkingDirectory();
|
const std::string& workingdirectory = this->CC->GetWorkingDirectory();
|
||||||
if (!workingdirectory.empty()) {
|
if (!workingdirectory.empty()) {
|
||||||
this->WorkingDirectory =
|
this->WorkingDirectory = EvaluateSplitConfigGenex(
|
||||||
EvaluateSplitConfigGenex(workingdirectory, ge, this->LG, true,
|
workingdirectory, ge, this->LG, true, this->OutputConfig,
|
||||||
this->OutputConfig, this->CommandConfig);
|
this->CommandConfig, target);
|
||||||
// Convert working directory to a full path.
|
// Convert working directory to a full path.
|
||||||
if (!this->WorkingDirectory.empty()) {
|
if (!this->WorkingDirectory.empty()) {
|
||||||
std::string const& build_dir = this->LG->GetCurrentBinaryDirectory();
|
std::string const& build_dir = this->LG->GetCurrentBinaryDirectory();
|
||||||
|
@@ -25,6 +25,7 @@ class cmCustomCommandGenerator
|
|||||||
cmCustomCommand const* CC;
|
cmCustomCommand const* CC;
|
||||||
std::string OutputConfig;
|
std::string OutputConfig;
|
||||||
std::string CommandConfig;
|
std::string CommandConfig;
|
||||||
|
std::string Target;
|
||||||
cmLocalGenerator* LG;
|
cmLocalGenerator* LG;
|
||||||
bool OldStyle;
|
bool OldStyle;
|
||||||
bool MakeVars;
|
bool MakeVars;
|
||||||
|
@@ -4096,6 +4096,7 @@ void AddCustomCommandToTarget(cmLocalGenerator& lg,
|
|||||||
cc.SetDepfile(depfile);
|
cc.SetDepfile(depfile);
|
||||||
cc.SetJobPool(job_pool);
|
cc.SetJobPool(job_pool);
|
||||||
cc.SetCMP0116Status(cmp0116);
|
cc.SetCMP0116Status(cmp0116);
|
||||||
|
cc.SetTarget(target->GetName());
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case cmCustomCommandType::PRE_BUILD:
|
case cmCustomCommandType::PRE_BUILD:
|
||||||
target->AddPreBuildCommand(std::move(cc));
|
target->AddPreBuildCommand(std::move(cc));
|
||||||
|
@@ -43,3 +43,20 @@ if(NOT RunCMake_GENERATOR STREQUAL "Ninja Multi-Config")
|
|||||||
unset(RunCMake_TEST_BINARY_DIR)
|
unset(RunCMake_TEST_BINARY_DIR)
|
||||||
unset(RunCMake_TEST_NO_CLEAN)
|
unset(RunCMake_TEST_NO_CLEAN)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
function(test_genex name)
|
||||||
|
run_cmake(${name})
|
||||||
|
|
||||||
|
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${name}-build")
|
||||||
|
set(RunCMake_TEST_NO_CLEAN 1)
|
||||||
|
run_cmake_command(${name}-build ${CMAKE_COMMAND} --build .)
|
||||||
|
|
||||||
|
if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/wdir/touched")
|
||||||
|
message(SEND_ERROR "File not created by target-dependent add_custom_command()!")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
unset(RunCMake_TEST_NO_CLEAN)
|
||||||
|
unset(RunCMake_TEST_BINARY_DIR)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
test_genex(TargetGenexEvent)
|
||||||
|
10
Tests/RunCMake/add_custom_command/TargetGenexEvent.cmake
Normal file
10
Tests/RunCMake/add_custom_command/TargetGenexEvent.cmake
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
add_custom_target(target ALL)
|
||||||
|
set_target_properties(target PROPERTIES COMPILE_DEFINITIONS "touched" COMPILE_OPTIONS "${CMAKE_BINARY_DIR}/wdir")
|
||||||
|
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/wdir")
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
TARGET target
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E touch $<TARGET_PROPERTY:COMPILE_DEFINITIONS>
|
||||||
|
WORKING_DIRECTORY $<TARGET_PROPERTY:COMPILE_OPTIONS>
|
||||||
|
)
|
Reference in New Issue
Block a user