1
0
Эх сурвалжийг харах

Merge topic 'refactor-custom-command-output-lookup'

953f4d503d cmMakefile: Consolidate CreateGenerated{Outputs,Byproducts}
0090a11a42 cmLocalGenerator: Migrate custom command output lookup from cmMakefile
26464da5d3 cmMakefile: Drop unnecessary custom command APPEND check

Acked-by: Kitware Robot <[email protected]>
Merge-request: !5347
Brad King 5 жил өмнө
parent
commit
c960674e24

+ 3 - 10
Source/cmAddCustomCommandCommand.cxx

@@ -314,16 +314,9 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
 
 
   // Check for an append request.
   // Check for an append request.
   if (append) {
   if (append) {
-    if (mf.AppendCustomCommandToOutput(output[0], depends, implicit_depends,
-                                       commandLines)) {
-      return true;
-    }
-
-    // No command for this output exists.
-    status.SetError(
-      cmStrCat("given APPEND option with output\n  ", output[0],
-               "\nwhich is not already a custom command output."));
-    return false;
+    mf.AppendCustomCommandToOutput(output[0], depends, implicit_depends,
+                                   commandLines);
+    return true;
   }
   }
 
 
   if (uses_terminal && !job_pool.empty()) {
   if (uses_terminal && !job_pool.empty()) {

+ 3 - 2
Source/cmGeneratorTarget.cxx

@@ -2986,7 +2986,8 @@ void cmTargetTraceDependencies::FollowName(std::string const& name)
   auto i = this->NameMap.lower_bound(name);
   auto i = this->NameMap.lower_bound(name);
   if (i == this->NameMap.end() || i->first != name) {
   if (i == this->NameMap.end() || i->first != name) {
     // Check if we know how to generate this file.
     // Check if we know how to generate this file.
-    cmSourcesWithOutput sources = this->Makefile->GetSourcesWithOutput(name);
+    cmSourcesWithOutput sources =
+      this->LocalGenerator->GetSourcesWithOutput(name);
     // If we failed to find a target or source and we have a relative path, it
     // If we failed to find a target or source and we have a relative path, it
     // might be a valid source if made relative to the current binary
     // might be a valid source if made relative to the current binary
     // directory.
     // directory.
@@ -2996,7 +2997,7 @@ void cmTargetTraceDependencies::FollowName(std::string const& name)
         cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', name);
         cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', name);
       fullname = cmSystemTools::CollapseFullPath(
       fullname = cmSystemTools::CollapseFullPath(
         fullname, this->Makefile->GetHomeOutputDirectory());
         fullname, this->Makefile->GetHomeOutputDirectory());
-      sources = this->Makefile->GetSourcesWithOutput(fullname);
+      sources = this->LocalGenerator->GetSourcesWithOutput(fullname);
     }
     }
     i = this->NameMap.emplace_hint(i, name, sources);
     i = this->NameMap.emplace_hint(i, name, sources);
   }
   }

+ 3 - 3
Source/cmGhsMultiTargetGenerator.cxx

@@ -763,9 +763,9 @@ bool cmGhsMultiTargetGenerator::VisitCustomCommand(
     /* set temporary mark; check if revisit*/
     /* set temporary mark; check if revisit*/
     if (temp.insert(si).second) {
     if (temp.insert(si).second) {
       for (auto& di : si->GetCustomCommand()->GetDepends()) {
       for (auto& di : si->GetCustomCommand()->GetDepends()) {
-        cmSourceFile const* sf = this->GeneratorTarget->GetLocalGenerator()
-                                   ->GetMakefile()
-                                   ->GetSourceFileWithOutput(di);
+        cmSourceFile const* sf =
+          this->GeneratorTarget->GetLocalGenerator()->GetSourceFileWithOutput(
+            di);
         /* if sf exists then visit */
         /* if sf exists then visit */
         if (sf && this->VisitCustomCommand(temp, perm, order, sf)) {
         if (sf && this->VisitCustomCommand(temp, perm, order, sf)) {
           return true;
           return true;

+ 193 - 7
Source/cmLocalGenerator.cxx

@@ -3918,10 +3918,35 @@ cmSourceFile* AddCustomCommand(
     cc->SetJobPool(job_pool);
     cc->SetJobPool(job_pool);
     file->SetCustomCommand(std::move(cc));
     file->SetCustomCommand(std::move(cc));
 
 
-    mf->AddSourceOutputs(file, outputs, byproducts);
+    lg.AddSourceOutputs(file, outputs, byproducts);
   }
   }
   return file;
   return file;
 }
 }
+
+bool AnyOutputMatches(const std::string& name,
+                      const std::vector<std::string>& outputs)
+{
+  for (std::string const& output : outputs) {
+    std::string::size_type pos = output.rfind(name);
+    // If the output matches exactly
+    if (pos != std::string::npos && pos == output.size() - name.size() &&
+        (pos == 0 || output[pos - 1] == '/')) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool AnyTargetCommandOutputMatches(
+  const std::string& name, const std::vector<cmCustomCommand>& commands)
+{
+  for (cmCustomCommand const& command : commands) {
+    if (AnyOutputMatches(name, command.GetByproducts())) {
+      return true;
+    }
+  }
+  return false;
+}
 }
 }
 
 
 namespace detail {
 namespace detail {
@@ -3937,8 +3962,6 @@ void AddCustomCommandToTarget(cmLocalGenerator& lg,
                               const std::string& job_pool,
                               const std::string& job_pool,
                               bool command_expand_lists, bool stdPipesUTF8)
                               bool command_expand_lists, bool stdPipesUTF8)
 {
 {
-  cmMakefile* mf = lg.GetMakefile();
-
   // Always create the byproduct sources and mark them generated.
   // Always create the byproduct sources and mark them generated.
   CreateGeneratedSources(lg, byproducts, origin, lfbt);
   CreateGeneratedSources(lg, byproducts, origin, lfbt);
 
 
@@ -3964,7 +3987,7 @@ void AddCustomCommandToTarget(cmLocalGenerator& lg,
       break;
       break;
   }
   }
 
 
-  mf->AddTargetByproducts(target, byproducts);
+  lg.AddTargetByproducts(target, byproducts);
 }
 }
 
 
 cmSourceFile* AddCustomCommandToOutput(
 cmSourceFile* AddCustomCommandToOutput(
@@ -3996,7 +4019,7 @@ void AppendCustomCommandToOutput(cmLocalGenerator& lg,
                                  const cmCustomCommandLines& commandLines)
                                  const cmCustomCommandLines& commandLines)
 {
 {
   // Lookup an existing command.
   // Lookup an existing command.
-  if (cmSourceFile* sf = lg.GetMakefile()->GetSourceFileWithOutput(output)) {
+  if (cmSourceFile* sf = lg.GetSourceFileWithOutput(output)) {
     if (cmCustomCommand* cc = sf->GetCustomCommand()) {
     if (cmCustomCommand* cc = sf->GetCustomCommand()) {
       cc->AppendCommands(commandLines);
       cc->AppendCommands(commandLines);
       cc->AppendDepends(depends);
       cc->AppendDepends(depends);
@@ -4008,7 +4031,7 @@ void AppendCustomCommandToOutput(cmLocalGenerator& lg,
   // No existing command found.
   // No existing command found.
   lg.GetCMakeInstance()->IssueMessage(
   lg.GetCMakeInstance()->IssueMessage(
     MessageType::FATAL_ERROR,
     MessageType::FATAL_ERROR,
-    cmStrCat("Attempt to append to output\n  ", output,
+    cmStrCat("Attempt to APPEND to custom command with output\n  ", output,
              "\nwhich is not already a custom command output."),
              "\nwhich is not already a custom command output."),
     lfbt);
     lfbt);
 }
 }
@@ -4040,7 +4063,7 @@ void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
     /*replace=*/false, escapeOldStyle, uses_terminal, command_expand_lists,
     /*replace=*/false, escapeOldStyle, uses_terminal, command_expand_lists,
     /*depfile=*/"", job_pool, stdPipesUTF8);
     /*depfile=*/"", job_pool, stdPipesUTF8);
   if (rule) {
   if (rule) {
-    lg.GetMakefile()->AddTargetByproducts(target, byproducts);
+    lg.AddTargetByproducts(target, byproducts);
   }
   }
 
 
   if (!force.NameCMP0049.empty()) {
   if (!force.NameCMP0049.empty()) {
@@ -4088,3 +4111,166 @@ std::vector<std::string> ComputeISPCExtraObjects(
   return computedObjects;
   return computedObjects;
 }
 }
 }
 }
+
+cmSourcesWithOutput cmLocalGenerator::GetSourcesWithOutput(
+  const std::string& name) const
+{
+  // Linear search?  Also see GetSourceFileWithOutput for detail.
+  if (!cmSystemTools::FileIsFullPath(name)) {
+    cmSourcesWithOutput sources;
+    sources.Target = this->LinearGetTargetWithOutput(name);
+    sources.Source = this->LinearGetSourceFileWithOutput(
+      name, cmSourceOutputKind::OutputOrByproduct, sources.SourceIsByproduct);
+    return sources;
+  }
+  // Otherwise we use an efficient lookup map.
+  auto o = this->OutputToSource.find(name);
+  if (o != this->OutputToSource.end()) {
+    return o->second.Sources;
+  }
+  return {};
+}
+
+cmSourceFile* cmLocalGenerator::GetSourceFileWithOutput(
+  const std::string& name, cmSourceOutputKind kind) const
+{
+  // If the queried path is not absolute we use the backward compatible
+  // linear-time search for an output with a matching suffix.
+  if (!cmSystemTools::FileIsFullPath(name)) {
+    bool byproduct = false;
+    return this->LinearGetSourceFileWithOutput(name, kind, byproduct);
+  }
+  // Otherwise we use an efficient lookup map.
+  auto o = this->OutputToSource.find(name);
+  if (o != this->OutputToSource.end() &&
+      (!o->second.Sources.SourceIsByproduct ||
+       kind == cmSourceOutputKind::OutputOrByproduct)) {
+    // Source file could also be null pointer for example if we found the
+    // byproduct of a utility target, a PRE_BUILD, PRE_LINK, or POST_BUILD
+    // command of a target, or a not yet created custom command.
+    return o->second.Sources.Source;
+  }
+  return nullptr;
+}
+
+void cmLocalGenerator::AddTargetByproducts(
+  cmTarget* target, const std::vector<std::string>& byproducts)
+{
+  for (std::string const& o : byproducts) {
+    this->UpdateOutputToSourceMap(o, target);
+  }
+}
+
+void cmLocalGenerator::AddSourceOutputs(
+  cmSourceFile* source, const std::vector<std::string>& outputs,
+  const std::vector<std::string>& byproducts)
+{
+  for (std::string const& o : outputs) {
+    this->UpdateOutputToSourceMap(o, source, false);
+  }
+  for (std::string const& o : byproducts) {
+    this->UpdateOutputToSourceMap(o, source, true);
+  }
+}
+
+void cmLocalGenerator::UpdateOutputToSourceMap(std::string const& byproduct,
+                                               cmTarget* target)
+{
+  SourceEntry entry;
+  entry.Sources.Target = target;
+
+  auto pr = this->OutputToSource.emplace(byproduct, entry);
+  if (!pr.second) {
+    SourceEntry& current = pr.first->second;
+    // Has the target already been set?
+    if (!current.Sources.Target) {
+      current.Sources.Target = target;
+    } else {
+      // Multiple custom commands/targets produce the same output (source file
+      // or target).  See also comment in other UpdateOutputToSourceMap
+      // overload.
+      //
+      // TODO: Warn the user about this case.
+    }
+  }
+}
+
+void cmLocalGenerator::UpdateOutputToSourceMap(std::string const& output,
+                                               cmSourceFile* source,
+                                               bool byproduct)
+{
+  SourceEntry entry;
+  entry.Sources.Source = source;
+  entry.Sources.SourceIsByproduct = byproduct;
+
+  auto pr = this->OutputToSource.emplace(output, entry);
+  if (!pr.second) {
+    SourceEntry& current = pr.first->second;
+    // Outputs take precedence over byproducts
+    if (!current.Sources.Source ||
+        (current.Sources.SourceIsByproduct && !byproduct)) {
+      current.Sources.Source = source;
+      current.Sources.SourceIsByproduct = false;
+    } else {
+      // Multiple custom commands produce the same output but may
+      // be attached to a different source file (MAIN_DEPENDENCY).
+      // LinearGetSourceFileWithOutput would return the first one,
+      // so keep the mapping for the first one.
+      //
+      // TODO: Warn the user about this case.  However, the VS 8 generator
+      // triggers it for separate generate.stamp rules in ZERO_CHECK and
+      // individual targets.
+    }
+  }
+}
+
+cmTarget* cmLocalGenerator::LinearGetTargetWithOutput(
+  const std::string& name) const
+{
+  // We go through the ordered vector of targets to get reproducible results
+  // should multiple names match.
+  for (cmTarget* t : this->Makefile->GetOrderedTargets()) {
+    // Does the output of any command match the source file name?
+    if (AnyTargetCommandOutputMatches(name, t->GetPreBuildCommands())) {
+      return t;
+    }
+    if (AnyTargetCommandOutputMatches(name, t->GetPreLinkCommands())) {
+      return t;
+    }
+    if (AnyTargetCommandOutputMatches(name, t->GetPostBuildCommands())) {
+      return t;
+    }
+  }
+  return nullptr;
+}
+
+cmSourceFile* cmLocalGenerator::LinearGetSourceFileWithOutput(
+  const std::string& name, cmSourceOutputKind kind, bool& byproduct) const
+{
+  // Outputs take precedence over byproducts.
+  byproduct = false;
+  cmSourceFile* fallback = nullptr;
+
+  // Look through all the source files that have custom commands and see if the
+  // custom command has the passed source file as an output.
+  for (const auto& src : this->Makefile->GetSourceFiles()) {
+    // Does this source file have a custom command?
+    if (src->GetCustomCommand()) {
+      // Does the output of the custom command match the source file name?
+      if (AnyOutputMatches(name, src->GetCustomCommand()->GetOutputs())) {
+        // Return the first matching output.
+        return src.get();
+      }
+      if (kind == cmSourceOutputKind::OutputOrByproduct) {
+        if (AnyOutputMatches(name, src->GetCustomCommand()->GetByproducts())) {
+          // Do not return the source yet as there might be a matching output.
+          fallback = src.get();
+        }
+      }
+    }
+  }
+
+  // Did we find a byproduct?
+  byproduct = fallback != nullptr;
+  return fallback;
+}

+ 73 - 0
Source/cmLocalGenerator.h

@@ -36,6 +36,24 @@ class cmState;
 class cmTarget;
 class cmTarget;
 class cmake;
 class cmake;
 
 
+/** Flag if byproducts shall also be considered.  */
+enum class cmSourceOutputKind
+{
+  OutputOnly,
+  OutputOrByproduct
+};
+
+/** Target and source file which have a specific output.  */
+struct cmSourcesWithOutput
+{
+  /** Target with byproduct.  */
+  cmTarget* Target = nullptr;
+
+  /** Source file with output or byproduct.  */
+  cmSourceFile* Source = nullptr;
+  bool SourceIsByproduct = false;
+};
+
 /** \class cmLocalGenerator
 /** \class cmLocalGenerator
  * \brief Create required build files for a directory.
  * \brief Create required build files for a directory.
  *
  *
@@ -337,6 +355,34 @@ public:
     bool command_expand_lists = false, const std::string& job_pool = "",
     bool command_expand_lists = false, const std::string& job_pool = "",
     bool stdPipesUTF8 = false);
     bool stdPipesUTF8 = false);
 
 
+  /**
+   * Add target byproducts.
+   */
+  void AddTargetByproducts(cmTarget* target,
+                           const std::vector<std::string>& byproducts);
+
+  /**
+   * Add source file outputs.
+   */
+  void AddSourceOutputs(cmSourceFile* source,
+                        const std::vector<std::string>& outputs,
+                        const std::vector<std::string>& byproducts);
+
+  /**
+   * Return the target if the provided source name is a byproduct of a utility
+   * target or a PRE_BUILD, PRE_LINK, or POST_BUILD command.
+   * Return the source file which has the provided source name as output.
+   */
+  cmSourcesWithOutput GetSourcesWithOutput(const std::string& name) const;
+
+  /**
+   * Is there a source file that has the provided source name as an output?
+   * If so then return it.
+   */
+  cmSourceFile* GetSourceFileWithOutput(
+    const std::string& name,
+    cmSourceOutputKind kind = cmSourceOutputKind::OutputOnly) const;
+
   std::string GetProjectName() const;
   std::string GetProjectName() const;
 
 
   /** Compute the language used to compile the given source file.  */
   /** Compute the language used to compile the given source file.  */
@@ -532,6 +578,33 @@ protected:
   bool BackwardsCompatibilityFinal;
   bool BackwardsCompatibilityFinal;
 
 
 private:
 private:
+  /**
+   * See LinearGetSourceFileWithOutput for background information
+   */
+  cmTarget* LinearGetTargetWithOutput(const std::string& name) const;
+
+  /**
+   * Generalized old version of GetSourceFileWithOutput kept for
+   * backward-compatibility. It implements a linear search and supports
+   * relative file paths. It is used as a fall back by GetSourceFileWithOutput
+   * and GetSourcesWithOutput.
+   */
+  cmSourceFile* LinearGetSourceFileWithOutput(const std::string& name,
+                                              cmSourceOutputKind kind,
+                                              bool& byproduct) const;
+  struct SourceEntry
+  {
+    cmSourcesWithOutput Sources;
+  };
+
+  // A map for fast output to input look up.
+  using OutputToSourceMap = std::unordered_map<std::string, SourceEntry>;
+  OutputToSourceMap OutputToSource;
+
+  void UpdateOutputToSourceMap(std::string const& byproduct, cmTarget* target);
+  void UpdateOutputToSourceMap(std::string const& output, cmSourceFile* source,
+                               bool byproduct);
+
   void AddSharedFlags(std::string& flags, const std::string& lang,
   void AddSharedFlags(std::string& flags, const std::string& lang,
                       bool shared);
                       bool shared);
   bool GetShouldUseOldFlags(bool shared, const std::string& lang) const;
   bool GetShouldUseOldFlags(bool shared, const std::string& lang) const;

+ 4 - 248
Source/cmMakefile.cxx

@@ -939,8 +939,6 @@ void cmMakefile::DoGenerate(cmLocalGenerator& lg)
     action.Value(lg, action.Backtrace);
     action.Value(lg, action.Backtrace);
   }
   }
   this->GeneratorActionsInvoked = true;
   this->GeneratorActionsInvoked = true;
-  this->DelayedOutputFiles.clear();
-  this->DelayedOutputFilesHaveGenex = false;
 
 
   // go through all configured files and see which ones still exist.
   // go through all configured files and see which ones still exist.
   // we don't want cmake to re-run if a configured file is created and deleted
   // we don't want cmake to re-run if a configured file is created and deleted
@@ -1104,7 +1102,7 @@ cmTarget* cmMakefile::AddCustomCommandToTarget(
   }
   }
 
 
   // Always create the byproduct sources and mark them generated.
   // Always create the byproduct sources and mark them generated.
-  this->CreateGeneratedByproducts(byproducts);
+  this->CreateGeneratedOutputs(byproducts);
 
 
   // Strings could be moved into the callback function with C++14.
   // Strings could be moved into the callback function with C++14.
   cm::optional<std::string> commentStr = MakeOptionalString(comment);
   cm::optional<std::string> commentStr = MakeOptionalString(comment);
@@ -1163,7 +1161,7 @@ void cmMakefile::AddCustomCommandToOutput(
 
 
   // Always create the output sources and mark them generated.
   // Always create the output sources and mark them generated.
   this->CreateGeneratedOutputs(outputs);
   this->CreateGeneratedOutputs(outputs);
-  this->CreateGeneratedByproducts(byproducts);
+  this->CreateGeneratedOutputs(byproducts);
 
 
   // Strings could be moved into the callback function with C++14.
   // Strings could be moved into the callback function with C++14.
   cm::optional<std::string> commentStr = MakeOptionalString(comment);
   cm::optional<std::string> commentStr = MakeOptionalString(comment);
@@ -1247,16 +1245,11 @@ void cmMakefile::AddCustomCommandOldStyle(
   }
   }
 }
 }
 
 
-bool cmMakefile::AppendCustomCommandToOutput(
+void cmMakefile::AppendCustomCommandToOutput(
   const std::string& output, const std::vector<std::string>& depends,
   const std::string& output, const std::vector<std::string>& depends,
   const cmImplicitDependsList& implicit_depends,
   const cmImplicitDependsList& implicit_depends,
   const cmCustomCommandLines& commandLines)
   const cmCustomCommandLines& commandLines)
 {
 {
-  // Check as good as we can if there will be a command for this output.
-  if (!this->MightHaveCustomCommand(output)) {
-    return false;
-  }
-
   // Validate custom commands.
   // Validate custom commands.
   if (this->ValidateCustomCommand(commandLines)) {
   if (this->ValidateCustomCommand(commandLines)) {
     // Dispatch command creation to allow generator expressions in outputs.
     // Dispatch command creation to allow generator expressions in outputs.
@@ -1267,8 +1260,6 @@ bool cmMakefile::AppendCustomCommandToOutput(
                                             implicit_depends, commandLines);
                                             implicit_depends, commandLines);
       });
       });
   }
   }
-
-  return true;
 }
 }
 
 
 cmUtilityOutput cmMakefile::GetUtilityOutput(cmTarget* target)
 cmUtilityOutput cmMakefile::GetUtilityOutput(cmTarget* target)
@@ -1313,7 +1304,7 @@ cmTarget* cmMakefile::AddUtilityCommand(
   this->GetOrCreateGeneratedSource(force.Name);
   this->GetOrCreateGeneratedSource(force.Name);
 
 
   // Always create the byproduct sources and mark them generated.
   // Always create the byproduct sources and mark them generated.
-  this->CreateGeneratedByproducts(byproducts);
+  this->CreateGeneratedOutputs(byproducts);
 
 
   // Strings could be moved into the callback function with C++14.
   // Strings could be moved into the callback function with C++14.
   cm::optional<std::string> commentStr = MakeOptionalString(comment);
   cm::optional<std::string> commentStr = MakeOptionalString(comment);
@@ -2154,213 +2145,6 @@ cmTarget* cmMakefile::AddNewUtilityTarget(const std::string& utilityName,
 }
 }
 
 
 namespace {
 namespace {
-bool AnyOutputMatches(const std::string& name,
-                      const std::vector<std::string>& outputs)
-{
-  for (std::string const& output : outputs) {
-    std::string::size_type pos = output.rfind(name);
-    // If the output matches exactly
-    if (pos != std::string::npos && pos == output.size() - name.size() &&
-        (pos == 0 || output[pos - 1] == '/')) {
-      return true;
-    }
-  }
-  return false;
-}
-
-bool AnyTargetCommandOutputMatches(
-  const std::string& name, const std::vector<cmCustomCommand>& commands)
-{
-  for (cmCustomCommand const& command : commands) {
-    if (AnyOutputMatches(name, command.GetByproducts())) {
-      return true;
-    }
-  }
-  return false;
-}
-}
-
-cmTarget* cmMakefile::LinearGetTargetWithOutput(const std::string& name) const
-{
-  // We go through the ordered vector of targets to get reproducible results
-  // should multiple names match.
-  for (cmTarget* t : this->OrderedTargets) {
-    // Does the output of any command match the source file name?
-    if (AnyTargetCommandOutputMatches(name, t->GetPreBuildCommands())) {
-      return t;
-    }
-    if (AnyTargetCommandOutputMatches(name, t->GetPreLinkCommands())) {
-      return t;
-    }
-    if (AnyTargetCommandOutputMatches(name, t->GetPostBuildCommands())) {
-      return t;
-    }
-  }
-  return nullptr;
-}
-
-cmSourceFile* cmMakefile::LinearGetSourceFileWithOutput(
-  const std::string& name, cmSourceOutputKind kind, bool& byproduct) const
-{
-  // Outputs take precedence over byproducts.
-  byproduct = false;
-  cmSourceFile* fallback = nullptr;
-
-  // Look through all the source files that have custom commands and see if the
-  // custom command has the passed source file as an output.
-  for (const auto& src : this->SourceFiles) {
-    // Does this source file have a custom command?
-    if (src->GetCustomCommand()) {
-      // Does the output of the custom command match the source file name?
-      if (AnyOutputMatches(name, src->GetCustomCommand()->GetOutputs())) {
-        // Return the first matching output.
-        return src.get();
-      }
-      if (kind == cmSourceOutputKind::OutputOrByproduct) {
-        if (AnyOutputMatches(name, src->GetCustomCommand()->GetByproducts())) {
-          // Do not return the source yet as there might be a matching output.
-          fallback = src.get();
-        }
-      }
-    }
-  }
-
-  // Did we find a byproduct?
-  byproduct = fallback != nullptr;
-  return fallback;
-}
-
-cmSourcesWithOutput cmMakefile::GetSourcesWithOutput(
-  const std::string& name) const
-{
-  // Linear search?  Also see GetSourceFileWithOutput for detail.
-  if (!cmSystemTools::FileIsFullPath(name)) {
-    cmSourcesWithOutput sources;
-    sources.Target = this->LinearGetTargetWithOutput(name);
-    sources.Source = this->LinearGetSourceFileWithOutput(
-      name, cmSourceOutputKind::OutputOrByproduct, sources.SourceIsByproduct);
-    return sources;
-  }
-  // Otherwise we use an efficient lookup map.
-  auto o = this->OutputToSource.find(name);
-  if (o != this->OutputToSource.end()) {
-    return o->second.Sources;
-  }
-  return {};
-}
-
-cmSourceFile* cmMakefile::GetSourceFileWithOutput(
-  const std::string& name, cmSourceOutputKind kind) const
-{
-  // If the queried path is not absolute we use the backward compatible
-  // linear-time search for an output with a matching suffix.
-  if (!cmSystemTools::FileIsFullPath(name)) {
-    bool byproduct = false;
-    return this->LinearGetSourceFileWithOutput(name, kind, byproduct);
-  }
-  // Otherwise we use an efficient lookup map.
-  auto o = this->OutputToSource.find(name);
-  if (o != this->OutputToSource.end() &&
-      (!o->second.Sources.SourceIsByproduct ||
-       kind == cmSourceOutputKind::OutputOrByproduct)) {
-    // Source file could also be null pointer for example if we found the
-    // byproduct of a utility target, a PRE_BUILD, PRE_LINK, or POST_BUILD
-    // command of a target, or a not yet created custom command.
-    return o->second.Sources.Source;
-  }
-  return nullptr;
-}
-
-bool cmMakefile::MightHaveCustomCommand(const std::string& name) const
-{
-  if (this->DelayedOutputFilesHaveGenex ||
-      cmGeneratorExpression::Find(name) != std::string::npos) {
-    // Could be more restrictive, but for now we assume that there could always
-    // be a match when generator expressions are involved.
-    return true;
-  }
-  // Also see LinearGetSourceFileWithOutput.
-  if (!cmSystemTools::FileIsFullPath(name)) {
-    return AnyOutputMatches(name, this->DelayedOutputFiles);
-  }
-  // Otherwise we use an efficient lookup map.
-  auto o = this->OutputToSource.find(name);
-  if (o != this->OutputToSource.end()) {
-    return o->second.SourceMightBeOutput;
-  }
-  return false;
-}
-
-void cmMakefile::AddTargetByproducts(
-  cmTarget* target, const std::vector<std::string>& byproducts)
-{
-  for (std::string const& o : byproducts) {
-    this->UpdateOutputToSourceMap(o, target);
-  }
-}
-
-void cmMakefile::AddSourceOutputs(cmSourceFile* source,
-                                  const std::vector<std::string>& outputs,
-                                  const std::vector<std::string>& byproducts)
-{
-  for (std::string const& o : outputs) {
-    this->UpdateOutputToSourceMap(o, source, false);
-  }
-  for (std::string const& o : byproducts) {
-    this->UpdateOutputToSourceMap(o, source, true);
-  }
-}
-
-void cmMakefile::UpdateOutputToSourceMap(std::string const& byproduct,
-                                         cmTarget* target)
-{
-  SourceEntry entry;
-  entry.Sources.Target = target;
-
-  auto pr = this->OutputToSource.emplace(byproduct, entry);
-  if (!pr.second) {
-    SourceEntry& current = pr.first->second;
-    // Has the target already been set?
-    if (!current.Sources.Target) {
-      current.Sources.Target = target;
-    } else {
-      // Multiple custom commands/targets produce the same output (source file
-      // or target).  See also comment in other UpdateOutputToSourceMap
-      // overload.
-      //
-      // TODO: Warn the user about this case.
-    }
-  }
-}
-
-void cmMakefile::UpdateOutputToSourceMap(std::string const& output,
-                                         cmSourceFile* source, bool byproduct)
-{
-  SourceEntry entry;
-  entry.Sources.Source = source;
-  entry.Sources.SourceIsByproduct = byproduct;
-  entry.SourceMightBeOutput = !byproduct;
-
-  auto pr = this->OutputToSource.emplace(output, entry);
-  if (!pr.second) {
-    SourceEntry& current = pr.first->second;
-    // Outputs take precedence over byproducts
-    if (!current.Sources.Source ||
-        (current.Sources.SourceIsByproduct && !byproduct)) {
-      current.Sources.Source = source;
-      current.Sources.SourceIsByproduct = false;
-      current.SourceMightBeOutput = true;
-    } else {
-      // Multiple custom commands produce the same output but may
-      // be attached to a different source file (MAIN_DEPENDENCY).
-      // LinearGetSourceFileWithOutput would return the first one,
-      // so keep the mapping for the first one.
-      //
-      // TODO: Warn the user about this case.  However, the VS 8 generator
-      // triggers it for separate generate.stamp rules in ZERO_CHECK and
-      // individual targets.
-    }
-  }
 }
 }
 
 
 #if !defined(CMAKE_BOOTSTRAP)
 #if !defined(CMAKE_BOOTSTRAP)
@@ -3676,38 +3460,10 @@ void cmMakefile::CreateGeneratedOutputs(
   for (std::string const& o : outputs) {
   for (std::string const& o : outputs) {
     if (cmGeneratorExpression::Find(o) == std::string::npos) {
     if (cmGeneratorExpression::Find(o) == std::string::npos) {
       this->GetOrCreateGeneratedSource(o);
       this->GetOrCreateGeneratedSource(o);
-      this->AddDelayedOutput(o);
-    } else {
-      this->DelayedOutputFilesHaveGenex = true;
     }
     }
   }
   }
 }
 }
 
 
-void cmMakefile::CreateGeneratedByproducts(
-  const std::vector<std::string>& byproducts)
-{
-  for (std::string const& o : byproducts) {
-    if (cmGeneratorExpression::Find(o) == std::string::npos) {
-      this->GetOrCreateGeneratedSource(o);
-    }
-  }
-}
-
-void cmMakefile::AddDelayedOutput(std::string const& output)
-{
-  // Note that this vector might contain the output names in a different order
-  // than in source file iteration order.
-  this->DelayedOutputFiles.push_back(output);
-
-  SourceEntry entry;
-  entry.SourceMightBeOutput = true;
-
-  auto pr = this->OutputToSource.emplace(output, entry);
-  if (!pr.second) {
-    pr.first->second.SourceMightBeOutput = true;
-  }
-}
-
 void cmMakefile::AddTargetObject(std::string const& tgtName,
 void cmMakefile::AddTargetObject(std::string const& tgtName,
                                  std::string const& objFile)
                                  std::string const& objFile)
 {
 {

+ 6 - 87
Source/cmMakefile.h

@@ -59,24 +59,6 @@ class cmTestGenerator;
 class cmVariableWatch;
 class cmVariableWatch;
 class cmake;
 class cmake;
 
 
-/** Flag if byproducts shall also be considered.  */
-enum class cmSourceOutputKind
-{
-  OutputOnly,
-  OutputOrByproduct
-};
-
-/** Target and source file which have a specific output.  */
-struct cmSourcesWithOutput
-{
-  /** Target with byproduct.  */
-  cmTarget* Target = nullptr;
-
-  /** Source file with output or byproduct.  */
-  cmSourceFile* Source = nullptr;
-  bool SourceIsByproduct = false;
-};
-
 /** A type-safe wrapper for a string representing a directory id.  */
 /** A type-safe wrapper for a string representing a directory id.  */
 class cmDirectoryId
 class cmDirectoryId
 {
 {
@@ -225,24 +207,11 @@ public:
                                 const std::string& source,
                                 const std::string& source,
                                 const cmCustomCommandLines& commandLines,
                                 const cmCustomCommandLines& commandLines,
                                 const char* comment);
                                 const char* comment);
-  bool AppendCustomCommandToOutput(
+  void AppendCustomCommandToOutput(
     const std::string& output, const std::vector<std::string>& depends,
     const std::string& output, const std::vector<std::string>& depends,
     const cmImplicitDependsList& implicit_depends,
     const cmImplicitDependsList& implicit_depends,
     const cmCustomCommandLines& commandLines);
     const cmCustomCommandLines& commandLines);
 
 
-  /**
-   * Add target byproducts.
-   */
-  void AddTargetByproducts(cmTarget* target,
-                           const std::vector<std::string>& byproducts);
-
-  /**
-   * Add source file outputs.
-   */
-  void AddSourceOutputs(cmSourceFile* source,
-                        const std::vector<std::string>& outputs,
-                        const std::vector<std::string>& byproducts);
-
   /**
   /**
    * Add a define flag to the build.
    * Add a define flag to the build.
    */
    */
@@ -753,20 +722,10 @@ public:
     return this->SourceFiles;
     return this->SourceFiles;
   }
   }
 
 
-  /**
-   * Return the target if the provided source name is a byproduct of a utility
-   * target or a PRE_BUILD, PRE_LINK, or POST_BUILD command.
-   * Return the source file which has the provided source name as output.
-   */
-  cmSourcesWithOutput GetSourcesWithOutput(const std::string& name) const;
-
-  /**
-   * Is there a source file that has the provided source name as an output?
-   * If so then return it.
-   */
-  cmSourceFile* GetSourceFileWithOutput(
-    const std::string& name,
-    cmSourceOutputKind kind = cmSourceOutputKind::OutputOnly) const;
+  std::vector<cmTarget*> const& GetOrderedTargets() const
+  {
+    return this->OrderedTargets;
+  }
 
 
   //! Add a new cmTest to the list of tests for this makefile.
   //! Add a new cmTest to the list of tests for this makefile.
   cmTest* CreateTest(const std::string& testName);
   cmTest* CreateTest(const std::string& testName);
@@ -983,8 +942,7 @@ protected:
   mutable cmTargetMap Targets;
   mutable cmTargetMap Targets;
   std::map<std::string, std::string> AliasTargets;
   std::map<std::string, std::string> AliasTargets;
 
 
-  using TargetsVec = std::vector<cmTarget*>;
-  TargetsVec OrderedTargets;
+  std::vector<cmTarget*> OrderedTargets;
 
 
   std::vector<std::unique_ptr<cmSourceFile>> SourceFiles;
   std::vector<std::unique_ptr<cmSourceFile>> SourceFiles;
 
 
@@ -1129,48 +1087,9 @@ private:
   bool ValidateCustomCommand(const cmCustomCommandLines& commandLines) const;
   bool ValidateCustomCommand(const cmCustomCommandLines& commandLines) const;
 
 
   void CreateGeneratedOutputs(const std::vector<std::string>& outputs);
   void CreateGeneratedOutputs(const std::vector<std::string>& outputs);
-  void CreateGeneratedByproducts(const std::vector<std::string>& byproducts);
 
 
   std::vector<BT<GeneratorAction>> GeneratorActions;
   std::vector<BT<GeneratorAction>> GeneratorActions;
   bool GeneratorActionsInvoked = false;
   bool GeneratorActionsInvoked = false;
-  bool DelayedOutputFilesHaveGenex = false;
-  std::vector<std::string> DelayedOutputFiles;
-
-  void AddDelayedOutput(std::string const& output);
-
-  /**
-   * See LinearGetSourceFileWithOutput for background information
-   */
-  cmTarget* LinearGetTargetWithOutput(const std::string& name) const;
-
-  /**
-   * Generalized old version of GetSourceFileWithOutput kept for
-   * backward-compatibility. It implements a linear search and supports
-   * relative file paths. It is used as a fall back by GetSourceFileWithOutput
-   * and GetSourcesWithOutput.
-   */
-  cmSourceFile* LinearGetSourceFileWithOutput(const std::string& name,
-                                              cmSourceOutputKind kind,
-                                              bool& byproduct) const;
-
-  struct SourceEntry
-  {
-    cmSourcesWithOutput Sources;
-    bool SourceMightBeOutput = false;
-  };
-
-  // A map for fast output to input look up.
-  using OutputToSourceMap = std::unordered_map<std::string, SourceEntry>;
-  OutputToSourceMap OutputToSource;
-
-  void UpdateOutputToSourceMap(std::string const& byproduct, cmTarget* target);
-  void UpdateOutputToSourceMap(std::string const& output, cmSourceFile* source,
-                               bool byproduct);
-
-  /**
-   * Return if the provided source file might have a custom command.
-   */
-  bool MightHaveCustomCommand(const std::string& name) const;
 
 
   bool CheckSystemVars;
   bool CheckSystemVars;
   bool CheckCMP0000;
   bool CheckCMP0000;

+ 1 - 1
Tests/RunCMake/add_custom_command/AppendNotOutput-stderr.txt

@@ -1,5 +1,5 @@
 CMake Error at AppendNotOutput.cmake:1 \(add_custom_command\):
 CMake Error at AppendNotOutput.cmake:1 \(add_custom_command\):
-  add_custom_command given APPEND option with output
+  Attempt to APPEND to custom command with output
 
 
     .*RunCMake/add_custom_command/AppendNotOutput-build/out
     .*RunCMake/add_custom_command/AppendNotOutput-build/out