[Cmake-commits] CMake branch, master, updated. v3.15.3-1136-g01d2944

Kitware Robot kwrobot at kitware.com
Fri Sep 20 10:28:02 EDT 2019


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, master has been updated
       via  01d2944458289ac2601855b3fce2e3f66d850ed4 (commit)
       via  541e681da26d3f264ad20228b66e6cfdfec83878 (commit)
       via  fb8341c35e43d605e4d2ece50dad6428fd9cc45d (commit)
       via  4ade1b00c5b2ca2e3c5ce5f5bcd7dd0a61ef7a2e (commit)
       via  71f088f53ae7f59e002ec893933d0f670347ea93 (commit)
       via  6511fa6f3309984fc10de8471017c2bb32d8d286 (commit)
       via  9b8a1f7c28deac892493b0a5548b08b2003238ea (commit)
       via  4d6334824d81086af205fe06b6fc4c4fda5224b4 (commit)
       via  5bd65dff7a8198279b1e592b7e48b91119dfc794 (commit)
       via  5d39e792ae769025866ab42d58d3363719eec5c1 (commit)
       via  7da17ef7973294a5207f879c0c5a3ed7ab727029 (commit)
       via  d4d0dd0f6a0f2287fd0fbdfad8c7210515af5eaa (commit)
       via  0ac9dcb807d6e7b1f905bc9685f8ae217dfce38b (commit)
       via  0c6468178a76b6a2a11791b010ab01c97855affa (commit)
       via  a209b31d0d088de40ba5bebdc6c9650f0583b2a6 (commit)
       via  a583b7bc17b30c7772d6ca1909c71c0c14e6fabb (commit)
       via  ccc9685cc1fb61242f179a02661730140b026253 (commit)
       via  026ef9b312047778ac0638cf2d2ef8bed6a2b3f2 (commit)
       via  0e1faa28cbd12d400b876f7a21d91aad5a837196 (commit)
       via  56c204e8eb8914b2ca273a56119cf1c40e13d75d (commit)
       via  3061dc6ac967e859424f81fb70bbc70a74246055 (commit)
       via  e893ab94baa29b4a21d3edd86174cd19d8cd5a1e (commit)
       via  f1e846fddece96d76d4d6b53ff1ca8ed197af550 (commit)
       via  4926ab24542d2c9e644feee88efd4a96f8bcab97 (commit)
      from  3c060ae6ca01464d507d6c7b6cef38639084418f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=01d2944458289ac2601855b3fce2e3f66d850ed4
commit 01d2944458289ac2601855b3fce2e3f66d850ed4
Merge: 541e681 71f088f
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Sep 20 14:26:28 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri Sep 20 10:26:41 2019 -0400

    Merge topic 'smart_ptr/cmExportSet'
    
    71f088f53a cmExportSet: subsume cmExportSetMap source files
    6511fa6f33 cmExportSet: default destructor
    9b8a1f7c28 cmExportSetMap: improve ownership of cmExportSet
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3816


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=541e681da26d3f264ad20228b66e6cfdfec83878
commit 541e681da26d3f264ad20228b66e6cfdfec83878
Merge: fb8341c 0e1faa2
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Sep 20 14:22:52 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri Sep 20 10:24:32 2019 -0400

    Merge topic 'split-custom-command-creation'
    
    0e1faa28cb cmMakefile: Separate custom command setup from actual creation
    56c204e8eb cmMakefile: Refactor AddCustomCommandOldStyle to be delay friendly
    3061dc6ac9 add_custom_command: Add tests for rejecting literal quotes in commands
    e893ab94ba cmMakefile: Validate command line for all custom commands
    f1e846fdde cmMakefile: Extract custom command validation method
    4926ab2454 cmMakefile: Create all generated byproducts as known sources
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3822


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fb8341c35e43d605e4d2ece50dad6428fd9cc45d
commit fb8341c35e43d605e4d2ece50dad6428fd9cc45d
Merge: 4ade1b0 a583b7b
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Sep 20 14:22:45 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri Sep 20 10:23:13 2019 -0400

    Merge topic 'prepare-genex-in-byproducts'
    
    a583b7bc17 Genex: Evaluate byproduct generator expressions in cmCustomCommandGenerator
    ccc9685cc1 Genex: Move genex expansion of paths into AppendPaths utility
    026ef9b312 Refactoring: Use ConfigName instead of property CMAKE_BUILD_TYPE
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3797


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4ade1b00c5b2ca2e3c5ce5f5bcd7dd0a61ef7a2e
commit 4ade1b00c5b2ca2e3c5ce5f5bcd7dd0a61ef7a2e
Merge: 3c060ae 4d63348
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Sep 20 14:21:47 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri Sep 20 10:22:01 2019 -0400

    Merge topic 'fileapiLinkPathAndLinkDirBacktraces'
    
    4d6334824d fileapi: add backtraces for LINK_PATH and LINK_DIRECTORIES
    5bd65dff7a cmLocalGenerator: Add OutputLinkLibraries overload with backtraces
    5d39e792ae cmGeneratorTarget: Store backtrace for target LINK_DIRECTORIES property
    7da17ef797 cmLinkLineComputer: Add ComputeLinkLibraries overload with backtraces
    d4d0dd0f6a cmLinkLineComputer: Add ComputeLinkLibs overload with backtraces
    0ac9dcb807 cmLinkLineComputer: Add ComputeLinkPath overload with backtraces
    0c6468178a cmComputeLinkInformation: Add GetDirectoriesWithBacktraces
    a209b31d0d cmComputeLinkInformation: Add AppendValues with backtraces
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3805


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=71f088f53ae7f59e002ec893933d0f670347ea93
commit 71f088f53ae7f59e002ec893933d0f670347ea93
Author:     Tushar Maheshwari <tushar27192 at gmail.com>
AuthorDate: Sat Sep 14 00:39:15 2019 +0530
Commit:     Tushar Maheshwari <tushar27192 at gmail.com>
CommitDate: Thu Sep 19 19:20:30 2019 +0530

    cmExportSet: subsume cmExportSetMap source files

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 65cd6c9..7b580e5 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -226,8 +226,6 @@ set(SRCS
   cmExportTryCompileFileGenerator.cxx
   cmExportSet.h
   cmExportSet.cxx
-  cmExportSetMap.h
-  cmExportSetMap.cxx
   cmExternalMakefileProjectGenerator.cxx
   cmExternalMakefileProjectGenerator.h
   cmExtraCodeBlocksGenerator.cxx
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index 08c6e7b..c751966 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -17,6 +17,7 @@
 #include "cmake.h"
 
 #include <map>
+#include <memory>
 #include <set>
 #include <sstream>
 #include <utility>
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 66dcb97..2713856 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -13,7 +13,7 @@
 #include "cmArgumentParser.h"
 #include "cmExportBuildAndroidMKGenerator.h"
 #include "cmExportBuildFileGenerator.h"
-#include "cmExportSetMap.h"
+#include "cmExportSet.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
@@ -23,7 +23,6 @@
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 
-class cmExportSet;
 class cmExecutionStatus;
 
 #if defined(__HAIKU__)
diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx
index 8f7e2dd..2d732c1 100644
--- a/Source/cmExportInstallAndroidMKGenerator.cxx
+++ b/Source/cmExportInstallAndroidMKGenerator.cxx
@@ -3,6 +3,7 @@
 #include "cmExportInstallAndroidMKGenerator.h"
 
 #include <cstddef>
+#include <memory>
 #include <ostream>
 
 #include "cmExportBuildAndroidMKGenerator.h"
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 28e8244..0009b3a 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -3,7 +3,6 @@
 #include "cmExportInstallFileGenerator.h"
 
 #include "cmExportSet.h"
-#include "cmExportSetMap.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
@@ -19,6 +18,7 @@
 #include "cmTarget.h"
 #include "cmTargetExport.h"
 
+#include <memory>
 #include <sstream>
 #include <utility>
 
diff --git a/Source/cmExportSet.cxx b/Source/cmExportSet.cxx
index 05f1b5d..a20aa9a 100644
--- a/Source/cmExportSet.cxx
+++ b/Source/cmExportSet.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExportSet.h"
 
+#include <tuple>
 #include <utility>
 
 #include "cmLocalGenerator.h"
@@ -30,3 +31,14 @@ void cmExportSet::AddInstallation(cmInstallExportGenerator const* installation)
 {
   this->Installations.push_back(installation);
 }
+
+cmExportSet& cmExportSetMap::operator[](const std::string& name)
+{
+  auto it = this->find(name);
+  if (it == this->end()) // Export set not found
+  {
+    auto tup_name = std::make_tuple(name);
+    it = this->emplace(std::piecewise_construct, tup_name, tup_name).first;
+  }
+  return it->second;
+}
diff --git a/Source/cmExportSet.h b/Source/cmExportSet.h
index 2eee849..f0d921f 100644
--- a/Source/cmExportSet.h
+++ b/Source/cmExportSet.h
@@ -5,6 +5,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <map>
 #include <memory>
 #include <string>
 #include <vector>
@@ -49,4 +50,16 @@ private:
   std::vector<cmInstallExportGenerator const*> Installations;
 };
 
+/// A name -> cmExportSet map with overloaded operator[].
+class cmExportSetMap : public std::map<std::string, cmExportSet>
+{
+public:
+  /** \brief Overloaded operator[].
+   *
+   * The operator is overloaded because cmExportSet has no default constructor:
+   * we do not want unnamed export sets.
+   */
+  cmExportSet& operator[](const std::string& name);
+};
+
 #endif
diff --git a/Source/cmExportSetMap.cxx b/Source/cmExportSetMap.cxx
deleted file mode 100644
index 68e76d5..0000000
--- a/Source/cmExportSetMap.cxx
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#include "cmExportSetMap.h"
-
-#include <tuple>
-#include <utility>
-
-cmExportSet& cmExportSetMap::operator[](const std::string& name)
-{
-  auto it = this->find(name);
-  if (it == this->end()) // Export set not found
-  {
-    auto tup_name = std::make_tuple(name);
-    it = this->emplace(std::piecewise_construct, tup_name, tup_name).first;
-  }
-  return it->second;
-}
diff --git a/Source/cmExportSetMap.h b/Source/cmExportSetMap.h
deleted file mode 100644
index 5764c0b..0000000
--- a/Source/cmExportSetMap.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#ifndef cmExportSetMap_h
-#define cmExportSetMap_h
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <map>
-#include <string>
-
-#include "cmExportSet.h"
-
-/// A name -> cmExportSet map with overloaded operator[].
-class cmExportSetMap : public std::map<std::string, cmExportSet>
-{
-  using derived = std::map<std::string, cmExportSet>;
-
-public:
-  /** \brief Overloaded operator[].
-   *
-   * The operator is overloaded because cmExportSet has no default constructor:
-   * we do not want unnamed export sets.
-   */
-  cmExportSet& operator[](const std::string& name);
-};
-
-#endif
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index d67c725..372e658 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -17,7 +17,7 @@
 #include "cmAlgorithms.h"
 #include "cmCustomCommandLines.h"
 #include "cmDuration.h"
-#include "cmExportSetMap.h"
+#include "cmExportSet.h"
 #include "cmStateSnapshot.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 54f6cc6..0d0b453 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -11,7 +11,6 @@
 
 #include "cmArgumentParser.h"
 #include "cmExportSet.h"
-#include "cmExportSetMap.h"
 #include "cmGeneratorExpression.h"
 #include "cmGlobalGenerator.h"
 #include "cmInstallCommandArguments.h"
diff --git a/bootstrap b/bootstrap
index 9504250..ca5441f 100755
--- a/bootstrap
+++ b/bootstrap
@@ -307,7 +307,6 @@ CMAKE_CXX_SOURCES="\
   cmExportFileGenerator \
   cmExportInstallFileGenerator \
   cmExportSet \
-  cmExportSetMap \
   cmExportTryCompileFileGenerator \
   cmExprParserHelper \
   cmExternalMakefileProjectGenerator \

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6511fa6f3309984fc10de8471017c2bb32d8d286
commit 6511fa6f3309984fc10de8471017c2bb32d8d286
Author:     Tushar Maheshwari <tushar27192 at gmail.com>
AuthorDate: Sun Sep 8 14:44:55 2019 +0530
Commit:     Tushar Maheshwari <tushar27192 at gmail.com>
CommitDate: Thu Sep 19 19:20:29 2019 +0530

    cmExportSet: default destructor

diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index e9d2412..08c6e7b 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -283,7 +283,8 @@ void cmExportBuildFileGenerator::GetTargets(
   std::vector<std::string>& targets) const
 {
   if (this->ExportSet) {
-    for (cmTargetExport* te : *this->ExportSet->GetTargetExports()) {
+    for (std::unique_ptr<cmTargetExport> const& te :
+         this->ExportSet->GetTargetExports()) {
       targets.push_back(te->TargetName);
     }
     return;
diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx
index 207ea41..8f7e2dd 100644
--- a/Source/cmExportInstallAndroidMKGenerator.cxx
+++ b/Source/cmExportInstallAndroidMKGenerator.cxx
@@ -35,7 +35,8 @@ void cmExportInstallAndroidMKGenerator::GenerateImportHeaderCode(
   }
   os << "_IMPORT_PREFIX := "
      << "$(LOCAL_PATH)" << path << "\n\n";
-  for (cmTargetExport* te : *this->IEGen->GetExportSet()->GetTargetExports()) {
+  for (std::unique_ptr<cmTargetExport> const& te :
+       this->IEGen->GetExportSet()->GetTargetExports()) {
     // Collect import properties for this target.
     if (te->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
       continue;
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index c5aec64..28e8244 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -40,12 +40,12 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
   {
     std::string expectedTargets;
     std::string sep;
-    for (cmTargetExport* te :
-         *this->IEGen->GetExportSet()->GetTargetExports()) {
+    for (std::unique_ptr<cmTargetExport> const& te :
+         this->IEGen->GetExportSet()->GetTargetExports()) {
       expectedTargets += sep + this->Namespace + te->Target->GetExportName();
       sep = " ";
       if (this->ExportedTargets.insert(te->Target).second) {
-        allTargets.push_back(te);
+        allTargets.push_back(te.get());
       } else {
         std::ostringstream e;
         e << "install(EXPORT \"" << this->IEGen->GetExportSet()->GetName()
@@ -314,9 +314,11 @@ void cmExportInstallFileGenerator::GenerateImportTargetsConfig(
   std::vector<std::string>& missingTargets)
 {
   // Add each target in the set to the export.
-  for (cmTargetExport* te : *this->IEGen->GetExportSet()->GetTargetExports()) {
+  for (std::unique_ptr<cmTargetExport> const& te :
+       this->IEGen->GetExportSet()->GetTargetExports()) {
     // Collect import properties for this target.
-    if (this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY) {
+    if (this->GetExportTargetType(te.get()) ==
+        cmStateEnums::INTERFACE_LIBRARY) {
       continue;
     }
 
@@ -475,10 +477,9 @@ cmExportInstallFileGenerator::FindNamespaces(cmGlobalGenerator* gg,
 
   for (auto const& expIt : exportSets) {
     const cmExportSet& exportSet = expIt.second;
-    std::vector<cmTargetExport*> const* targets = exportSet.GetTargetExports();
 
     bool containsTarget = false;
-    for (cmTargetExport* target : *targets) {
+    for (auto const& target : exportSet.GetTargetExports()) {
       if (name == target->TargetName) {
         containsTarget = true;
         break;
diff --git a/Source/cmExportSet.cxx b/Source/cmExportSet.cxx
index a6fa186..05f1b5d 100644
--- a/Source/cmExportSet.cxx
+++ b/Source/cmExportSet.cxx
@@ -2,25 +2,28 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExportSet.h"
 
-#include "cmAlgorithms.h"
+#include <utility>
+
 #include "cmLocalGenerator.h"
 #include "cmTargetExport.h"
 
-cmExportSet::~cmExportSet()
+cmExportSet::cmExportSet(std::string name)
+  : Name(std::move(name))
 {
-  cmDeleteAll(this->TargetExports);
 }
 
+cmExportSet::~cmExportSet() = default;
+
 void cmExportSet::Compute(cmLocalGenerator* lg)
 {
-  for (cmTargetExport* tgtExport : this->TargetExports) {
+  for (std::unique_ptr<cmTargetExport>& tgtExport : this->TargetExports) {
     tgtExport->Target = lg->FindGeneratorTargetToUse(tgtExport->TargetName);
   }
 }
 
-void cmExportSet::AddTargetExport(cmTargetExport* te)
+void cmExportSet::AddTargetExport(std::unique_ptr<cmTargetExport> te)
 {
-  this->TargetExports.push_back(te);
+  this->TargetExports.emplace_back(std::move(te));
 }
 
 void cmExportSet::AddInstallation(cmInstallExportGenerator const* installation)
diff --git a/Source/cmExportSet.h b/Source/cmExportSet.h
index d654c12..2eee849 100644
--- a/Source/cmExportSet.h
+++ b/Source/cmExportSet.h
@@ -5,8 +5,8 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <memory>
 #include <string>
-#include <utility>
 #include <vector>
 
 class cmInstallExportGenerator;
@@ -18,10 +18,7 @@ class cmExportSet
 {
 public:
   /// Construct an empty export set named \a name
-  cmExportSet(std::string name)
-    : Name(std::move(name))
-  {
-  }
+  cmExportSet(std::string name);
   /// Destructor
   ~cmExportSet();
 
@@ -30,15 +27,15 @@ public:
 
   void Compute(cmLocalGenerator* lg);
 
-  void AddTargetExport(cmTargetExport* tgt);
+  void AddTargetExport(std::unique_ptr<cmTargetExport> tgt);
 
   void AddInstallation(cmInstallExportGenerator const* installation);
 
   std::string const& GetName() const { return this->Name; }
 
-  std::vector<cmTargetExport*> const* GetTargetExports() const
+  std::vector<std::unique_ptr<cmTargetExport>> const& GetTargetExports() const
   {
-    return &this->TargetExports;
+    return this->TargetExports;
   }
 
   std::vector<cmInstallExportGenerator const*> const* GetInstallations() const
@@ -47,7 +44,7 @@ public:
   }
 
 private:
-  std::vector<cmTargetExport*> TargetExports;
+  std::vector<std::unique_ptr<cmTargetExport>> TargetExports;
   std::string Name;
   std::vector<cmInstallExportGenerator const*> Installations;
 };
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 11d2c4b..54f6cc6 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -744,7 +744,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
     // Add this install rule to an export if one was specified and
     // this is not a namelink-only rule.
     if (!exports.empty() && !namelinkOnly) {
-      cmTargetExport* te = new cmTargetExport;
+      auto te = cm::make_unique<cmTargetExport>();
       te->TargetName = target.GetName();
       te->ArchiveGenerator = archiveGenerator;
       te->BundleGenerator = bundleGenerator;
@@ -753,12 +753,12 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
       te->LibraryGenerator = libraryGenerator;
       te->RuntimeGenerator = runtimeGenerator;
       te->ObjectsGenerator = objectGenerator;
-      this->Makefile->GetGlobalGenerator()
-        ->GetExportSets()[exports]
-        .AddTargetExport(te);
-
       te->InterfaceIncludeDirectories =
         cmJoin(includesArgs.GetIncludeDirs(), ";");
+
+      this->Makefile->GetGlobalGenerator()
+        ->GetExportSets()[exports]
+        .AddTargetExport(std::move(te));
     }
   }
 
@@ -1433,7 +1433,7 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
   cmExportSet& exportSet =
     this->Makefile->GetGlobalGenerator()->GetExportSets()[exp];
   if (exportOld) {
-    for (cmTargetExport* te : *exportSet.GetTargetExports()) {
+    for (auto const& te : exportSet.GetTargetExports()) {
       cmTarget* tgt =
         this->Makefile->GetGlobalGenerator()->FindTarget(te->TargetName);
       const bool newCMP0022Behavior =
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index 0b3617b..cba68be 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -123,7 +123,7 @@ size_t cmInstallExportGenerator::GetMaxConfigLength() const
 void cmInstallExportGenerator::GenerateScript(std::ostream& os)
 {
   // Skip empty sets.
-  if (ExportSet->GetTargetExports()->empty()) {
+  if (ExportSet->GetTargetExports().empty()) {
     std::ostringstream e;
     e << "INSTALL(EXPORT) given unknown export \"" << ExportSet->GetName()
       << "\"";

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9b8a1f7c28deac892493b0a5548b08b2003238ea
commit 9b8a1f7c28deac892493b0a5548b08b2003238ea
Author:     Tushar Maheshwari <tushar27192 at gmail.com>
AuthorDate: Fri Sep 6 15:46:02 2019 +0530
Commit:     Tushar Maheshwari <tushar27192 at gmail.com>
CommitDate: Thu Sep 19 19:20:29 2019 +0530

    cmExportSetMap: improve ownership of cmExportSet
    
    - use `std::piecewise_construct` to fix gcc-4.8 build.
    - can use `emplace(name, name)` gcc-6 onwards.

diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 4046f91..66dcb97 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -121,7 +121,7 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
 
   cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
 
-  cmExportSet* ExportSet = nullptr;
+  cmExportSet* exportSet = nullptr;
   if (args[0] == "EXPORT") {
     cmExportSetMap& setMap = gg->GetExportSets();
     auto const it = setMap.find(arguments.ExportSetName);
@@ -131,7 +131,7 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
       this->SetError(e.str());
       return false;
     }
-    ExportSet = it->second;
+    exportSet = &it->second;
   } else if (!arguments.Targets.empty() ||
              cmContains(keywordsMissingValue, "TARGETS")) {
     for (std::string const& currentTarget : arguments.Targets) {
@@ -180,8 +180,8 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
   ebfg->SetExportFile(fname.c_str());
   ebfg->SetNamespace(arguments.Namespace);
   ebfg->SetAppendMode(arguments.Append);
-  if (ExportSet != nullptr) {
-    ebfg->SetExportSet(ExportSet);
+  if (exportSet != nullptr) {
+    ebfg->SetExportSet(exportSet);
   } else {
     ebfg->SetTargets(targets);
   }
@@ -197,7 +197,7 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
   for (std::string const& ct : configurationTypes) {
     ebfg->AddConfiguration(ct);
   }
-  if (ExportSet != nullptr) {
+  if (exportSet != nullptr) {
     gg->AddBuildExportExportSet(ebfg);
   } else {
     gg->AddBuildExportSet(ebfg);
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 4e3db09..c5aec64 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -474,9 +474,8 @@ cmExportInstallFileGenerator::FindNamespaces(cmGlobalGenerator* gg,
   const cmExportSetMap& exportSets = gg->GetExportSets();
 
   for (auto const& expIt : exportSets) {
-    const cmExportSet* exportSet = expIt.second;
-    std::vector<cmTargetExport*> const* targets =
-      exportSet->GetTargetExports();
+    const cmExportSet& exportSet = expIt.second;
+    std::vector<cmTargetExport*> const* targets = exportSet.GetTargetExports();
 
     bool containsTarget = false;
     for (cmTargetExport* target : *targets) {
@@ -488,7 +487,7 @@ cmExportInstallFileGenerator::FindNamespaces(cmGlobalGenerator* gg,
 
     if (containsTarget) {
       std::vector<cmInstallExportGenerator const*> const* installs =
-        exportSet->GetInstallations();
+        exportSet.GetInstallations();
       for (cmInstallExportGenerator const* install : *installs) {
         exportFiles.push_back(install->GetDestinationFile());
         ns = install->GetNamespace();
diff --git a/Source/cmExportSetMap.cxx b/Source/cmExportSetMap.cxx
index 5c3f84f..68e76d5 100644
--- a/Source/cmExportSetMap.cxx
+++ b/Source/cmExportSetMap.cxx
@@ -2,30 +2,16 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExportSetMap.h"
 
-#include "cmAlgorithms.h"
-#include "cmExportSet.h"
-
+#include <tuple>
 #include <utility>
 
-cmExportSet* cmExportSetMap::operator[](const std::string& name)
+cmExportSet& cmExportSetMap::operator[](const std::string& name)
 {
   auto it = this->find(name);
   if (it == this->end()) // Export set not found
   {
-    it = this->insert(std::make_pair(name, new cmExportSet(name))).first;
+    auto tup_name = std::make_tuple(name);
+    it = this->emplace(std::piecewise_construct, tup_name, tup_name).first;
   }
   return it->second;
 }
-
-void cmExportSetMap::clear()
-{
-  cmDeleteAll(*this);
-  this->derived::clear();
-}
-
-cmExportSetMap::cmExportSetMap() = default;
-
-cmExportSetMap::~cmExportSetMap()
-{
-  this->clear();
-}
diff --git a/Source/cmExportSetMap.h b/Source/cmExportSetMap.h
index 0ef07ef..5764c0b 100644
--- a/Source/cmExportSetMap.h
+++ b/Source/cmExportSetMap.h
@@ -8,12 +8,12 @@
 #include <map>
 #include <string>
 
-class cmExportSet;
+#include "cmExportSet.h"
 
 /// A name -> cmExportSet map with overloaded operator[].
-class cmExportSetMap : public std::map<std::string, cmExportSet*>
+class cmExportSetMap : public std::map<std::string, cmExportSet>
 {
-  using derived = std::map<std::string, cmExportSet*>;
+  using derived = std::map<std::string, cmExportSet>;
 
 public:
   /** \brief Overloaded operator[].
@@ -21,17 +21,7 @@ public:
    * The operator is overloaded because cmExportSet has no default constructor:
    * we do not want unnamed export sets.
    */
-  cmExportSet* operator[](const std::string& name);
-
-  void clear();
-
-  cmExportSetMap();
-
-  /// Overloaded destructor deletes all member export sets.
-  ~cmExportSetMap();
-
-  cmExportSetMap(const cmExportSetMap&) = delete;
-  cmExportSetMap& operator=(const cmExportSetMap&) = delete;
+  cmExportSet& operator[](const std::string& name);
 };
 
 #endif
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 9b931f7..11d2c4b 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -755,7 +755,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
       te->ObjectsGenerator = objectGenerator;
       this->Makefile->GetGlobalGenerator()
         ->GetExportSets()[exports]
-        ->AddTargetExport(te);
+        .AddTargetExport(te);
 
       te->InterfaceIncludeDirectories =
         cmJoin(includesArgs.GetIncludeDirs(), ";");
@@ -1333,7 +1333,7 @@ bool cmInstallCommand::HandleExportAndroidMKMode(
     fname = "Android.mk";
   }
 
-  cmExportSet* exportSet =
+  cmExportSet& exportSet =
     this->Makefile->GetGlobalGenerator()->GetExportSets()[exp];
 
   cmInstallGenerator::MessageLevel message =
@@ -1341,7 +1341,7 @@ bool cmInstallCommand::HandleExportAndroidMKMode(
 
   // Create the export install generator.
   cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator(
-    exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
+    &exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
     ica.GetConfigurations(), ica.GetComponent().c_str(), message,
     ica.GetExcludeFromAll(), fname.c_str(), name_space.c_str(), exportOld,
     true);
@@ -1430,10 +1430,10 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
     }
   }
 
-  cmExportSet* exportSet =
+  cmExportSet& exportSet =
     this->Makefile->GetGlobalGenerator()->GetExportSets()[exp];
   if (exportOld) {
-    for (cmTargetExport* te : *exportSet->GetTargetExports()) {
+    for (cmTargetExport* te : *exportSet.GetTargetExports()) {
       cmTarget* tgt =
         this->Makefile->GetGlobalGenerator()->FindTarget(te->TargetName);
       const bool newCMP0022Behavior =
@@ -1457,7 +1457,7 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
 
   // Create the export install generator.
   cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator(
-    exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
+    &exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
     ica.GetConfigurations(), ica.GetComponent().c_str(), message,
     ica.GetExcludeFromAll(), fname.c_str(), name_space.c_str(), exportOld,
     false);

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4d6334824d81086af205fe06b6fc4c4fda5224b4
commit 4d6334824d81086af205fe06b6fc4c4fda5224b4
Author:     Justin Goshi <jgoshi at microsoft.com>
AuthorDate: Wed Sep 11 11:37:48 2019 -0700
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Sep 18 14:00:39 2019 -0400

    fileapi: add backtraces for LINK_PATH and LINK_DIRECTORIES

diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index 805da81..3cf929f 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -1270,8 +1270,8 @@ Json::Value Target::DumpLinkCommandFragments()
   std::string linkLanguageFlags;
   std::vector<BT<std::string>> linkFlags;
   std::string frameworkPath;
-  std::string linkPath;
-  std::string linkLibs;
+  std::vector<BT<std::string>> linkPath;
+  std::vector<BT<std::string>> linkLibs;
   cmLocalGenerator* lg = this->GT->GetLocalGenerator();
   cmLinkLineComputer linkLineComputer(lg,
                                       lg->GetStateSnapshot().GetDirectory());
@@ -1280,8 +1280,6 @@ Json::Value Target::DumpLinkCommandFragments()
                      this->GT);
   linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags);
   frameworkPath = cmTrimWhitespace(frameworkPath);
-  linkPath = cmTrimWhitespace(linkPath);
-  linkLibs = cmTrimWhitespace(linkLibs);
 
   if (!linkLanguageFlags.empty()) {
     linkFragments.append(
@@ -1302,13 +1300,19 @@ Json::Value Target::DumpLinkCommandFragments()
   }
 
   if (!linkPath.empty()) {
-    linkFragments.append(
-      this->DumpCommandFragment(std::move(linkPath), "libraryPath"));
+    for (BT<std::string> frag : linkPath) {
+      frag.Value = cmTrimWhitespace(frag.Value);
+      linkFragments.append(
+        this->DumpCommandFragment(this->ToJBT(frag), "libraryPath"));
+    }
   }
 
   if (!linkLibs.empty()) {
-    linkFragments.append(
-      this->DumpCommandFragment(std::move(linkLibs), "libraries"));
+    for (BT<std::string> frag : linkLibs) {
+      frag.Value = cmTrimWhitespace(frag.Value);
+      linkFragments.append(
+        this->DumpCommandFragment(this->ToJBT(frag), "libraries"));
+    }
   }
 
   return linkFragments;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index a4b482c..214e92c 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1198,17 +1198,21 @@ void cmLocalGenerator::GetTargetFlags(
   std::string& linkLibs, std::string& flags, std::string& linkFlags,
   std::string& frameworkPath, std::string& linkPath, cmGeneratorTarget* target)
 {
-  std::vector<BT<std::string>> tmpLinkFlags;
-  this->GetTargetFlags(linkLineComputer, config, linkLibs, flags, tmpLinkFlags,
-                       frameworkPath, linkPath, target);
-  this->AppendFlags(linkFlags, tmpLinkFlags);
+  std::vector<BT<std::string>> linkFlagsList;
+  std::vector<BT<std::string>> linkPathList;
+  std::vector<BT<std::string>> linkLibsList;
+  this->GetTargetFlags(linkLineComputer, config, linkLibsList, flags,
+                       linkFlagsList, frameworkPath, linkPathList, target);
+  this->AppendFlags(linkFlags, linkFlagsList);
+  this->AppendFlags(linkPath, linkPathList);
+  this->AppendFlags(linkLibs, linkLibsList);
 }
 
 void cmLocalGenerator::GetTargetFlags(
   cmLinkLineComputer* linkLineComputer, const std::string& config,
-  std::string& linkLibs, std::string& flags,
+  std::vector<BT<std::string>>& linkLibs, std::string& flags,
   std::vector<BT<std::string>>& linkFlags, std::string& frameworkPath,
-  std::string& linkPath, cmGeneratorTarget* target)
+  std::vector<BT<std::string>>& linkPath, cmGeneratorTarget* target)
 {
   const std::string buildType = cmSystemTools::UpperCase(config);
   cmComputeLinkInformation* pcli = target->GetLinkInformation(config);
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index f04f391..512df26 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -382,12 +382,11 @@ public:
                       std::string& flags, std::string& linkFlags,
                       std::string& frameworkPath, std::string& linkPath,
                       cmGeneratorTarget* target);
-  void GetTargetFlags(cmLinkLineComputer* linkLineComputer,
-                      const std::string& config, std::string& linkLibs,
-                      std::string& flags,
-                      std::vector<BT<std::string>>& linkFlags,
-                      std::string& frameworkPath, std::string& linkPath,
-                      cmGeneratorTarget* target);
+  void GetTargetFlags(
+    cmLinkLineComputer* linkLineComputer, const std::string& config,
+    std::vector<BT<std::string>>& linkLibs, std::string& flags,
+    std::vector<BT<std::string>>& linkFlags, std::string& frameworkPath,
+    std::vector<BT<std::string>>& linkPath, cmGeneratorTarget* target);
   void GetTargetDefines(cmGeneratorTarget const* target,
                         std::string const& config, std::string const& lang,
                         std::set<std::string>& defines) const;
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
index 2a24421..52934f2 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
@@ -249,13 +249,13 @@ def check_target(c):
 
                     if expected["backtrace"] is not None:
                         expected_keys.append("backtrace")
-                        assert actual["fragment"] == expected["fragment"]
+                        assert matches(actual["fragment"], expected["fragment"])
                         assert actual["role"] == expected["role"]
                         check_backtrace(obj, actual["backtrace"], expected["backtrace"])
 
                     assert sorted(actual.keys()) == sorted(expected_keys)
 
-                check_list_match(lambda a, e: is_string(a["fragment"], e["fragment"]),
+                check_list_match(lambda a, e: matches(a["fragment"], e["fragment"]),
                                  obj["link"]["commandFragments"], expected["link"]["commandFragments"],
                                  check=check_link_command_fragments,
                                  check_exception=lambda a, e: "Link fragment: %s" % a["fragment"],
@@ -2218,6 +2218,42 @@ def gen_check_targets(c, g, inSource):
                             },
                         ],
                     },
+                    {
+                        "fragment" : ".*TargetLinkDir\\\"?$",
+                        "role" : "libraryPath",
+                        "backtrace": [
+                            {
+                                "file": "^cxx/CMakeLists\\.txt$",
+                                "line": 19,
+                                "command": "target_link_directories",
+                                "hasParent": True,
+                            },
+                            {
+                                "file" : "^cxx/CMakeLists\\.txt$",
+                                "line": None,
+                                "command": None,
+                                "hasParent": False,
+                            },
+                        ],
+                    },
+                    {
+                        "fragment" : ".*cxx_lib.*",
+                        "role" : "libraries",
+                        "backtrace": [
+                            {
+                                "file": "^cxx/CMakeLists\\.txt$",
+                                "line": 6,
+                                "command": "target_link_libraries",
+                                "hasParent": True,
+                            },
+                            {
+                                "file" : "^cxx/CMakeLists\\.txt$",
+                                "line": None,
+                                "command": None,
+                                "hasParent": False,
+                            },
+                        ],
+                    },
                 ],
             },
             "archive": None,
diff --git a/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt b/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt
index 17ff455..b0564f5 100644
--- a/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt
+++ b/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt
@@ -16,3 +16,4 @@ target_link_libraries(cxx_static_exe PRIVATE cxx_static_lib)
 
 target_compile_options(cxx_exe PUBLIC TargetCompileOptions)
 target_link_options(cxx_exe PUBLIC TargetLinkOptions)
+target_link_directories(cxx_exe PUBLIC "${CMAKE_BINARY_DIR}/TargetLinkDir")

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5bd65dff7a8198279b1e592b7e48b91119dfc794
commit 5bd65dff7a8198279b1e592b7e48b91119dfc794
Author:     Justin Goshi <jgoshi at microsoft.com>
AuthorDate: Wed Sep 11 11:15:08 2019 -0700
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Sep 18 14:00:39 2019 -0400

    cmLocalGenerator: Add OutputLinkLibraries overload with backtraces

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 9f22277..a4b482c 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1526,6 +1526,19 @@ void cmLocalGenerator::OutputLinkLibraries(
   std::string& linkLibraries, std::string& frameworkPath,
   std::string& linkPath)
 {
+  std::vector<BT<std::string>> linkLibrariesList;
+  std::vector<BT<std::string>> linkPathList;
+  this->OutputLinkLibraries(pcli, linkLineComputer, linkLibrariesList,
+                            frameworkPath, linkPathList);
+  pcli->AppendValues(linkLibraries, linkLibrariesList);
+  pcli->AppendValues(linkPath, linkPathList);
+}
+
+void cmLocalGenerator::OutputLinkLibraries(
+  cmComputeLinkInformation* pcli, cmLinkLineComputer* linkLineComputer,
+  std::vector<BT<std::string>>& linkLibraries, std::string& frameworkPath,
+  std::vector<BT<std::string>>& linkPath)
+{
   cmComputeLinkInformation& cli = *pcli;
 
   std::string linkLanguage = cli.GetLinkLanguage();
@@ -1557,10 +1570,9 @@ void cmLocalGenerator::OutputLinkLibraries(
     cmStrCat("CMAKE_", linkLanguage, "_FRAMEWORK_SEARCH_FLAG"));
 
   frameworkPath = linkLineComputer->ComputeFrameworkPath(cli, fwSearchFlag);
-  linkPath =
-    linkLineComputer->ComputeLinkPath(cli, libPathFlag, libPathTerminator);
-
-  linkLibraries = linkLineComputer->ComputeLinkLibraries(cli, stdLibString);
+  linkLineComputer->ComputeLinkPath(cli, libPathFlag, libPathTerminator,
+                                    linkPath);
+  linkLineComputer->ComputeLinkLibraries(cli, stdLibString, linkLibraries);
 }
 
 std::string cmLocalGenerator::GetLinkLibsCMP0065(
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 34f58bd..f04f391 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -430,6 +430,11 @@ protected:
                            cmLinkLineComputer* linkLineComputer,
                            std::string& linkLibraries,
                            std::string& frameworkPath, std::string& linkPath);
+  void OutputLinkLibraries(cmComputeLinkInformation* pcli,
+                           cmLinkLineComputer* linkLineComputer,
+                           std::vector<BT<std::string>>& linkLibraries,
+                           std::string& frameworkPath,
+                           std::vector<BT<std::string>>& linkPath);
 
   // Handle old-style install rules stored in the targets.
   void GenerateTargetInstallRules(

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5d39e792ae769025866ab42d58d3363719eec5c1
commit 5d39e792ae769025866ab42d58d3363719eec5c1
Author:     Justin Goshi <jgoshi at microsoft.com>
AuthorDate: Wed Sep 11 11:07:43 2019 -0700
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Sep 18 14:00:39 2019 -0400

    cmGeneratorTarget: Store backtrace for target LINK_DIRECTORIES property

diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index e4659b7..76b72b5 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -3692,7 +3692,7 @@ void processLinkDirectories(cmGeneratorTarget const* tgt,
       // in case projects set the LINK_DIRECTORIES property directly.
       cmSystemTools::ConvertToUnixSlashes(entryDirectory);
       if (uniqueDirectories.insert(entryDirectory).second) {
-        directories.emplace_back(entryDirectory);
+        directories.emplace_back(entryDirectory, entry.Backtrace);
         if (debugDirectories) {
           usedDirectories += " * " + entryDirectory + "\n";
         }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7da17ef7973294a5207f879c0c5a3ed7ab727029
commit 7da17ef7973294a5207f879c0c5a3ed7ab727029
Author:     Justin Goshi <jgoshi at microsoft.com>
AuthorDate: Wed Sep 11 11:04:36 2019 -0700
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Sep 18 14:00:37 2019 -0400

    cmLinkLineComputer: Add ComputeLinkLibraries overload with backtraces

diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx
index dec25ff..0dc6236 100644
--- a/Source/cmLinkLineComputer.cxx
+++ b/Source/cmLinkLineComputer.cxx
@@ -222,13 +222,30 @@ std::string cmLinkLineComputer::ComputeFrameworkPath(
 std::string cmLinkLineComputer::ComputeLinkLibraries(
   cmComputeLinkInformation& cli, std::string const& stdLibString)
 {
-  std::ostringstream fout;
-  fout << this->ComputeRPath(cli);
+  std::string linkLibraries;
+  std::vector<BT<std::string>> linkLibrariesList;
+  this->ComputeLinkLibraries(cli, stdLibString, linkLibrariesList);
+  cli.AppendValues(linkLibraries, linkLibrariesList);
+  return linkLibraries;
+}
+
+void cmLinkLineComputer::ComputeLinkLibraries(
+  cmComputeLinkInformation& cli, std::string const& stdLibString,
+  std::vector<BT<std::string>>& linkLibraries)
+{
+  std::ostringstream rpathOut;
+  rpathOut << this->ComputeRPath(cli);
+
+  std::string rpath = rpathOut.str();
+  if (!rpath.empty()) {
+    linkLibraries.emplace_back(std::move(rpath));
+  }
 
   // Write the library flags to the build rule.
-  fout << this->ComputeLinkLibs(cli);
+  this->ComputeLinkLibs(cli, linkLibraries);
 
   // Add the linker runtime search path if any.
+  std::ostringstream fout;
   std::string rpath_link = cli.GetRPathLinkString();
   if (!cli.GetRPathLinkFlag().empty() && !rpath_link.empty()) {
     fout << cli.GetRPathLinkFlag();
@@ -241,7 +258,10 @@ std::string cmLinkLineComputer::ComputeLinkLibraries(
     fout << stdLibString << " ";
   }
 
-  return fout.str();
+  std::string remainingLibs = fout.str();
+  if (!remainingLibs.empty()) {
+    linkLibraries.emplace_back(remainingLibs);
+  }
 }
 
 std::string cmLinkLineComputer::GetLinkerLanguage(cmGeneratorTarget* target,
diff --git a/Source/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h
index a6e0ebf..f426976 100644
--- a/Source/cmLinkLineComputer.h
+++ b/Source/cmLinkLineComputer.h
@@ -45,8 +45,12 @@ public:
   std::string ComputeFrameworkPath(cmComputeLinkInformation& cli,
                                    std::string const& fwSearchFlag);
 
-  virtual std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
-                                           std::string const& stdLibString);
+  std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
+                                   std::string const& stdLibString);
+
+  virtual void ComputeLinkLibraries(
+    cmComputeLinkInformation& cli, std::string const& stdLibString,
+    std::vector<BT<std::string>>& linkLibraries);
 
   virtual std::string GetLinkerLanguage(cmGeneratorTarget* target,
                                         std::string const& config);
diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx
index 1a602ca..d845652 100644
--- a/Source/cmLinkLineDeviceComputer.cxx
+++ b/Source/cmLinkLineDeviceComputer.cxx
@@ -4,13 +4,14 @@
 #include "cmLinkLineDeviceComputer.h"
 
 #include <set>
-#include <sstream>
 #include <utility>
 
 #include "cmAlgorithms.h"
 #include "cmComputeLinkInformation.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
+#include "cmLinkItem.h"
+#include "cmListFileCache.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmStateDirectory.h"
@@ -67,12 +68,10 @@ bool cmLinkLineDeviceComputer::ComputeRequiresDeviceLinking(
   return false;
 }
 
-std::string cmLinkLineDeviceComputer::ComputeLinkLibraries(
-  cmComputeLinkInformation& cli, std::string const& stdLibString)
+void cmLinkLineDeviceComputer::ComputeLinkLibraries(
+  cmComputeLinkInformation& cli, std::string const& stdLibString,
+  std::vector<BT<std::string>>& linkLibraries)
 {
-  // Write the library flags to the build rule.
-  std::ostringstream fout;
-
   // Generate the unique set of link items when device linking.
   // The nvcc device linker is designed so that each static library
   // with device symbols only needs to be listed once as it doesn't
@@ -110,7 +109,7 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries(
       }
     }
 
-    std::string out;
+    BT<std::string> linkLib;
     if (item.IsPath) {
       // nvcc understands absolute paths to libraries ending in '.a' or '.lib'.
       // These should be passed to nvlink.  Other extensions need to be left
@@ -118,7 +117,7 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries(
       // can tolerate '.so' or '.dylib' it cannot tolerate '.so.1'.
       if (cmHasLiteralSuffix(item.Value, ".a") ||
           cmHasLiteralSuffix(item.Value, ".lib")) {
-        out += this->ConvertToOutputFormat(
+        linkLib.Value += this->ConvertToOutputFormat(
           this->ConvertToLinkReference(item.Value));
       }
     } else if (item.Value == "-framework") {
@@ -127,19 +126,33 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries(
       skipItemAfterFramework = true;
       continue;
     } else if (cmLinkItemValidForDevice(item.Value)) {
-      out += item.Value;
+      linkLib.Value += item.Value;
     }
 
-    if (emitted.insert(out).second) {
-      fout << out << " ";
+    if (emitted.insert(linkLib.Value).second) {
+      linkLib.Value += " ";
+
+      const cmLinkImplementation* linkImpl =
+        cli.GetTarget()->GetLinkImplementation(cli.GetConfig());
+
+      for (const cmLinkImplItem& iter : linkImpl->Libraries) {
+        if (iter.Target != nullptr &&
+            iter.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+          std::string libPath = iter.Target->GetLocation(cli.GetConfig());
+          if (item.Value == libPath) {
+            linkLib.Backtrace = iter.Backtrace;
+            break;
+          }
+        }
+      }
+
+      linkLibraries.emplace_back(linkLib);
     }
   }
 
   if (!stdLibString.empty()) {
-    fout << stdLibString << " ";
+    linkLibraries.emplace_back(cmStrCat(stdLibString, ' '));
   }
-
-  return fout.str();
 }
 
 std::string cmLinkLineDeviceComputer::GetLinkerLanguage(cmGeneratorTarget*,
diff --git a/Source/cmLinkLineDeviceComputer.h b/Source/cmLinkLineDeviceComputer.h
index 0ea5f69..a9b01cd 100644
--- a/Source/cmLinkLineDeviceComputer.h
+++ b/Source/cmLinkLineDeviceComputer.h
@@ -7,6 +7,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
+#include <vector>
 
 #include "cmLinkLineComputer.h"
 
@@ -15,6 +16,8 @@ class cmGeneratorTarget;
 class cmLocalGenerator;
 class cmOutputConverter;
 class cmStateDirectory;
+template <typename T>
+class BT;
 
 class cmLinkLineDeviceComputer : public cmLinkLineComputer
 {
@@ -29,8 +32,9 @@ public:
 
   bool ComputeRequiresDeviceLinking(cmComputeLinkInformation& cli);
 
-  std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
-                                   std::string const& stdLibString) override;
+  void ComputeLinkLibraries(
+    cmComputeLinkInformation& cli, std::string const& stdLibString,
+    std::vector<BT<std::string>>& linkLibraries) override;
 
   std::string GetLinkerLanguage(cmGeneratorTarget* target,
                                 std::string const& config) override;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d4d0dd0f6a0f2287fd0fbdfad8c7210515af5eaa
commit d4d0dd0f6a0f2287fd0fbdfad8c7210515af5eaa
Author:     Justin Goshi <jgoshi at microsoft.com>
AuthorDate: Fri Sep 13 10:59:53 2019 -0700
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Sep 18 13:59:36 2019 -0400

    cmLinkLineComputer: Add ComputeLinkLibs overload with backtraces

diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index 71af43f..d3345d9 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -70,6 +70,8 @@ public:
 
   std::string GetConfig() const { return this->Config; }
 
+  const cmGeneratorTarget* GetTarget() { return this->Target; }
+
 private:
   void AddItem(std::string const& item, const cmGeneratorTarget* tgt);
   void AddSharedDepItem(std::string const& item, cmGeneratorTarget const* tgt);
diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx
index d5225db..dec25ff 100644
--- a/Source/cmLinkLineComputer.cxx
+++ b/Source/cmLinkLineComputer.cxx
@@ -9,6 +9,7 @@
 
 #include "cmComputeLinkInformation.h"
 #include "cmGeneratorTarget.h"
+#include "cmLinkItem.h"
 #include "cmListFileCache.h"
 #include "cmOutputConverter.h"
 #include "cmStateDirectory.h"
@@ -58,6 +59,15 @@ std::string cmLinkLineComputer::ConvertToLinkReference(
 std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
 {
   std::string linkLibs;
+  std::vector<BT<std::string>> linkLibsList;
+  this->ComputeLinkLibs(cli, linkLibsList);
+  cli.AppendValues(linkLibs, linkLibsList);
+  return linkLibs;
+}
+
+void cmLinkLineComputer::ComputeLinkLibs(
+  cmComputeLinkInformation& cli, std::vector<BT<std::string>>& linkLibraries)
+{
   using ItemVector = cmComputeLinkInformation::ItemVector;
   ItemVector const& items = cli.GetItems();
   for (auto const& item : items) {
@@ -66,17 +76,32 @@ std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
       continue;
     }
 
+    BT<std::string> linkLib;
     if (item.IsPath) {
-      linkLibs += cli.GetLibLinkFileFlag();
-      linkLibs +=
+      linkLib.Value += cli.GetLibLinkFileFlag();
+      linkLib.Value +=
         this->ConvertToOutputFormat(this->ConvertToLinkReference(item.Value));
     } else {
-      linkLibs += item.Value;
+      linkLib.Value += item.Value;
+    }
+    linkLib.Value += " ";
+
+    const cmLinkImplementation* linkImpl =
+      cli.GetTarget()->GetLinkImplementation(cli.GetConfig());
+
+    for (const cmLinkImplItem& iter : linkImpl->Libraries) {
+      if (iter.Target != nullptr &&
+          iter.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+        std::string libPath = iter.Target->GetLocation(cli.GetConfig());
+        if (item.Value == libPath) {
+          linkLib.Backtrace = iter.Backtrace;
+          break;
+        }
+      }
     }
-    linkLibs += " ";
-  }
 
-  return linkLibs;
+    linkLibraries.emplace_back(linkLib);
+  }
 }
 
 std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input)
diff --git a/Source/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h
index 5e0f795..a6e0ebf 100644
--- a/Source/cmLinkLineComputer.h
+++ b/Source/cmLinkLineComputer.h
@@ -53,6 +53,8 @@ public:
 
 protected:
   std::string ComputeLinkLibs(cmComputeLinkInformation& cli);
+  void ComputeLinkLibs(cmComputeLinkInformation& cli,
+                       std::vector<BT<std::string>>& linkLibraries);
   std::string ComputeRPath(cmComputeLinkInformation& cli);
 
   std::string ConvertToOutputFormat(std::string const& input);

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0ac9dcb807d6e7b1f905bc9685f8ae217dfce38b
commit 0ac9dcb807d6e7b1f905bc9685f8ae217dfce38b
Author:     Justin Goshi <jgoshi at microsoft.com>
AuthorDate: Wed Sep 11 10:37:03 2019 -0700
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Sep 18 13:59:07 2019 -0400

    cmLinkLineComputer: Add ComputeLinkPath overload with backtraces

diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx
index 91c551f..d5225db 100644
--- a/Source/cmLinkLineComputer.cxx
+++ b/Source/cmLinkLineComputer.cxx
@@ -4,10 +4,12 @@
 #include "cmLinkLineComputer.h"
 
 #include <sstream>
+#include <utility>
 #include <vector>
 
 #include "cmComputeLinkInformation.h"
 #include "cmGeneratorTarget.h"
+#include "cmListFileCache.h"
 #include "cmOutputConverter.h"
 #include "cmStateDirectory.h"
 #include "cmStateTypes.h"
@@ -63,6 +65,7 @@ std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
         item.Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
       continue;
     }
+
     if (item.IsPath) {
       linkLibs += cli.GetLibLinkFileFlag();
       linkLibs +=
@@ -72,6 +75,7 @@ std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
     }
     linkLibs += " ";
   }
+
   return linkLibs;
 }
 
@@ -101,8 +105,19 @@ std::string cmLinkLineComputer::ComputeLinkPath(
   std::string const& libPathTerminator)
 {
   std::string linkPath;
+  std::vector<BT<std::string>> linkPathList;
+  this->ComputeLinkPath(cli, libPathFlag, libPathTerminator, linkPathList);
+  cli.AppendValues(linkPath, linkPathList);
+  return linkPath;
+}
 
+void cmLinkLineComputer::ComputeLinkPath(
+  cmComputeLinkInformation& cli, std::string const& libPathFlag,
+  std::string const& libPathTerminator, std::vector<BT<std::string>>& linkPath)
+{
   if (cli.GetLinkLanguage() == "Swift") {
+    std::string linkPathNoBT;
+
     for (const cmComputeLinkInformation::Item& item : cli.GetItems()) {
       const cmGeneratorTarget* target = item.Target;
       if (!target) {
@@ -116,20 +131,23 @@ std::string cmLinkLineComputer::ComputeLinkPath(
           type = cmStateEnums::ImportLibraryArtifact;
         }
 
-        linkPath += cmStrCat(" ", libPathFlag,
-                             item.Target->GetDirectory(cli.GetConfig(), type),
-                             libPathTerminator, " ");
+        linkPathNoBT += cmStrCat(
+          " ", libPathFlag, item.Target->GetDirectory(cli.GetConfig(), type),
+          libPathTerminator, " ");
       }
     }
-  }
 
-  for (std::string const& libDir : cli.GetDirectories()) {
-    linkPath +=
-      cmStrCat(" ", libPathFlag, this->ConvertToOutputForExisting(libDir),
-               libPathTerminator, " ");
+    if (!linkPathNoBT.empty()) {
+      linkPath.emplace_back(std::move(linkPathNoBT));
+    }
   }
 
-  return linkPath;
+  for (BT<std::string> libDir : cli.GetDirectoriesWithBacktraces()) {
+    libDir.Value = cmStrCat(" ", libPathFlag,
+                            this->ConvertToOutputForExisting(libDir.Value),
+                            libPathTerminator, " ");
+    linkPath.emplace_back(libDir);
+  }
 }
 
 std::string cmLinkLineComputer::ComputeRPath(cmComputeLinkInformation& cli)
diff --git a/Source/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h
index 2355c32..5e0f795 100644
--- a/Source/cmLinkLineComputer.h
+++ b/Source/cmLinkLineComputer.h
@@ -7,12 +7,15 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
+#include <vector>
 
 #include "cmStateDirectory.h"
 
 class cmComputeLinkInformation;
 class cmGeneratorTarget;
 class cmOutputConverter;
+template <typename T>
+class BT;
 
 class cmLinkLineComputer
 {
@@ -34,6 +37,11 @@ public:
                               std::string const& libPathFlag,
                               std::string const& libPathTerminator);
 
+  void ComputeLinkPath(cmComputeLinkInformation& cli,
+                       std::string const& libPathFlag,
+                       std::string const& libPathTerminator,
+                       std::vector<BT<std::string>>& linkPath);
+
   std::string ComputeFrameworkPath(cmComputeLinkInformation& cli,
                                    std::string const& fwSearchFlag);
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0c6468178a76b6a2a11791b010ab01c97855affa
commit 0c6468178a76b6a2a11791b010ab01c97855affa
Author:     Justin Goshi <jgoshi at microsoft.com>
AuthorDate: Wed Sep 11 10:31:05 2019 -0700
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Sep 18 09:58:41 2019 -0400

    cmComputeLinkInformation: Add GetDirectoriesWithBacktraces

diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index ed0bb85..6ee6455 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -431,6 +431,28 @@ std::vector<std::string> const& cmComputeLinkInformation::GetDirectories()
   return this->OrderLinkerSearchPath->GetOrderedDirectories();
 }
 
+std::vector<BT<std::string>>
+cmComputeLinkInformation::GetDirectoriesWithBacktraces()
+{
+  std::vector<BT<std::string>> directoriesWithBacktraces;
+
+  std::vector<BT<std::string>> targetLinkDirectores =
+    this->Target->GetLinkDirectories(this->Config, this->LinkLanguage);
+
+  const std::vector<std::string>& orderedDirectories = this->GetDirectories();
+  for (const std::string& dir : orderedDirectories) {
+    auto result =
+      std::find(targetLinkDirectores.begin(), targetLinkDirectores.end(), dir);
+    if (result != targetLinkDirectores.end()) {
+      directoriesWithBacktraces.emplace_back(std::move(*result));
+    } else {
+      directoriesWithBacktraces.emplace_back(dir);
+    }
+  }
+
+  return directoriesWithBacktraces;
+}
+
 std::string cmComputeLinkInformation::GetRPathLinkString() const
 {
   // If there is no separate linker runtime search flag (-rpath-link)
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index ee36a71..71af43f 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -48,6 +48,7 @@ public:
   void AppendValues(std::string& result, std::vector<BT<std::string>>& values);
   ItemVector const& GetItems() const;
   std::vector<std::string> const& GetDirectories() const;
+  std::vector<BT<std::string>> GetDirectoriesWithBacktraces();
   std::vector<std::string> const& GetDepends() const;
   std::vector<std::string> const& GetFrameworkPaths() const;
   std::string GetLinkLanguage() const { return this->LinkLanguage; }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a209b31d0d088de40ba5bebdc6c9650f0583b2a6
commit a209b31d0d088de40ba5bebdc6c9650f0583b2a6
Author:     Justin Goshi <jgoshi at microsoft.com>
AuthorDate: Wed Sep 11 10:28:38 2019 -0700
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Sep 18 09:57:30 2019 -0400

    cmComputeLinkInformation: Add AppendValues with backtraces

diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index dd8d246..ed0bb85 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -6,6 +6,7 @@
 #include "cmComputeLinkDepends.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
@@ -406,6 +407,18 @@ cmComputeLinkInformation::~cmComputeLinkInformation()
   delete this->OrderDependentRPath;
 }
 
+void cmComputeLinkInformation::AppendValues(
+  std::string& result, std::vector<BT<std::string>>& values)
+{
+  for (BT<std::string>& p : values) {
+    if (result.empty()) {
+      result.append(" ");
+    }
+
+    result.append(p.Value);
+  }
+}
+
 cmComputeLinkInformation::ItemVector const&
 cmComputeLinkInformation::GetItems() const
 {
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index 0f71381..ee36a71 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -17,6 +17,8 @@ class cmGlobalGenerator;
 class cmMakefile;
 class cmOrderDirectories;
 class cmake;
+template <typename T>
+class BT;
 
 /** \class cmComputeLinkInformation
  * \brief Compute link information for a target in one configuration.
@@ -43,6 +45,7 @@ public:
     cmGeneratorTarget const* Target = nullptr;
   };
   using ItemVector = std::vector<Item>;
+  void AppendValues(std::string& result, std::vector<BT<std::string>>& values);
   ItemVector const& GetItems() const;
   std::vector<std::string> const& GetDirectories() const;
   std::vector<std::string> const& GetDepends() const;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a583b7bc17b30c7772d6ca1909c71c0c14e6fabb
commit a583b7bc17b30c7772d6ca1909c71c0c14e6fabb
Author:     Daniel Eiband <daniel.eiband at brainlab.com>
AuthorDate: Wed Sep 11 18:18:47 2019 +0200
Commit:     Daniel Eiband <daniel.eiband at brainlab.com>
CommitDate: Tue Sep 17 22:58:31 2019 +0200

    Genex: Evaluate byproduct generator expressions in cmCustomCommandGenerator
    
    Evaluate and expand generator expressions in byproducts of custom commands.
    
    Note that it is still not possible to use generator expressions in byproducts
    of the commands `add_custom_command` and `add_custom_target`.  These commands
    still reject the input.  This is a preparation step for OUTPUT generator
    expression support.
    
    Issue: #12877

diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index d5d7041..ddb855b 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -72,6 +72,8 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
     this->CommandLines.push_back(std::move(argv));
   }
 
+  AppendPaths(cc.GetByproducts(), *this->GE, this->LG, this->Config,
+              this->Byproducts);
   AppendPaths(cc.GetDepends(), *this->GE, this->LG, this->Config,
               this->Depends);
 
@@ -248,7 +250,7 @@ std::vector<std::string> const& cmCustomCommandGenerator::GetOutputs() const
 
 std::vector<std::string> const& cmCustomCommandGenerator::GetByproducts() const
 {
-  return this->CC.GetByproducts();
+  return this->Byproducts;
 }
 
 std::vector<std::string> const& cmCustomCommandGenerator::GetDepends() const
diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h
index 766f4b8..d614302 100644
--- a/Source/cmCustomCommandGenerator.h
+++ b/Source/cmCustomCommandGenerator.h
@@ -23,6 +23,7 @@ class cmCustomCommandGenerator
   cmGeneratorExpression* GE;
   cmCustomCommandLines CommandLines;
   std::vector<std::vector<std::string>> EmulatorsWithArguments;
+  std::vector<std::string> Byproducts;
   std::vector<std::string> Depends;
   std::string WorkingDirectory;
 
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 84e95ef..482af22 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -221,7 +221,8 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
              this->GeneratorTarget->GetPostBuildCommands());
 
     for (const auto& be : buildEventCommands) {
-      const std::vector<std::string>& byproducts = be.GetByproducts();
+      cmCustomCommandGenerator beg(be, this->ConfigName, this->LocalGenerator);
+      const std::vector<std::string>& byproducts = beg.GetByproducts();
       for (std::string const& byproduct : byproducts) {
         this->CleanFiles.insert(
           this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ccc9685cc1fb61242f179a02661730140b026253
commit ccc9685cc1fb61242f179a02661730140b026253
Author:     Daniel Eiband <daniel.eiband at brainlab.com>
AuthorDate: Wed Sep 11 18:05:06 2019 +0200
Commit:     Daniel Eiband <daniel.eiband at brainlab.com>
CommitDate: Tue Sep 17 22:58:31 2019 +0200

    Genex: Move genex expansion of paths into AppendPaths utility
    
    Refactored internals of cmCustomCommandGenerator to make processing of path
    lists (evaluation of generator expressions and expansion into a list) available
    as AppendPaths utility function to be used for byproduct generator expression
    support.

diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 2c0cbfd..d5d7041 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -17,6 +17,26 @@
 #include <memory>
 #include <utility>
 
+namespace {
+void AppendPaths(const std::vector<std::string>& inputs,
+                 cmGeneratorExpression& ge, cmLocalGenerator* lg,
+                 std::string const& config, std::vector<std::string>& output)
+{
+  for (std::string const& in : inputs) {
+    std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(in);
+    std::vector<std::string> result =
+      cmExpandedList(cge->Evaluate(lg, config));
+    for (std::string& it : result) {
+      cmSystemTools::ConvertToUnixSlashes(it);
+      if (cmSystemTools::FileIsFullPath(it)) {
+        it = cmSystemTools::CollapseFullPath(it);
+      }
+    }
+    cmAppend(output, result);
+  }
+}
+}
+
 cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
                                                    std::string config,
                                                    cmLocalGenerator* lg)
@@ -46,25 +66,14 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
     // lists on an empty command may have left this empty.
     // FIXME: Should we define behavior for removing empty commands?
     if (argv.empty()) {
-      argv.push_back(std::string());
+      argv.emplace_back();
     }
 
     this->CommandLines.push_back(std::move(argv));
   }
 
-  std::vector<std::string> depends = this->CC.GetDepends();
-  for (std::string const& d : depends) {
-    std::unique_ptr<cmCompiledGeneratorExpression> cge = this->GE->Parse(d);
-    std::vector<std::string> result =
-      cmExpandedList(cge->Evaluate(this->LG, this->Config));
-    for (std::string& it : result) {
-      cmSystemTools::ConvertToUnixSlashes(it);
-      if (cmSystemTools::FileIsFullPath(it)) {
-        it = cmSystemTools::CollapseFullPath(it);
-      }
-    }
-    cmAppend(this->Depends, result);
-  }
+  AppendPaths(cc.GetDepends(), *this->GE, this->LG, this->Config,
+              this->Depends);
 
   const std::string& workingdirectory = this->CC.GetWorkingDirectory();
   if (!workingdirectory.empty()) {

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=026ef9b312047778ac0638cf2d2ef8bed6a2b3f2
commit 026ef9b312047778ac0638cf2d2ef8bed6a2b3f2
Author:     Daniel Eiband <daniel.eiband at brainlab.com>
AuthorDate: Wed Sep 11 17:56:42 2019 +0200
Commit:     Daniel Eiband <daniel.eiband at brainlab.com>
CommitDate: Tue Sep 17 22:58:31 2019 +0200

    Refactoring: Use ConfigName instead of property CMAKE_BUILD_TYPE
    
    Use memorized `this->ConfigName` instead of retrieving the value of property
    CMAKE_BUILD_TYPE.

diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index f80695d..0be1de5 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -161,8 +161,7 @@ void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles(
       continue;
     }
     std::vector<cmSourceFile const*> objectSources;
-    gt->GetObjectSources(
-      objectSources, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
+    gt->GetObjectSources(objectSources, this->ConfigName);
     // Compute full path to object file directory for this target.
     std::string dir = cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(),
                                '/', this->GetTargetDirectory(gt), '/');
@@ -1864,9 +1863,8 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
                     << "_TARGET_INCLUDE_PATH\n";
     std::vector<std::string> includes;
 
-    const std::string& config =
-      this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
-    this->GetIncludeDirectories(includes, target, implicitLang.first, config);
+    this->GetIncludeDirectories(includes, target, implicitLang.first,
+                                this->ConfigName);
     std::string binaryDir = this->GetState()->GetBinaryDirectory();
     if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) {
       std::string const& sourceDir = this->GetState()->GetSourceDirectory();
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 477badd..84e95ef 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -150,16 +150,13 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
 {
   // -- Write the custom commands for this target
 
-  const std::string& config =
-    this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
-
   // Evaluates generator expressions and expands prop_value
   auto evaluatedFiles =
-    [this, &config](const char* prop_value) -> std::vector<std::string> {
+    [this](const char* prop_value) -> std::vector<std::string> {
     std::vector<std::string> files;
     cmGeneratorExpression ge;
     std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop_value);
-    cmExpandList(cge->Evaluate(this->LocalGenerator, config, false,
+    cmExpandList(cge->Evaluate(this->LocalGenerator, this->ConfigName, false,
                                this->GeneratorTarget, nullptr, nullptr),
                  files);
     return files;
@@ -191,7 +188,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
   // First generate the object rule files.  Save a list of all object
   // files for this target.
   std::vector<cmSourceFile const*> customCommands;
-  this->GeneratorTarget->GetCustomCommands(customCommands, config);
+  this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName);
   std::string currentBinDir =
     this->LocalGenerator->GetCurrentBinaryDirectory();
   for (cmSourceFile const* sf : customCommands) {
@@ -233,17 +230,17 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
     }
   }
   std::vector<cmSourceFile const*> headerSources;
-  this->GeneratorTarget->GetHeaderSources(headerSources, config);
+  this->GeneratorTarget->GetHeaderSources(headerSources, this->ConfigName);
   this->OSXBundleGenerator->GenerateMacOSXContentStatements(
     headerSources, this->MacOSXContentGenerator);
   std::vector<cmSourceFile const*> extraSources;
-  this->GeneratorTarget->GetExtraSources(extraSources, config);
+  this->GeneratorTarget->GetExtraSources(extraSources, this->ConfigName);
   this->OSXBundleGenerator->GenerateMacOSXContentStatements(
     extraSources, this->MacOSXContentGenerator);
   const char* pchExtension =
     this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
   std::vector<cmSourceFile const*> externalObjects;
-  this->GeneratorTarget->GetExternalObjects(externalObjects, config);
+  this->GeneratorTarget->GetExternalObjects(externalObjects, this->ConfigName);
   for (cmSourceFile const* sf : externalObjects) {
     auto const& objectFileName = sf->GetFullPath();
     if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) {
@@ -251,7 +248,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
     }
   }
   std::vector<cmSourceFile const*> objectSources;
-  this->GeneratorTarget->GetObjectSources(objectSources, config);
+  this->GeneratorTarget->GetObjectSources(objectSources, this->ConfigName);
   for (cmSourceFile const* sf : objectSources) {
     // Generate this object file's rule file.
     this->WriteObjectRuleFiles(*sf);
@@ -1610,10 +1607,8 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
 {
   std::string frameworkPath;
   std::string linkPath;
-  const std::string& config =
-    this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
   cmComputeLinkInformation* pcli =
-    this->GeneratorTarget->GetLinkInformation(config);
+    this->GeneratorTarget->GetLinkInformation(this->ConfigName);
   this->LocalGenerator->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
                                             frameworkPath, linkPath);
   linkLibs = frameworkPath + linkPath + linkLibs;
@@ -1706,13 +1701,12 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
   bool useResponseFile = this->Makefile->IsOn(responseVar);
 
   std::vector<std::string> includes;
-  const std::string& config =
-    this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
   this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
-                                              lang, config);
+                                              lang, this->ConfigName);
 
   std::string includeFlags = this->LocalGenerator->GetIncludeFlags(
-    includes, this->GeneratorTarget, lang, false, useResponseFile, config);
+    includes, this->GeneratorTarget, lang, false, useResponseFile,
+    this->ConfigName);
   if (includeFlags.empty()) {
     return;
   }
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 37e9e0e..84a98fd 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -777,11 +777,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
     << cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType())
     << " target " << this->GetTargetName() << "\n\n";
 
-  const std::string& config =
-    this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
   {
     std::vector<cmSourceFile const*> customCommands;
-    this->GeneratorTarget->GetCustomCommands(customCommands, config);
+    this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName);
     for (cmSourceFile const* sf : customCommands) {
       cmCustomCommand const* cc = sf->GetCustomCommand();
       this->GetLocalGenerator()->AddCustomCommandTarget(
@@ -793,13 +791,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
   }
   {
     std::vector<cmSourceFile const*> headerSources;
-    this->GeneratorTarget->GetHeaderSources(headerSources, config);
+    this->GeneratorTarget->GetHeaderSources(headerSources, this->ConfigName);
     this->OSXBundleGenerator->GenerateMacOSXContentStatements(
       headerSources, this->MacOSXContentGenerator.get());
   }
   {
     std::vector<cmSourceFile const*> extraSources;
-    this->GeneratorTarget->GetExtraSources(extraSources, config);
+    this->GeneratorTarget->GetExtraSources(extraSources, this->ConfigName);
     this->OSXBundleGenerator->GenerateMacOSXContentStatements(
       extraSources, this->MacOSXContentGenerator.get());
   }
@@ -808,7 +806,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
       GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
 
     std::vector<cmSourceFile const*> externalObjects;
-    this->GeneratorTarget->GetExternalObjects(externalObjects, config);
+    this->GeneratorTarget->GetExternalObjects(externalObjects,
+                                              this->ConfigName);
     for (cmSourceFile const* sf : externalObjects) {
       const auto objectFileName = this->GetSourceFilePath(sf);
       if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) {
@@ -863,7 +862,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
 
   {
     std::vector<cmSourceFile const*> objectSources;
-    this->GeneratorTarget->GetObjectSources(objectSources, config);
+    this->GeneratorTarget->GetObjectSources(objectSources, this->ConfigName);
     for (cmSourceFile const* sf : objectSources) {
       this->WriteObjectBuildStatement(sf);
     }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0e1faa28cbd12d400b876f7a21d91aad5a837196
commit 0e1faa28cbd12d400b876f7a21d91aad5a837196
Author:     Daniel Eiband <daniel.eiband at brainlab.com>
AuthorDate: Sat Sep 14 22:59:05 2019 +0200
Commit:     Daniel Eiband <daniel.eiband at brainlab.com>
CommitDate: Tue Sep 17 22:52:32 2019 +0200

    cmMakefile: Separate custom command setup from actual creation
    
    Refactor custom command manipulation functions to consist of a setup and a
    commit stage.  The commit stage will be delayed to generate time.

diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 19cd068..b3a0678 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -910,6 +910,21 @@ cmTarget* cmMakefile::AddCustomCommandToTarget(
   // Always create the byproduct sources and mark them generated.
   this->CreateGeneratedSources(byproducts);
 
+  this->CommitCustomCommandToTarget(
+    t, byproducts, depends, commandLines, type, comment, workingDir,
+    escapeOldStyle, uses_terminal, depfile, job_pool, command_expand_lists);
+
+  return t;
+}
+
+void cmMakefile::CommitCustomCommandToTarget(
+  cmTarget* target, const std::vector<std::string>& byproducts,
+  const std::vector<std::string>& depends,
+  const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type,
+  const char* comment, const char* workingDir, bool escapeOldStyle,
+  bool uses_terminal, const std::string& depfile, const std::string& job_pool,
+  bool command_expand_lists)
+{
   // Add the command to the appropriate build step for the target.
   std::vector<std::string> no_output;
   cmCustomCommand cc(this, no_output, byproducts, depends, commandLines,
@@ -922,18 +937,16 @@ cmTarget* cmMakefile::AddCustomCommandToTarget(
   cc.SetJobPool(job_pool);
   switch (type) {
     case cmTarget::PRE_BUILD:
-      t->AddPreBuildCommand(cc);
+      target->AddPreBuildCommand(cc);
       break;
     case cmTarget::PRE_LINK:
-      t->AddPreLinkCommand(cc);
+      target->AddPreLinkCommand(cc);
       break;
     case cmTarget::POST_BUILD:
-      t->AddPostBuildCommand(cc);
+      target->AddPostBuildCommand(cc);
       break;
   }
-  this->UpdateOutputToSourceMap(byproducts, t);
-
-  return t;
+  this->UpdateOutputToSourceMap(byproducts, target);
 }
 
 void cmMakefile::UpdateOutputToSourceMap(
@@ -967,6 +980,23 @@ void cmMakefile::UpdateOutputToSourceMap(std::string const& byproduct,
 }
 
 cmSourceFile* cmMakefile::AddCustomCommandToOutput(
+  const std::string& output, const std::vector<std::string>& depends,
+  const std::string& main_dependency, const cmCustomCommandLines& commandLines,
+  const char* comment, const char* workingDir, bool replace,
+  bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
+  const std::string& depfile, const std::string& job_pool)
+{
+  std::vector<std::string> outputs;
+  outputs.push_back(output);
+  std::vector<std::string> no_byproducts;
+  cmImplicitDependsList no_implicit_depends;
+  return this->AddCustomCommandToOutput(
+    outputs, no_byproducts, depends, main_dependency, no_implicit_depends,
+    commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
+    command_expand_lists, depfile, job_pool);
+}
+
+cmSourceFile* cmMakefile::AddCustomCommandToOutput(
   const std::vector<std::string>& outputs,
   const std::vector<std::string>& byproducts,
   const std::vector<std::string>& depends, const std::string& main_dependency,
@@ -991,6 +1021,22 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput(
   this->CreateGeneratedSources(outputs);
   this->CreateGeneratedSources(byproducts);
 
+  return this->CommitCustomCommandToOutput(
+    outputs, byproducts, depends, main_dependency, implicit_depends,
+    commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
+    command_expand_lists, depfile, job_pool);
+}
+
+cmSourceFile* cmMakefile::CommitCustomCommandToOutput(
+  const std::vector<std::string>& outputs,
+  const std::vector<std::string>& byproducts,
+  const std::vector<std::string>& depends, const std::string& main_dependency,
+  const cmImplicitDependsList& implicit_depends,
+  const cmCustomCommandLines& commandLines, const char* comment,
+  const char* workingDir, bool replace, bool escapeOldStyle,
+  bool uses_terminal, bool command_expand_lists, const std::string& depfile,
+  const std::string& job_pool)
+{
   // Choose a source file on which to store the custom command.
   cmSourceFile* file = nullptr;
   if (!commandLines.empty() && !main_dependency.empty()) {
@@ -1099,23 +1145,6 @@ void cmMakefile::UpdateOutputToSourceMap(std::string const& output,
   }
 }
 
-cmSourceFile* cmMakefile::AddCustomCommandToOutput(
-  const std::string& output, const std::vector<std::string>& depends,
-  const std::string& main_dependency, const cmCustomCommandLines& commandLines,
-  const char* comment, const char* workingDir, bool replace,
-  bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
-  const std::string& depfile, const std::string& job_pool)
-{
-  std::vector<std::string> outputs;
-  outputs.push_back(output);
-  std::vector<std::string> no_byproducts;
-  cmImplicitDependsList no_implicit_depends;
-  return this->AddCustomCommandToOutput(
-    outputs, no_byproducts, depends, main_dependency, no_implicit_depends,
-    commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
-    command_expand_lists, depfile, job_pool);
-}
-
 void cmMakefile::AddCustomCommandOldStyle(
   const std::string& target, const std::vector<std::string>& outputs,
   const std::vector<std::string>& depends, const std::string& source,
@@ -1188,19 +1217,34 @@ bool cmMakefile::AppendCustomCommandToOutput(
   const cmImplicitDependsList& implicit_depends,
   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.
+  if (this->ValidateCustomCommand(commandLines)) {
+    // Add command factory to allow generator expressions in output.
+    this->CommitAppendCustomCommandToOutput(output, depends, implicit_depends,
+                                            commandLines);
+  }
+
+  return true;
+}
+
+void cmMakefile::CommitAppendCustomCommandToOutput(
+  const std::string& output, const std::vector<std::string>& depends,
+  const cmImplicitDependsList& implicit_depends,
+  const cmCustomCommandLines& commandLines)
+{
   // Lookup an existing command.
   if (cmSourceFile* sf = this->GetSourceFileWithOutput(output)) {
     if (cmCustomCommand* cc = sf->GetCustomCommand()) {
-      // Validate custom commands.
-      if (this->ValidateCustomCommand(commandLines)) {
-        cc->AppendCommands(commandLines);
-        cc->AppendDepends(depends);
-        cc->AppendImplicitDepends(implicit_depends);
-      }
-      return true;
+      cc->AppendCommands(commandLines);
+      cc->AppendDepends(depends);
+      cc->AppendImplicitDepends(implicit_depends);
     }
   }
-  return false;
 }
 
 cmTarget* cmMakefile::AddUtilityCommand(
@@ -1261,11 +1305,6 @@ cmTarget* cmMakefile::AddUtilityCommand(
     target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
   }
 
-  if (!comment) {
-    // Use an empty comment to avoid generation of default comment.
-    comment = "";
-  }
-
   // Validate custom commands.
   if (!this->ValidateCustomCommand(commandLines) ||
       (commandLines.empty() && depends.empty())) {
@@ -1277,27 +1316,58 @@ cmTarget* cmMakefile::AddUtilityCommand(
 
   std::string force =
     cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/", utilityName);
+  this->CreateGeneratedSource(force);
+  std::string forceCMP0049 = target->GetSourceCMP0049(force);
+  {
+    cmSourceFile* sf = nullptr;
+    if (!forceCMP0049.empty()) {
+      sf = this->GetOrCreateSource(forceCMP0049, false,
+                                   cmSourceFileLocationKind::Known);
+    }
+    // The output is not actually created so mark it symbolic.
+    if (sf) {
+      sf->SetProperty("SYMBOLIC", "1");
+    } else {
+      cmSystemTools::Error("Could not get source file entry for " + force);
+    }
+  }
+
+  if (!comment) {
+    // Use an empty comment to avoid generation of default comment.
+    comment = "";
+  }
+
+  this->CommitUtilityCommand(target, force, forceCMP0049, workingDirectory,
+                             byproducts, depends, commandLines, escapeOldStyle,
+                             comment, uses_terminal, command_expand_lists,
+                             job_pool);
+
+  return target;
+}
+
+void cmMakefile::CommitUtilityCommand(
+  cmTarget* target, const std::string& force, const std::string& forceCMP0049,
+  const char* workingDirectory, const std::vector<std::string>& byproducts,
+  const std::vector<std::string>& depends,
+  const cmCustomCommandLines& commandLines, bool escapeOldStyle,
+  const char* comment, bool uses_terminal, bool command_expand_lists,
+  const std::string& job_pool)
+{
   std::vector<std::string> forced;
   forced.push_back(force);
   std::string no_main_dependency;
   cmImplicitDependsList no_implicit_depends;
   bool no_replace = false;
-  this->AddCustomCommandToOutput(
+  cmSourceFile* sf = this->AddCustomCommandToOutput(
     forced, byproducts, depends, no_main_dependency, no_implicit_depends,
     commandLines, comment, workingDirectory, no_replace, escapeOldStyle,
     uses_terminal, command_expand_lists, /*depfile=*/"", job_pool);
-  cmSourceFile* sf = target->AddSourceCMP0049(force);
-
-  // The output is not actually created so mark it symbolic.
+  if (!forceCMP0049.empty()) {
+    target->AddSource(forceCMP0049);
+  }
   if (sf) {
-    sf->SetProperty("SYMBOLIC", "1");
-  } else {
-    cmSystemTools::Error("Could not get source file entry for " + force);
+    this->UpdateOutputToSourceMap(byproducts, target);
   }
-
-  this->UpdateOutputToSourceMap(byproducts, target);
-
-  return target;
 }
 
 static void s_AddDefineFlag(std::string const& flag, std::string& dflags)
@@ -2233,6 +2303,18 @@ cmSourceFile* cmMakefile::GetSourceFileWithOutput(
   return nullptr;
 }
 
+bool cmMakefile::MightHaveCustomCommand(const std::string& name) const
+{
+  // This will have to be changed for delaying custom command creation, because
+  // GetSourceFileWithOutput requires the command to be already created.
+  if (cmSourceFile* sf = this->GetSourceFileWithOutput(name)) {
+    if (sf->GetCustomCommand()) {
+      return true;
+    }
+  }
+  return false;
+}
+
 #if !defined(CMAKE_BOOTSTRAP)
 cmSourceGroup* cmMakefile::GetSourceGroup(
   const std::vector<std::string>& name) const
@@ -3477,14 +3559,19 @@ cmSourceFile* cmMakefile::GetOrCreateSource(const std::string& sourceName,
   return this->CreateSource(sourceName, generated, kind);
 }
 
+void cmMakefile::CreateGeneratedSource(const std::string& output)
+{
+  if (cmSourceFile* out = this->GetOrCreateSource(
+        output, true, cmSourceFileLocationKind::Known)) {
+    out->SetProperty("GENERATED", "1");
+  }
+}
+
 void cmMakefile::CreateGeneratedSources(
   const std::vector<std::string>& outputs)
 {
   for (std::string const& output : outputs) {
-    if (cmSourceFile* out = this->GetOrCreateSource(
-          output, true, cmSourceFileLocationKind::Known)) {
-      out->SetProperty("GENERATED", "1");
-    }
+    this->CreateGeneratedSource(output);
   }
 }
 
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index ed118db..19a71ad 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -181,18 +181,18 @@ public:
     const std::string& job_pool = "", bool command_expand_lists = false,
     ObjectLibraryCommands objLibraryCommands = RejectObjectLibraryCommands);
   cmSourceFile* AddCustomCommandToOutput(
-    const std::vector<std::string>& outputs,
-    const std::vector<std::string>& byproducts,
-    const std::vector<std::string>& depends,
+    const std::string& output, const std::vector<std::string>& depends,
     const std::string& main_dependency,
-    const cmImplicitDependsList& implicit_depends,
     const cmCustomCommandLines& commandLines, const char* comment,
     const char* workingDir, bool replace = false, bool escapeOldStyle = true,
     bool uses_terminal = false, bool command_expand_lists = false,
     const std::string& depfile = "", const std::string& job_pool = "");
   cmSourceFile* AddCustomCommandToOutput(
-    const std::string& output, const std::vector<std::string>& depends,
+    const std::vector<std::string>& outputs,
+    const std::vector<std::string>& byproducts,
+    const std::vector<std::string>& depends,
     const std::string& main_dependency,
+    const cmImplicitDependsList& implicit_depends,
     const cmCustomCommandLines& commandLines, const char* comment,
     const char* workingDir, bool replace = false, bool escapeOldStyle = true,
     bool uses_terminal = false, bool command_expand_lists = false,
@@ -1069,6 +1069,39 @@ private:
 
   bool ValidateCustomCommand(const cmCustomCommandLines& commandLines) const;
 
+  void CommitCustomCommandToTarget(
+    cmTarget* target, const std::vector<std::string>& byproducts,
+    const std::vector<std::string>& depends,
+    const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type,
+    const char* comment, const char* workingDir, bool escapeOldStyle,
+    bool uses_terminal, const std::string& depfile,
+    const std::string& job_pool, bool command_expand_lists);
+  cmSourceFile* CommitCustomCommandToOutput(
+    const std::vector<std::string>& outputs,
+    const std::vector<std::string>& byproducts,
+    const std::vector<std::string>& depends,
+    const std::string& main_dependency,
+    const cmImplicitDependsList& implicit_depends,
+    const cmCustomCommandLines& commandLines, const char* comment,
+    const char* workingDir, bool replace, bool escapeOldStyle,
+    bool uses_terminal, bool command_expand_lists, const std::string& depfile,
+    const std::string& job_pool);
+  void CommitAppendCustomCommandToOutput(
+    const std::string& output, const std::vector<std::string>& depends,
+    const cmImplicitDependsList& implicit_depends,
+    const cmCustomCommandLines& commandLines);
+
+  void CommitUtilityCommand(cmTarget* target, const std::string& force,
+                            const std::string& forceCMP0049,
+                            const char* workingDirectory,
+                            const std::vector<std::string>& byproducts,
+                            const std::vector<std::string>& depends,
+                            const cmCustomCommandLines& commandLines,
+                            bool escapeOldStyle, const char* comment,
+                            bool uses_terminal, bool command_expand_lists,
+                            const std::string& job_pool);
+
+  void CreateGeneratedSource(const std::string& output);
   void CreateGeneratedSources(const std::vector<std::string>& outputs);
 
   /**
@@ -1104,6 +1137,11 @@ private:
   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 AddRequiredTargetCFeature(cmTarget* target, const std::string& feature,
                                  std::string* error = nullptr) const;
 
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 6637e32..83d69a4 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -694,13 +694,9 @@ std::string cmTargetInternals::ProcessSourceItemCMP0049(const std::string& s)
   return src;
 }
 
-cmSourceFile* cmTarget::AddSourceCMP0049(const std::string& s)
+std::string cmTarget::GetSourceCMP0049(const std::string& s)
 {
-  std::string src = impl->ProcessSourceItemCMP0049(s);
-  if (!s.empty() && src.empty()) {
-    return nullptr;
-  }
-  return this->AddSource(src);
+  return impl->ProcessSourceItemCMP0049(s);
 }
 
 struct CreateLocation
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index e9bcffe..f4726d3 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -103,7 +103,7 @@ public:
   //! Add sources to the target.
   void AddSources(std::vector<std::string> const& srcs);
   void AddTracedSources(std::vector<std::string> const& srcs);
-  cmSourceFile* AddSourceCMP0049(const std::string& src);
+  std::string GetSourceCMP0049(const std::string& src);
   cmSourceFile* AddSource(const std::string& src, bool before = false);
 
   //! how we identify a library, by name and type

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=56c204e8eb8914b2ca273a56119cf1c40e13d75d
commit 56c204e8eb8914b2ca273a56119cf1c40e13d75d
Author:     Daniel Eiband <daniel.eiband at brainlab.com>
AuthorDate: Sat Sep 14 22:01:20 2019 +0200
Commit:     Daniel Eiband <daniel.eiband at brainlab.com>
CommitDate: Tue Sep 17 22:52:32 2019 +0200

    cmMakefile: Refactor AddCustomCommandOldStyle to be delay friendly
    
    Custom command functions consist of two parts: setup and commit.  Only the
    commit part will be delayed to generate time.  This change puts the commit part
    of AddCustomCommandOldStyle into a lambda.  When delayed, it will not be
    possible to break the loop over the outputs if an error occurs which seems
    reasonable.

diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 6707b1c..19cd068 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -1134,41 +1134,50 @@ void cmMakefile::AddCustomCommandOldStyle(
     return;
   }
 
-  // Each output must get its own copy of this rule.
-  cmsys::RegularExpression sourceFiles("\\.(C|M|c|c\\+\\+|cc|cpp|cxx|cu|m|mm|"
-                                       "rc|def|r|odl|idl|hpj|bat|h|h\\+\\+|"
-                                       "hm|hpp|hxx|in|txx|inl)$");
-  for (std::string const& oi : outputs) {
-    // Get the name of this output.
-    const char* output = oi.c_str();
-    cmSourceFile* sf;
-
-    // Choose whether to use a main dependency.
-    if (sourceFiles.find(source)) {
-      // The source looks like a real file.  Use it as the main dependency.
-      sf = this->AddCustomCommandToOutput(output, depends, source,
-                                          commandLines, comment, nullptr);
-    } else {
-      // The source may not be a real file.  Do not use a main dependency.
-      std::string no_main_dependency;
-      std::vector<std::string> depends2 = depends;
-      depends2.push_back(source);
-      sf = this->AddCustomCommandToOutput(output, depends2, no_main_dependency,
-                                          commandLines, comment, nullptr);
-    }
+  auto ti = this->Targets.find(target);
+  cmTarget* t = ti != this->Targets.end() ? &ti->second : nullptr;
 
+  auto addRuleFileToTarget = [=](cmSourceFile* sf) {
     // If the rule was added to the source (and not a .rule file),
     // then add the source to the target to make sure the rule is
     // included.
-    if (sf && !sf->GetPropertyAsBool("__CMAKE_RULE")) {
-      auto ti = this->Targets.find(target);
-      if (ti != this->Targets.end()) {
-        ti->second.AddSource(sf->ResolveFullPath());
+    if (!sf->GetPropertyAsBool("__CMAKE_RULE")) {
+      if (t) {
+        t->AddSource(sf->ResolveFullPath());
       } else {
         cmSystemTools::Error("Attempt to add a custom rule to a target "
                              "that does not exist yet for target " +
                              target);
-        return;
+      }
+    }
+  };
+
+  // Each output must get its own copy of this rule.
+  cmsys::RegularExpression sourceFiles("\\.(C|M|c|c\\+\\+|cc|cpp|cxx|cu|m|mm|"
+                                       "rc|def|r|odl|idl|hpj|bat|h|h\\+\\+|"
+                                       "hm|hpp|hxx|in|txx|inl)$");
+
+  // Choose whether to use a main dependency.
+  if (sourceFiles.find(source)) {
+    // The source looks like a real file.  Use it as the main dependency.
+    for (std::string const& output : outputs) {
+      cmSourceFile* sf = this->AddCustomCommandToOutput(
+        output, depends, source, commandLines, comment, nullptr);
+      if (sf) {
+        addRuleFileToTarget(sf);
+      }
+    }
+  } else {
+    std::string no_main_dependency;
+    std::vector<std::string> depends2 = depends;
+    depends2.push_back(source);
+
+    // The source may not be a real file.  Do not use a main dependency.
+    for (std::string const& output : outputs) {
+      cmSourceFile* sf = this->AddCustomCommandToOutput(
+        output, depends2, no_main_dependency, commandLines, comment, nullptr);
+      if (sf) {
+        addRuleFileToTarget(sf);
       }
     }
   }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3061dc6ac967e859424f81fb70bbc70a74246055
commit 3061dc6ac967e859424f81fb70bbc70a74246055
Author:     Daniel Eiband <daniel.eiband at brainlab.com>
AuthorDate: Sat Sep 14 21:44:42 2019 +0200
Commit:     Daniel Eiband <daniel.eiband at brainlab.com>
CommitDate: Tue Sep 17 22:52:32 2019 +0200

    add_custom_command: Add tests for rejecting literal quotes in commands

diff --git a/Tests/RunCMake/add_custom_command/AppendLiteralQuotes-result.txt b/Tests/RunCMake/add_custom_command/AppendLiteralQuotes-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/AppendLiteralQuotes-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/add_custom_command/AppendLiteralQuotes-stderr.txt b/Tests/RunCMake/add_custom_command/AppendLiteralQuotes-stderr.txt
new file mode 100644
index 0000000..503385f
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/AppendLiteralQuotes-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error at AppendLiteralQuotes.cmake:2 \(add_custom_command\):
+  COMMAND may not contain literal quotes:
+
+    "c"
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/add_custom_command/AppendLiteralQuotes.cmake b/Tests/RunCMake/add_custom_command/AppendLiteralQuotes.cmake
new file mode 100644
index 0000000..038fb3f
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/AppendLiteralQuotes.cmake
@@ -0,0 +1,2 @@
+add_custom_command(OUTPUT a COMMAND b)
+add_custom_command(OUTPUT a COMMAND "\"c\"" APPEND)
diff --git a/Tests/RunCMake/add_custom_command/LiteralQuotes-result.txt b/Tests/RunCMake/add_custom_command/LiteralQuotes-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/LiteralQuotes-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/add_custom_command/LiteralQuotes-stderr.txt b/Tests/RunCMake/add_custom_command/LiteralQuotes-stderr.txt
new file mode 100644
index 0000000..e7d6155
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/LiteralQuotes-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error at LiteralQuotes.cmake:1 \(add_custom_command\):
+  COMMAND may not contain literal quotes:
+
+    "b"
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/add_custom_command/LiteralQuotes.cmake b/Tests/RunCMake/add_custom_command/LiteralQuotes.cmake
new file mode 100644
index 0000000..046ddd9
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/LiteralQuotes.cmake
@@ -0,0 +1 @@
+add_custom_command(OUTPUT a COMMAND "\"b\"")
diff --git a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
index 20097b7..270df2f 100644
--- a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake
@@ -1,15 +1,18 @@
 include(RunCMake)
 
+run_cmake(AppendLiteralQuotes)
 run_cmake(AppendNoOutput)
 run_cmake(AppendNotOutput)
 run_cmake(BadArgument)
 run_cmake(GeneratedProperty)
+run_cmake(LiteralQuotes)
 run_cmake(NoArguments)
 run_cmake(NoOutputOrTarget)
 run_cmake(OutputAndTarget)
 run_cmake(SourceByproducts)
 run_cmake(SourceUsesTerminal)
 run_cmake(TargetImported)
+run_cmake(TargetLiteralQuotes)
 run_cmake(TargetNotInDir)
 
 if(${RunCMake_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])")
diff --git a/Tests/RunCMake/add_custom_command/TargetLiteralQuotes-result.txt b/Tests/RunCMake/add_custom_command/TargetLiteralQuotes-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/TargetLiteralQuotes-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/add_custom_command/TargetLiteralQuotes-stderr.txt b/Tests/RunCMake/add_custom_command/TargetLiteralQuotes-stderr.txt
new file mode 100644
index 0000000..c4589b4
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/TargetLiteralQuotes-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error at TargetLiteralQuotes.cmake:2 \(add_custom_command\):
+  COMMAND may not contain literal quotes:
+
+    "b"
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/add_custom_command/TargetLiteralQuotes.cmake b/Tests/RunCMake/add_custom_command/TargetLiteralQuotes.cmake
new file mode 100644
index 0000000..5f11ed1
--- /dev/null
+++ b/Tests/RunCMake/add_custom_command/TargetLiteralQuotes.cmake
@@ -0,0 +1,2 @@
+add_library(a)
+add_custom_command(TARGET a POST_BUILD COMMAND "\"b\"")
diff --git a/Tests/RunCMake/add_custom_target/LiteralQuotes-result.txt b/Tests/RunCMake/add_custom_target/LiteralQuotes-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/LiteralQuotes-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/add_custom_target/LiteralQuotes-stderr.txt b/Tests/RunCMake/add_custom_target/LiteralQuotes-stderr.txt
new file mode 100644
index 0000000..bc5187a
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/LiteralQuotes-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error at LiteralQuotes.cmake:1 \(add_custom_target\):
+  COMMAND may not contain literal quotes:
+
+    "b"
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/add_custom_target/LiteralQuotes.cmake b/Tests/RunCMake/add_custom_target/LiteralQuotes.cmake
new file mode 100644
index 0000000..9870608
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/LiteralQuotes.cmake
@@ -0,0 +1 @@
+add_custom_target(a COMMAND "\"b\"")
diff --git a/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
index d80ca19..49c7d3e 100644
--- a/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
@@ -5,6 +5,7 @@ run_cmake(GeneratedProperty)
 run_cmake(NoArguments)
 run_cmake(BadTargetName)
 run_cmake(ByproductsNoCommand)
+run_cmake(LiteralQuotes)
 run_cmake(UsesTerminalNoCommand)
 
 function(run_TargetOrder)

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e893ab94baa29b4a21d3edd86174cd19d8cd5a1e
commit e893ab94baa29b4a21d3edd86174cd19d8cd5a1e
Author:     Daniel Eiband <daniel.eiband at brainlab.com>
AuthorDate: Sat Sep 14 15:29:59 2019 +0200
Commit:     Daniel Eiband <daniel.eiband at brainlab.com>
CommitDate: Tue Sep 17 22:50:25 2019 +0200

    cmMakefile: Validate command line for all custom commands

diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 6462c26..6707b1c 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -837,7 +837,7 @@ bool cmMakefile::ValidateCustomCommand(
   return true;
 }
 
-void cmMakefile::AddCustomCommandToTarget(
+cmTarget* cmMakefile::AddCustomCommandToTarget(
   const std::string& target, const std::vector<std::string>& byproducts,
   const std::vector<std::string>& depends,
   const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type,
@@ -880,26 +880,31 @@ void cmMakefile::AddCustomCommandToTarget(
       this->IssueMessage(messageType, e.str());
     }
 
-    return;
+    return nullptr;
   }
 
-  cmTarget& t = ti->second;
+  cmTarget* t = &ti->second;
   if (objLibraryCommands == RejectObjectLibraryCommands &&
-      t.GetType() == cmStateEnums::OBJECT_LIBRARY) {
+      t->GetType() == cmStateEnums::OBJECT_LIBRARY) {
     std::ostringstream e;
     e << "Target \"" << target
       << "\" is an OBJECT library "
          "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands.";
     this->IssueMessage(MessageType::FATAL_ERROR, e.str());
-    return;
+    return nullptr;
   }
-  if (t.GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+  if (t->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
     std::ostringstream e;
     e << "Target \"" << target
       << "\" is an INTERFACE library "
          "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands.";
     this->IssueMessage(MessageType::FATAL_ERROR, e.str());
-    return;
+    return nullptr;
+  }
+
+  // Validate custom commands.
+  if (!this->ValidateCustomCommand(commandLines)) {
+    return t;
   }
 
   // Always create the byproduct sources and mark them generated.
@@ -917,16 +922,18 @@ void cmMakefile::AddCustomCommandToTarget(
   cc.SetJobPool(job_pool);
   switch (type) {
     case cmTarget::PRE_BUILD:
-      t.AddPreBuildCommand(cc);
+      t->AddPreBuildCommand(cc);
       break;
     case cmTarget::PRE_LINK:
-      t.AddPreLinkCommand(cc);
+      t->AddPreLinkCommand(cc);
       break;
     case cmTarget::POST_BUILD:
-      t.AddPostBuildCommand(cc);
+      t->AddPostBuildCommand(cc);
       break;
   }
-  this->UpdateOutputToSourceMap(byproducts, &t);
+  this->UpdateOutputToSourceMap(byproducts, t);
+
+  return t;
 }
 
 void cmMakefile::UpdateOutputToSourceMap(
@@ -1175,9 +1182,12 @@ bool cmMakefile::AppendCustomCommandToOutput(
   // Lookup an existing command.
   if (cmSourceFile* sf = this->GetSourceFileWithOutput(output)) {
     if (cmCustomCommand* cc = sf->GetCustomCommand()) {
-      cc->AppendCommands(commandLines);
-      cc->AppendDepends(depends);
-      cc->AppendImplicitDepends(implicit_depends);
+      // Validate custom commands.
+      if (this->ValidateCustomCommand(commandLines)) {
+        cc->AppendCommands(commandLines);
+        cc->AppendDepends(depends);
+        cc->AppendImplicitDepends(implicit_depends);
+      }
       return true;
     }
   }
@@ -1247,33 +1257,37 @@ cmTarget* cmMakefile::AddUtilityCommand(
     comment = "";
   }
 
-  // Store the custom command in the target.
-  if (!commandLines.empty() || !depends.empty()) {
-    // Always create the byproduct sources and mark them generated.
-    this->CreateGeneratedSources(byproducts);
-
-    std::string force =
-      cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/", utilityName);
-    std::vector<std::string> forced;
-    forced.push_back(force);
-    std::string no_main_dependency;
-    cmImplicitDependsList no_implicit_depends;
-    bool no_replace = false;
-    this->AddCustomCommandToOutput(
-      forced, byproducts, depends, no_main_dependency, no_implicit_depends,
-      commandLines, comment, workingDirectory, no_replace, escapeOldStyle,
-      uses_terminal, command_expand_lists, /*depfile=*/"", job_pool);
-    cmSourceFile* sf = target->AddSourceCMP0049(force);
-
-    // The output is not actually created so mark it symbolic.
-    if (sf) {
-      sf->SetProperty("SYMBOLIC", "1");
-    } else {
-      cmSystemTools::Error("Could not get source file entry for " + force);
-    }
+  // Validate custom commands.
+  if (!this->ValidateCustomCommand(commandLines) ||
+      (commandLines.empty() && depends.empty())) {
+    return target;
+  }
+
+  // Always create the byproduct sources and mark them generated.
+  this->CreateGeneratedSources(byproducts);
 
-    this->UpdateOutputToSourceMap(byproducts, target);
+  std::string force =
+    cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/", utilityName);
+  std::vector<std::string> forced;
+  forced.push_back(force);
+  std::string no_main_dependency;
+  cmImplicitDependsList no_implicit_depends;
+  bool no_replace = false;
+  this->AddCustomCommandToOutput(
+    forced, byproducts, depends, no_main_dependency, no_implicit_depends,
+    commandLines, comment, workingDirectory, no_replace, escapeOldStyle,
+    uses_terminal, command_expand_lists, /*depfile=*/"", job_pool);
+  cmSourceFile* sf = target->AddSourceCMP0049(force);
+
+  // The output is not actually created so mark it symbolic.
+  if (sf) {
+    sf->SetProperty("SYMBOLIC", "1");
+  } else {
+    cmSystemTools::Error("Could not get source file entry for " + force);
   }
+
+  this->UpdateOutputToSourceMap(byproducts, target);
+
   return target;
 }
 
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 4a1af7d..ed118db 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -172,7 +172,7 @@ public:
   };
 
   /** Add a custom command to the build.  */
-  void AddCustomCommandToTarget(
+  cmTarget* AddCustomCommandToTarget(
     const std::string& target, const std::vector<std::string>& byproducts,
     const std::vector<std::string>& depends,
     const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type,

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f1e846fddece96d76d4d6b53ff1ca8ed197af550
commit f1e846fddece96d76d4d6b53ff1ca8ed197af550
Author:     Daniel Eiband <daniel.eiband at brainlab.com>
AuthorDate: Sat Sep 14 14:16:14 2019 +0200
Commit:     Daniel Eiband <daniel.eiband at brainlab.com>
CommitDate: Tue Sep 17 22:50:25 2019 +0200

    cmMakefile: Extract custom command validation method

diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 564ac56..6462c26 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -821,6 +821,22 @@ void cmMakefile::ConfigureFinalPass()
   }
 }
 
+bool cmMakefile::ValidateCustomCommand(
+  const cmCustomCommandLines& commandLines) const
+{
+  // TODO: More strict?
+  for (cmCustomCommandLine const& cl : commandLines) {
+    if (!cl.empty() && !cl[0].empty() && cl[0][0] == '"') {
+      std::ostringstream e;
+      e << "COMMAND may not contain literal quotes:\n  " << cl[0] << "\n";
+      this->IssueMessage(MessageType::FATAL_ERROR, e.str());
+      return false;
+    }
+  }
+
+  return true;
+}
+
 void cmMakefile::AddCustomCommandToTarget(
   const std::string& target, const std::vector<std::string>& byproducts,
   const std::vector<std::string>& depends,
@@ -959,14 +975,9 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput(
     return nullptr;
   }
 
-  // Validate custom commands.  TODO: More strict?
-  for (cmCustomCommandLine const& cl : commandLines) {
-    if (!cl.empty() && !cl[0].empty() && cl[0][0] == '"') {
-      std::ostringstream e;
-      e << "COMMAND may not contain literal quotes:\n  " << cl[0] << "\n";
-      this->IssueMessage(MessageType::FATAL_ERROR, e.str());
-      return nullptr;
-    }
+  // Validate custom commands.
+  if (!this->ValidateCustomCommand(commandLines)) {
+    return nullptr;
   }
 
   // Always create the output sources and mark them generated.
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 28f5452..4a1af7d 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -1067,6 +1067,8 @@ private:
                                          bool atOnly, const char* filename,
                                          long line, bool replaceAt) const;
 
+  bool ValidateCustomCommand(const cmCustomCommandLines& commandLines) const;
+
   void CreateGeneratedSources(const std::vector<std::string>& outputs);
 
   /**

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4926ab24542d2c9e644feee88efd4a96f8bcab97
commit 4926ab24542d2c9e644feee88efd4a96f8bcab97
Author:     Daniel Eiband <daniel.eiband at brainlab.com>
AuthorDate: Fri Sep 6 19:17:37 2019 +0200
Commit:     Daniel Eiband <daniel.eiband at brainlab.com>
CommitDate: Tue Sep 17 22:50:25 2019 +0200

    cmMakefile: Create all generated byproducts as known sources

diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index f35b999..564ac56 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -970,8 +970,8 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput(
   }
 
   // Always create the output sources and mark them generated.
-  this->CreateGeneratedSources(outputs, cmSourceFileLocationKind::Known);
-  this->CreateGeneratedSources(byproducts, cmSourceFileLocationKind::Known);
+  this->CreateGeneratedSources(outputs);
+  this->CreateGeneratedSources(byproducts);
 
   // Choose a source file on which to store the custom command.
   cmSourceFile* file = nullptr;
@@ -1239,7 +1239,7 @@ 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);
+    this->CreateGeneratedSources(byproducts);
 
     std::string force =
       cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/", utilityName);
@@ -3444,10 +3444,11 @@ cmSourceFile* cmMakefile::GetOrCreateSource(const std::string& sourceName,
 }
 
 void cmMakefile::CreateGeneratedSources(
-  const std::vector<std::string>& outputs, cmSourceFileLocationKind kind)
+  const std::vector<std::string>& outputs)
 {
   for (std::string const& output : outputs) {
-    if (cmSourceFile* out = this->GetOrCreateSource(output, true, kind)) {
+    if (cmSourceFile* out = this->GetOrCreateSource(
+          output, true, cmSourceFileLocationKind::Known)) {
       out->SetProperty("GENERATED", "1");
     }
   }
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 1944879..28f5452 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -1067,9 +1067,7 @@ private:
                                          bool atOnly, const char* filename,
                                          long line, bool replaceAt) const;
 
-  void CreateGeneratedSources(
-    const std::vector<std::string>& outputs,
-    cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous);
+  void CreateGeneratedSources(const std::vector<std::string>& outputs);
 
   /**
    * See LinearGetSourceFileWithOutput for background information

-----------------------------------------------------------------------

Summary of changes:
 Source/CMakeLists.txt                              |   2 -
 Source/cmComputeLinkInformation.cxx                |  35 +++
 Source/cmComputeLinkInformation.h                  |   6 +
 Source/cmCustomCommandGenerator.cxx                |  41 ++-
 Source/cmCustomCommandGenerator.h                  |   1 +
 Source/cmExportBuildFileGenerator.cxx              |   4 +-
 Source/cmExportCommand.cxx                         |  13 +-
 Source/cmExportInstallAndroidMKGenerator.cxx       |   4 +-
 Source/cmExportInstallFileGenerator.cxx            |  22 +-
 Source/cmExportSet.cxx                             |  27 +-
 Source/cmExportSet.h                               |  28 +-
 Source/cmExportSetMap.cxx                          |  31 ---
 Source/cmExportSetMap.h                            |  37 ---
 Source/cmFileAPICodemodel.cxx                      |  20 +-
 Source/cmGeneratorTarget.cxx                       |   2 +-
 Source/cmGlobalGenerator.h                         |   2 +-
 Source/cmInstallCommand.cxx                        |  21 +-
 Source/cmInstallExportGenerator.cxx                |   2 +-
 Source/cmLinkLineComputer.cxx                      |  99 +++++--
 Source/cmLinkLineComputer.h                        |  18 +-
 Source/cmLinkLineDeviceComputer.cxx                |  41 ++-
 Source/cmLinkLineDeviceComputer.h                  |   8 +-
 Source/cmLocalGenerator.cxx                        |  36 ++-
 Source/cmLocalGenerator.h                          |  16 +-
 Source/cmLocalUnixMakefileGenerator3.cxx           |   8 +-
 Source/cmMakefile.cxx                              | 306 ++++++++++++++-------
 Source/cmMakefile.h                                |  54 +++-
 Source/cmMakefileTargetGenerator.cxx               |  31 +--
 Source/cmNinjaTargetGenerator.cxx                  |  13 +-
 Source/cmTarget.cxx                                |   8 +-
 Source/cmTarget.h                                  |   2 +-
 Tests/RunCMake/FileAPI/codemodel-v2-check.py       |  40 ++-
 Tests/RunCMake/FileAPI/cxx/CMakeLists.txt          |   1 +
 .../AppendLiteralQuotes-result.txt}                |   0
 .../AppendLiteralQuotes-stderr.txt                 |   7 +
 .../add_custom_command/AppendLiteralQuotes.cmake   |   2 +
 .../LiteralQuotes-result.txt}                      |   0
 .../add_custom_command/LiteralQuotes-stderr.txt    |   7 +
 .../add_custom_command/LiteralQuotes.cmake         |   1 +
 .../RunCMake/add_custom_command/RunCMakeTest.cmake |   3 +
 .../TargetLiteralQuotes-result.txt}                |   0
 .../TargetLiteralQuotes-stderr.txt                 |   7 +
 .../add_custom_command/TargetLiteralQuotes.cmake   |   2 +
 .../LiteralQuotes-result.txt}                      |   0
 .../add_custom_target/LiteralQuotes-stderr.txt     |   7 +
 .../RunCMake/add_custom_target/LiteralQuotes.cmake |   1 +
 .../RunCMake/add_custom_target/RunCMakeTest.cmake  |   1 +
 bootstrap                                          |   1 -
 48 files changed, 684 insertions(+), 334 deletions(-)
 delete mode 100644 Source/cmExportSetMap.cxx
 delete mode 100644 Source/cmExportSetMap.h
 copy Tests/RunCMake/{while/MissingArgument-result.txt => add_custom_command/AppendLiteralQuotes-result.txt} (100%)
 create mode 100644 Tests/RunCMake/add_custom_command/AppendLiteralQuotes-stderr.txt
 create mode 100644 Tests/RunCMake/add_custom_command/AppendLiteralQuotes.cmake
 copy Tests/RunCMake/{while/MissingArgument-result.txt => add_custom_command/LiteralQuotes-result.txt} (100%)
 create mode 100644 Tests/RunCMake/add_custom_command/LiteralQuotes-stderr.txt
 create mode 100644 Tests/RunCMake/add_custom_command/LiteralQuotes.cmake
 copy Tests/RunCMake/{while/MissingArgument-result.txt => add_custom_command/TargetLiteralQuotes-result.txt} (100%)
 create mode 100644 Tests/RunCMake/add_custom_command/TargetLiteralQuotes-stderr.txt
 create mode 100644 Tests/RunCMake/add_custom_command/TargetLiteralQuotes.cmake
 copy Tests/RunCMake/{while/MissingArgument-result.txt => add_custom_target/LiteralQuotes-result.txt} (100%)
 create mode 100644 Tests/RunCMake/add_custom_target/LiteralQuotes-stderr.txt
 create mode 100644 Tests/RunCMake/add_custom_target/LiteralQuotes.cmake


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list