From 75692393628d757a3dadb090179e167cd9539e2f Mon Sep 17 00:00:00 2001
From: Daniel Eiband <daniel.eiband@brainlab.com>
Date: Fri, 6 Sep 2019 19:17:37 +0200
Subject: cmMakefile: set GENERATED property of outputs upfront

Setting the GENERATED property of outputs upfront is a precondition for delayed
custom command creation (generator expressions in outputs).

Issue: 12877
---
 Source/cmMakefile.cxx | 48 ++++++++++++++++++++----------------------------
 Source/cmMakefile.h   |  5 +++++
 2 files changed, 25 insertions(+), 28 deletions(-)

diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 411add3..d729451 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -860,7 +860,7 @@ void cmMakefile::AddCustomCommandToTarget(
         e << "No TARGET '" << target
           << "' has been created in this directory.";
       }
-      IssueMessage(messageType, e.str());
+      this->IssueMessage(messageType, e.str());
     }
 
     return;
@@ -886,11 +886,7 @@ void cmMakefile::AddCustomCommandToTarget(
   }
 
   // Always create the byproduct sources and mark them generated.
-  for (std::string const& o : byproducts) {
-    if (cmSourceFile* out = this->GetOrCreateSource(o, true)) {
-      out->SetProperty("GENERATED", "1");
-    }
-  }
+  this->CreateGeneratedSources(byproducts);
 
   // Add the command to the appropriate build step for the target.
   std::vector<std::string> no_output;
@@ -940,6 +936,10 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput(
     }
   }
 
+  // Always create the output sources and mark them generated.
+  this->CreateGeneratedSources(outputs, cmSourceFileLocationKind::Known);
+  this->CreateGeneratedSources(byproducts, cmSourceFileLocationKind::Known);
+
   // Choose a source file on which to store the custom command.
   cmSourceFile* file = nullptr;
   if (!commandLines.empty() && !main_dependency.empty()) {
@@ -987,20 +987,6 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput(
     file->SetProperty("__CMAKE_RULE", "1");
   }
 
-  // Always create the output sources and mark them generated.
-  for (std::string const& o : outputs) {
-    if (cmSourceFile* out =
-          this->GetOrCreateSource(o, true, cmSourceFileLocationKind::Known)) {
-      out->SetProperty("GENERATED", "1");
-    }
-  }
-  for (std::string const& o : byproducts) {
-    if (cmSourceFile* out =
-          this->GetOrCreateSource(o, true, cmSourceFileLocationKind::Known)) {
-      out->SetProperty("GENERATED", "1");
-    }
-  }
-
   // Attach the custom command to the file.
   if (file) {
     // Construct a complete list of dependencies.
@@ -1180,6 +1166,7 @@ cmTarget* cmMakefile::AddUtilityCommand(
   if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
     target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
   }
+
   if (!comment) {
     // Use an empty comment to avoid generation of default comment.
     comment = "";
@@ -1187,6 +1174,9 @@ cmTarget* cmMakefile::AddUtilityCommand(
 
   // Store the custom command in the target.
   if (!commandLines.empty() || !depends.empty()) {
+    // Always create the byproduct sources and mark them generated.
+    this->CreateGeneratedSources(byproducts, cmSourceFileLocationKind::Known);
+
     std::string force =
       cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/", utilityName);
     std::vector<std::string> forced;
@@ -1205,14 +1195,6 @@ cmTarget* cmMakefile::AddUtilityCommand(
     } else {
       cmSystemTools::Error("Could not get source file entry for " + force);
     }
-
-    // Always create the byproduct sources and mark them generated.
-    for (std::string const& byproduct : byproducts) {
-      if (cmSourceFile* out = this->GetOrCreateSource(
-            byproduct, true, cmSourceFileLocationKind::Known)) {
-        out->SetProperty("GENERATED", "1");
-      }
-    }
   }
   return target;
 }
@@ -3325,6 +3307,16 @@ cmSourceFile* cmMakefile::GetOrCreateSource(const std::string& sourceName,
   return this->CreateSource(sourceName, generated, kind);
 }
 
+void cmMakefile::CreateGeneratedSources(
+  const std::vector<std::string>& outputs, cmSourceFileLocationKind kind)
+{
+  for (std::string const& output : outputs) {
+    if (cmSourceFile* out = this->GetOrCreateSource(output, true, kind)) {
+      out->SetProperty("GENERATED", "1");
+    }
+  }
+}
+
 void cmMakefile::AddTargetObject(std::string const& tgtName,
                                  std::string const& objFile)
 {
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 09f53c9..52464d6 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -1030,6 +1030,11 @@ private:
                                          bool escapeQuotes, bool noEscapes,
                                          bool atOnly, const char* filename,
                                          long line, bool replaceAt) const;
+
+  void CreateGeneratedSources(
+    const std::vector<std::string>& outputs,
+    cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous);
+
   /**
    * Old version of GetSourceFileWithOutput(const std::string&) kept for
    * backward-compatibility. It implements a linear search and support
-- 
cgit v0.12