summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaul Tambre <raul@tambre.ee>2020-12-19 12:14:18 (GMT)
committerRaul Tambre <raul@tambre.ee>2021-05-31 07:39:58 (GMT)
commit1cb4f592a09752972d89785c0e8f1e160d5b5c4e (patch)
tree0afc49c1b2e286cf9f24feb9da0b1f52b4a197f8
parent7676e11943a6446e3cdc60370a37e4ce9cc548d3 (diff)
downloadCMake-1cb4f592a09752972d89785c0e8f1e160d5b5c4e.zip
CMake-1cb4f592a09752972d89785c0e8f1e160d5b5c4e.tar.gz
CMake-1cb4f592a09752972d89785c0e8f1e160d5b5c4e.tar.bz2
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.
-rw-r--r--Help/command/add_custom_command.rst5
-rw-r--r--Help/release/dev/add_custom_command-TARGET-genex.rst5
-rw-r--r--Source/cmCustomCommand.cxx10
-rw-r--r--Source/cmCustomCommand.h5
-rw-r--r--Source/cmCustomCommandGenerator.cxx18
-rw-r--r--Source/cmCustomCommandGenerator.h1
-rw-r--r--Source/cmLocalGenerator.cxx1
-rw-r--r--Tests/RunCMake/add_custom_command/RunCMakeTest.cmake17
-rw-r--r--Tests/RunCMake/add_custom_command/TargetGenexEvent.cmake10
9 files changed, 65 insertions, 7 deletions
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst
index 569f1e8..a053e59 100644
--- a/Help/command/add_custom_command.rst
+++ b/Help/command/add_custom_command.rst
@@ -338,6 +338,8 @@ will re-run whenever ``in.txt`` changes.
where ``<config>`` is the build configuration, and then compile the generated
source as part of a library.
+.. _`add_custom_command(TARGET)`:
+
Build Events
^^^^^^^^^^^^
@@ -388,6 +390,9 @@ of the following is specified:
This allows to add individual build events for every configuration.
+.. versionadded:: 3.21
+ Support for target-dependent generator expressions.
+
Examples: Build Events
^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Help/release/dev/add_custom_command-TARGET-genex.rst b/Help/release/dev/add_custom_command-TARGET-genex.rst
new file mode 100644
index 0000000..86f8b36
--- /dev/null
+++ b/Help/release/dev/add_custom_command-TARGET-genex.rst
@@ -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.
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index f6b9989..ec60ff7 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -150,3 +150,13 @@ void cmCustomCommand::SetCMP0116Status(cmPolicies::PolicyStatus cmp0116)
{
this->CMP0116Status = cmp0116;
}
+
+const std::string& cmCustomCommand::GetTarget() const
+{
+ return this->Target;
+}
+
+void cmCustomCommand::SetTarget(const std::string& target)
+{
+ this->Target = target;
+}
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index e22c7a4..5cbd3d1 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -100,6 +100,10 @@ public:
cmPolicies::PolicyStatus GetCMP0116Status() const;
void SetCMP0116Status(cmPolicies::PolicyStatus cmp0116);
+ /** Set/Get the associated target */
+ const std::string& GetTarget() const;
+ void SetTarget(const std::string& target);
+
private:
std::vector<std::string> Outputs;
std::vector<std::string> Byproducts;
@@ -107,6 +111,7 @@ private:
cmCustomCommandLines CommandLines;
cmListFileBacktrace Backtrace;
cmImplicitDependsList ImplicitDepends;
+ std::string Target;
std::string Comment;
std::string WorkingDirectory;
std::string Depfile;
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 1054beb..77779ba 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -29,7 +29,7 @@ namespace {
std::string EvaluateSplitConfigGenex(
cm::string_view input, cmGeneratorExpression const& ge, cmLocalGenerator* lg,
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::string result;
@@ -87,7 +87,7 @@ std::string EvaluateSplitConfigGenex(
// Evaluate this genex in the selected configuration.
std::unique_ptr<cmCompiledGeneratorExpression> cge =
ge.Parse(std::string(genex));
- result += cge->Evaluate(lg, *config);
+ result += cge->Evaluate(lg, *config, target);
// Record targets referenced by the genex.
if (utils) {
@@ -114,7 +114,8 @@ std::vector<std::string> EvaluateDepends(std::vector<std::string> const& paths,
std::string const& ep =
EvaluateSplitConfigGenex(p, ge, lg, /*useOutputConfig=*/true,
/*outputConfig=*/outputConfig,
- /*commandConfig=*/commandConfig);
+ /*commandConfig=*/commandConfig,
+ /*target=*/nullptr);
cm::append(depends, cmExpandedList(ep));
}
for (std::string& p : depends) {
@@ -157,6 +158,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
: CC(&cc)
, OutputConfig(crossConfig ? *crossConfig : config)
, CommandConfig(std::move(config))
+ , Target(cc.GetTarget())
, LG(lg)
, OldStyle(cc.GetEscapeOldStyle())
, MakeVars(cc.GetEscapeAllowMakeVars())
@@ -171,6 +173,8 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
}
cmGeneratorExpression ge(cc.GetBacktrace());
+ cmGeneratorTarget const* target{ lg->FindGeneratorTargetToUse(
+ this->Target) };
const cmCustomCommandLines& cmdlines = this->CC->GetCommandLines();
for (cmCustomCommandLine const& cmdline : cmdlines) {
@@ -180,7 +184,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
for (std::string const& clarg : cmdline) {
std::string parsed_arg = EvaluateSplitConfigGenex(
clarg, ge, this->LG, useOutputConfig, this->OutputConfig,
- this->CommandConfig, &this->Utilities);
+ this->CommandConfig, target, &this->Utilities);
if (this->CC->GetCommandExpandLists()) {
cm::append(argv, cmExpandedList(parsed_arg));
} else {
@@ -249,9 +253,9 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
const std::string& workingdirectory = this->CC->GetWorkingDirectory();
if (!workingdirectory.empty()) {
- this->WorkingDirectory =
- EvaluateSplitConfigGenex(workingdirectory, ge, this->LG, true,
- this->OutputConfig, this->CommandConfig);
+ this->WorkingDirectory = EvaluateSplitConfigGenex(
+ workingdirectory, ge, this->LG, true, this->OutputConfig,
+ this->CommandConfig, target);
// Convert working directory to a full path.
if (!this->WorkingDirectory.empty()) {
std::string const& build_dir = this->LG->GetCurrentBinaryDirectory();
diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h
index e70909a..73a8d38 100644
--- a/Source/cmCustomCommandGenerator.h
+++ b/Source/cmCustomCommandGenerator.h
@@ -25,6 +25,7 @@ class cmCustomCommandGenerator
cmCustomCommand const* CC;
std::string OutputConfig;
std::string CommandConfig;
+ std::string Target;
cmLocalGenerator* LG;
bool OldStyle;
bool MakeVars;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 0c686aa..6a49b84 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -4096,6 +4096,7 @@ void AddCustomCommandToTarget(cmLocalGenerator& lg,
cc.SetDepfile(depfile);
cc.SetJobPool(job_pool);
cc.SetCMP0116Status(cmp0116);
+ cc.SetTarget(target->GetName());
switch (type) {
case cmCustomCommandType::PRE_BUILD:
target->AddPreBuildCommand(std::move(cc));
diff --git a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
index 9c59b4b..ad6b258 100644
--- a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
@@ -43,3 +43,20 @@ if(NOT RunCMake_GENERATOR STREQUAL "Ninja Multi-Config")
unset(RunCMake_TEST_BINARY_DIR)
unset(RunCMake_TEST_NO_CLEAN)
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)
diff --git a/Tests/RunCMake/add_custom_command/TargetGenexEvent.cmake b/Tests/RunCMake/add_custom_command/TargetGenexEvent.cmake
new file mode 100644
index 0000000..8591b74
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/TargetGenexEvent.cmake
@@ -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>
+)