diff options
author | Kyle Edwards <kyle.edwards@kitware.com> | 2021-01-07 11:03:25 -0500 |
---|---|---|
committer | Kyle Edwards <kyle.edwards@kitware.com> | 2021-01-07 11:26:17 -0500 |
commit | 98805a11ce8010810b9be89a019841752f6b34f4 (patch) | |
tree | ff59ce61bb1c6eccc82295aaee3f09c06d544787 | |
parent | 1c9b61c23edb8200400ac77585f94ccd9fe0e58f (diff) | |
download | cmake-98805a11ce8010810b9be89a019841752f6b34f4.tar.gz |
Ninja Multi-Config: Run POST_BUILD when BYPRODUCTS don't overlap
Fixes: #21252
-rw-r--r-- | Help/generator/Ninja Multi-Config.rst | 31 | ||||
-rw-r--r-- | Source/cmLocalNinjaGenerator.cxx | 13 | ||||
-rw-r--r-- | Source/cmLocalNinjaGenerator.h | 3 | ||||
-rw-r--r-- | Source/cmNinjaNormalTargetGenerator.cxx | 20 | ||||
-rw-r--r-- | Tests/RunCMake/NinjaMultiConfig/PostBuild-debug-in-release-graph-build-stdout.txt | 2 | ||||
-rw-r--r-- | Tests/RunCMake/NinjaMultiConfig/PostBuild-release-build-stdout.txt | 3 | ||||
-rw-r--r-- | Tests/RunCMake/NinjaMultiConfig/PostBuild.cmake | 6 | ||||
-rw-r--r-- | Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake | 6 |
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) |