From f6574c9a816ffda7d9ff8c3f2e4ce0485cf28894 Mon Sep 17 00:00:00 2001 From: Daniel Eiband Date: Wed, 11 Sep 2019 12:45:50 +0200 Subject: Depend: Hook up automatic target-level dependencies via byproducts Target-level dependencies to utility targets are added from another target if the other target requires a byproduct of the utility target or if it requires a byproduct of PRE_BUILD, PRE_LINK, or POST_BUILD build events of a target. Issue: #19005 --- Help/command/add_custom_command.rst | 6 +++--- Help/command/add_custom_target.rst | 6 +++--- Source/cmGeneratorTarget.cxx | 35 +++++++++++++++++++++++------------ 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index ed321fc..ab2a023 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -68,9 +68,6 @@ The options are: order-only dependencies to ensure the byproducts will be available before their dependents build. - The ``BYPRODUCTS`` option is ignored on non-Ninja generators - except to mark byproducts ``GENERATED``. - ``COMMAND`` Specify the command-line(s) to execute at build time. If more than one ``COMMAND`` is specified they will be executed in order, @@ -111,6 +108,9 @@ The options are: an ``OUTPUT`` of another custom command in the same directory (``CMakeLists.txt`` file) CMake automatically brings the other custom command into the target in which this command is built. + A target-level dependency is added if any dependency is listed as + ``BYPRODUCTS`` of a target or any of its build events in the same + directory to ensure the byproducts will be available. If ``DEPENDS`` is not specified the command will run whenever the ``OUTPUT`` is missing; if the command does not actually create the ``OUTPUT`` then the rule will always run. diff --git a/Help/command/add_custom_target.rst b/Help/command/add_custom_target.rst index 08b9516..e74960c 100644 --- a/Help/command/add_custom_target.rst +++ b/Help/command/add_custom_target.rst @@ -49,9 +49,6 @@ The options are: order-only dependencies to ensure the byproducts will be available before their dependents build. - The ``BYPRODUCTS`` option is ignored on non-Ninja generators - except to mark byproducts ``GENERATED``. - ``COMMAND`` Specify the command-line(s) to execute at build time. If more than one ``COMMAND`` is specified they will be executed in order, @@ -86,6 +83,9 @@ The options are: :command:`add_custom_command` command calls in the same directory (``CMakeLists.txt`` file). They will be brought up to date when the target is built. + A target-level dependency is added if any dependency is a byproduct + of a target or any of its build events in the same directory to ensure + the byproducts will be available before this target is built. Use the :command:`add_dependencies` command to add dependencies on other targets. diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index fa04fbb..b019e0b 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -2599,7 +2599,7 @@ private: SourceEntry* CurrentEntry; std::queue SourceQueue; std::set SourcesQueued; - using NameMapType = std::map; + using NameMapType = std::map; NameMapType NameMap; std::vector NewSources; @@ -2705,19 +2705,30 @@ void cmTargetTraceDependencies::QueueSource(cmSourceFile* sf) void cmTargetTraceDependencies::FollowName(std::string const& name) { - auto i = this->NameMap.find(name); - if (i == this->NameMap.end()) { + // Use lower bound with key comparison to not repeat the search for the + // insert position if the name could not be found (which is the common case). + auto i = this->NameMap.lower_bound(name); + if (i == this->NameMap.end() || i->first != name) { // Check if we know how to generate this file. - cmSourceFile* sf = this->Makefile->GetSourceFileWithOutput(name); - NameMapType::value_type entry(name, sf); - i = this->NameMap.insert(entry).first; - } - if (cmSourceFile* sf = i->second) { - // Record the dependency we just followed. - if (this->CurrentEntry) { - this->CurrentEntry->Depends.push_back(sf); + cmSourcesWithOutput sources = this->Makefile->GetSourcesWithOutput(name); + i = this->NameMap.emplace_hint(i, name, sources); + } + if (cmTarget* t = i->second.Target) { + // The name is a byproduct of a utility target or a PRE_BUILD, PRE_LINK, or + // POST_BUILD command. + this->GeneratorTarget->Target->AddUtility(t->GetName()); + } + if (cmSourceFile* sf = i->second.Source) { + // For now only follow the dependency if the source file is not a + // byproduct. Semantics of byproducts in a non-Ninja context will have to + // be defined first. + if (!i->second.SourceIsByproduct) { + // Record the dependency we just followed. + if (this->CurrentEntry) { + this->CurrentEntry->Depends.push_back(sf); + } + this->QueueSource(sf); } - this->QueueSource(sf); } } -- cgit v0.12