summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Edwards <kyle.edwards@kitware.com>2021-01-07 11:03:25 -0500
committerKyle Edwards <kyle.edwards@kitware.com>2021-01-07 11:26:17 -0500
commit98805a11ce8010810b9be89a019841752f6b34f4 (patch)
treeff59ce61bb1c6eccc82295aaee3f09c06d544787
parent1c9b61c23edb8200400ac77585f94ccd9fe0e58f (diff)
downloadcmake-98805a11ce8010810b9be89a019841752f6b34f4.tar.gz
Ninja Multi-Config: Run POST_BUILD when BYPRODUCTS don't overlap
Fixes: #21252
-rw-r--r--Help/generator/Ninja Multi-Config.rst31
-rw-r--r--Source/cmLocalNinjaGenerator.cxx13
-rw-r--r--Source/cmLocalNinjaGenerator.h3
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx20
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/PostBuild-debug-in-release-graph-build-stdout.txt2
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/PostBuild-release-build-stdout.txt3
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/PostBuild.cmake6
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake6
8 files changed, 69 insertions, 15 deletions
diff --git a/Help/generator/Ninja Multi-Config.rst b/Help/generator/Ninja Multi-Config.rst
index d1df42b55b..89011925f8 100644
--- a/Help/generator/Ninja Multi-Config.rst
+++ b/Help/generator/Ninja Multi-Config.rst
@@ -130,3 +130,34 @@ output config using the ``Release`` command config. The ``Release`` build of
the ``generator`` target is called with ``Debug.txt Debug Release`` as
arguments. The command depends on the ``Release`` builds of ``tgt1`` and
``tgt4``, and the ``Debug`` builds of ``tgt2`` and ``tgt3``.
+
+``PRE_BUILD``, ``PRE_LINK``, and ``POST_BUILD`` custom commands for targets
+only get run in their "native" configuration (the ``Release`` configuration in
+the ``build-Release.ninja`` file) unless they have no ``BYPRODUCTS`` or their
+``BYPRODUCTS`` are unique per config. Consider the following example:
+
+.. code-block:: cmake
+
+ add_executable(exe main.c)
+ add_custom_command(
+ TARGET exe
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo "Running no-byproduct command"
+ )
+ add_custom_command(
+ TARGET exe
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo "Running separate-byproduct command for $<CONFIG>"
+ BYPRODUCTS $<CONFIG>.txt
+ )
+ add_custom_command(
+ TARGET exe
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo "Running common-byproduct command for $<CONFIG>"
+ BYPRODUCTS exe.txt
+ )
+
+In this example, if you build ``exe:Debug`` in ``build-Release.ninja``, the
+first and second custom commands get run, since their byproducts are unique
+per-config, but the last custom command does not. However, if you build
+``exe:Release`` in ``build-Release.ninja``, all three custom commands get run.
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 5a747e5fdd..7229101a83 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -693,13 +693,11 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
}
}
-namespace {
-bool HasUniqueByproducts(cmLocalGenerator& lg,
- std::vector<std::string> const& byproducts,
- cmListFileBacktrace const& bt)
+bool cmLocalNinjaGenerator::HasUniqueByproducts(
+ std::vector<std::string> const& byproducts, cmListFileBacktrace const& bt)
{
std::vector<std::string> configs =
- lg.GetMakefile()->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
+ this->GetMakefile()->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
cmGeneratorExpression ge(bt);
for (std::string const& p : byproducts) {
if (cmGeneratorExpression::Find(p) == std::string::npos) {
@@ -709,7 +707,7 @@ bool HasUniqueByproducts(cmLocalGenerator& lg,
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(p);
for (std::string const& config : configs) {
for (std::string const& b :
- lg.ExpandCustomCommandOutputPaths(*cge, config)) {
+ this->ExpandCustomCommandOutputPaths(*cge, config)) {
if (!seen.insert(b).second) {
return false;
}
@@ -719,6 +717,7 @@ bool HasUniqueByproducts(cmLocalGenerator& lg,
return true;
}
+namespace {
bool HasUniqueOutputs(std::vector<cmCustomCommandGenerator> const& ccgs)
{
std::set<std::string> allOutputs;
@@ -746,7 +745,7 @@ std::string cmLocalNinjaGenerator::CreateUtilityOutput(
// In Ninja Multi-Config, we can only produce cross-config utility
// commands if all byproducts are per-config.
if (!this->GetGlobalGenerator()->IsMultiConfig() ||
- !HasUniqueByproducts(*this, byproducts, bt)) {
+ !this->HasUniqueByproducts(byproducts, bt)) {
return this->cmLocalGenerator::CreateUtilityOutput(targetName, byproducts,
bt);
}
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index 87d5e53a05..5b850f3d09 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -86,6 +86,9 @@ public:
cmNinjaDeps& ninjaDeps,
const std::string& config);
+ bool HasUniqueByproducts(std::vector<std::string> const& byproducts,
+ cmListFileBacktrace const& bt);
+
protected:
std::string ConvertToIncludeReference(
std::string const& path,
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 620b8ffde3..49e5e4cc65 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -12,6 +12,7 @@
#include <utility>
#include <cm/memory>
+#include <cm/optional>
#include <cm/vector>
#include "cmComputeLinkInformation.h"
@@ -1238,14 +1239,17 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
std::vector<std::string> preLinkCmdLines;
std::vector<std::string> postBuildCmdLines;
- if (config == fileConfig) {
- std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines,
- &preLinkCmdLines,
- &postBuildCmdLines };
-
- for (unsigned i = 0; i != 3; ++i) {
- for (cmCustomCommand const& cc : *cmdLists[i]) {
- cmCustomCommandGenerator ccg(cc, config, this->GetLocalGenerator());
+ std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines,
+ &preLinkCmdLines,
+ &postBuildCmdLines };
+
+ for (unsigned i = 0; i != 3; ++i) {
+ for (cmCustomCommand const& cc : *cmdLists[i]) {
+ if (config == fileConfig ||
+ this->GetLocalGenerator()->HasUniqueByproducts(cc.GetByproducts(),
+ cc.GetBacktrace())) {
+ cmCustomCommandGenerator ccg(cc, fileConfig, this->GetLocalGenerator(),
+ true, config);
localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]);
std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
std::transform(ccByproducts.begin(), ccByproducts.end(),
diff --git a/Tests/RunCMake/NinjaMultiConfig/PostBuild-debug-in-release-graph-build-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/PostBuild-debug-in-release-graph-build-stdout.txt
new file mode 100644
index 0000000000..fad923ac01
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/PostBuild-debug-in-release-graph-build-stdout.txt
@@ -0,0 +1,2 @@
+Running post-build command with Debug
+Generating Debug\.txt
diff --git a/Tests/RunCMake/NinjaMultiConfig/PostBuild-release-build-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/PostBuild-release-build-stdout.txt
new file mode 100644
index 0000000000..485a52c23e
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/PostBuild-release-build-stdout.txt
@@ -0,0 +1,3 @@
+Running post-build command with Release
+Generating out\.txt with Release
+Generating Release\.txt
diff --git a/Tests/RunCMake/NinjaMultiConfig/PostBuild.cmake b/Tests/RunCMake/NinjaMultiConfig/PostBuild.cmake
new file mode 100644
index 0000000000..5fcff74637
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/PostBuild.cmake
@@ -0,0 +1,6 @@
+enable_language(C)
+
+add_executable(Exe main.c)
+add_custom_command(TARGET Exe POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Running post-build command with $<CONFIG>")
+add_custom_command(TARGET Exe POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Generating out.txt with $<CONFIG>" BYPRODUCTS out.txt)
+add_custom_command(TARGET Exe POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Generating $<CONFIG>.txt" BYPRODUCTS $<CONFIG>.txt)
diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
index dc2db57bbe..480d628fa2 100644
--- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
@@ -187,6 +187,12 @@ run_ninja(SimpleCrossConfigs clean-all-in-release-graph build-Release.ninja clea
run_cmake_build(SimpleCrossConfigs all-all-in-release-graph Release all:all)
run_cmake_build(SimpleCrossConfigs all-relwithdebinfo-in-release-graph Release all:RelWithDebInfo)
+set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/PostBuild-build)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all")
+run_cmake_configure(PostBuild)
+run_cmake_build(PostBuild release Release Exe)
+run_cmake_build(PostBuild debug-in-release-graph Release Exe:Debug)
+
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Framework-build)
set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all")
run_cmake_configure(Framework)