Selaa lähdekoodia

Add generator APIs to get build settings with backtraces

In cmGeneratorTarget and cmLocalGenerator we offer several APIs to get
build settings like include directories, compile definitions, source
files, etc.  Add corresponding APIs that include backtrace information.
Brad King 7 vuotta sitten
vanhempi
sitoutus
753ab3c978
4 muutettua tiedostoa jossa 329 lisäystä ja 112 poistoa
  1. 197 70
      Source/cmGeneratorTarget.cxx
  2. 25 6
      Source/cmGeneratorTarget.h
  3. 91 34
      Source/cmLocalGenerator.cxx
  4. 16 2
      Source/cmLocalGenerator.h

+ 197 - 70
Source/cmGeneratorTarget.cxx

@@ -439,7 +439,7 @@ static void handleSystemIncludesDep(
     KindedSources const& kinded = this->GetKindedSources(config);             \
     KindedSources const& kinded = this->GetKindedSources(config);             \
     for (SourceAndKind const& s : kinded.Sources) {                           \
     for (SourceAndKind const& s : kinded.Sources) {                           \
       if (s.Kind == KIND) {                                                   \
       if (s.Kind == KIND) {                                                   \
-        data.push_back(s.Source);                                             \
+        data.push_back(s.Source.Value);                                       \
       }                                                                       \
       }                                                                       \
     }                                                                         \
     }                                                                         \
   }
   }
@@ -865,7 +865,8 @@ static void AddObjectEntries(
 static bool processSources(
 static bool processSources(
   cmGeneratorTarget const* tgt,
   cmGeneratorTarget const* tgt,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<std::string>& srcs, std::unordered_set<std::string>& uniqueSrcs,
+  std::vector<BT<std::string>>& srcs,
+  std::unordered_set<std::string>& uniqueSrcs,
   cmGeneratorExpressionDAGChecker* dagChecker, std::string const& config,
   cmGeneratorExpressionDAGChecker* dagChecker, std::string const& config,
   bool debugSources)
   bool debugSources)
 {
 {
@@ -916,7 +917,7 @@ static bool processSources(
     std::string usedSources;
     std::string usedSources;
     for (std::string const& src : entrySources) {
     for (std::string const& src : entrySources) {
       if (uniqueSrcs.insert(src).second) {
       if (uniqueSrcs.insert(src).second) {
-        srcs.push_back(src);
+        srcs.emplace_back(src, entry->ge->GetBacktrace());
         if (debugSources) {
         if (debugSources) {
           usedSources += " * " + src + "\n";
           usedSources += " * " + src + "\n";
         }
         }
@@ -933,9 +934,10 @@ static bool processSources(
   return contextDependent;
   return contextDependent;
 }
 }
 
 
-void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
-                                       const std::string& config) const
+std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
+  std::string const& config) const
 {
 {
+  std::vector<BT<std::string>> files;
   assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
   assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
 
 
   if (!this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
   if (!this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
@@ -957,7 +959,7 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
         files.push_back(item);
         files.push_back(item);
       }
       }
     }
     }
-    return;
+    return files;
   }
   }
 
 
   std::vector<std::string> debugProperties;
   std::vector<std::string> debugProperties;
@@ -1009,11 +1011,23 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
 
 
   cmDeleteAll(linkInterfaceSourcesEntries);
   cmDeleteAll(linkInterfaceSourcesEntries);
   cmDeleteAll(linkObjectsEntries);
   cmDeleteAll(linkObjectsEntries);
+  return files;
 }
 }
 
 
 void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
 void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
                                        const std::string& config) const
                                        const std::string& config) const
 {
 {
+  std::vector<BT<cmSourceFile*>> tmp = this->GetSourceFiles(config);
+  files.reserve(tmp.size());
+  for (BT<cmSourceFile*>& v : tmp) {
+    files.push_back(v.Value);
+  }
+}
+
+std::vector<BT<cmSourceFile*>> cmGeneratorTarget::GetSourceFiles(
+  std::string const& config) const
+{
+  std::vector<BT<cmSourceFile*>> files;
   if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) {
   if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) {
     // Since we are still configuring not all sources may exist yet,
     // Since we are still configuring not all sources may exist yet,
     // so we need to avoid full source classification because that
     // so we need to avoid full source classification because that
@@ -1021,16 +1035,15 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
     // Since this is only for compatibility with old policies that
     // Since this is only for compatibility with old policies that
     // projects should not depend on anymore, just compute the files
     // projects should not depend on anymore, just compute the files
     // without memoizing them.
     // without memoizing them.
-    std::vector<std::string> srcs;
-    this->GetSourceFiles(srcs, config);
+    std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);
     std::set<cmSourceFile*> emitted;
     std::set<cmSourceFile*> emitted;
-    for (std::string const& s : srcs) {
-      cmSourceFile* sf = this->Makefile->GetOrCreateSource(s);
+    for (BT<std::string> const& s : srcs) {
+      cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
       if (emitted.insert(sf).second) {
       if (emitted.insert(sf).second) {
-        files.push_back(sf);
+        files.emplace_back(sf, s.Backtrace);
       }
       }
     }
     }
-    return;
+    return files;
   }
   }
 
 
   KindedSources const& kinded = this->GetKindedSources(config);
   KindedSources const& kinded = this->GetKindedSources(config);
@@ -1038,18 +1051,33 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
   for (SourceAndKind const& si : kinded.Sources) {
   for (SourceAndKind const& si : kinded.Sources) {
     files.push_back(si.Source);
     files.push_back(si.Source);
   }
   }
+  return files;
 }
 }
 
 
 void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
 void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
   std::vector<cmSourceFile*>& files, const std::string& config) const
   std::vector<cmSourceFile*>& files, const std::string& config) const
 {
 {
+  std::vector<BT<cmSourceFile*>> tmp =
+    this->GetSourceFilesWithoutObjectLibraries(config);
+  files.reserve(tmp.size());
+  for (BT<cmSourceFile*>& v : tmp) {
+    files.push_back(v.Value);
+  }
+}
+
+std::vector<BT<cmSourceFile*>>
+cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
+  std::string const& config) const
+{
+  std::vector<BT<cmSourceFile*>> files;
   KindedSources const& kinded = this->GetKindedSources(config);
   KindedSources const& kinded = this->GetKindedSources(config);
   files.reserve(kinded.Sources.size());
   files.reserve(kinded.Sources.size());
   for (SourceAndKind const& si : kinded.Sources) {
   for (SourceAndKind const& si : kinded.Sources) {
-    if (si.Source->GetObjectLibrary().empty()) {
+    if (si.Source.Value->GetObjectLibrary().empty()) {
       files.push_back(si.Source);
       files.push_back(si.Source);
     }
     }
   }
   }
+  return files;
 }
 }
 
 
 cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
 cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
@@ -1089,16 +1117,15 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
                                              std::string const& config) const
                                              std::string const& config) const
 {
 {
   // Get the source file paths by string.
   // Get the source file paths by string.
-  std::vector<std::string> srcs;
-  this->GetSourceFiles(srcs, config);
+  std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);
 
 
   cmsys::RegularExpression header_regex(CM_HEADER_REGEX);
   cmsys::RegularExpression header_regex(CM_HEADER_REGEX);
   std::vector<cmSourceFile*> badObjLib;
   std::vector<cmSourceFile*> badObjLib;
 
 
   std::set<cmSourceFile*> emitted;
   std::set<cmSourceFile*> emitted;
-  for (std::string const& s : srcs) {
+  for (BT<std::string> const& s : srcs) {
     // Create each source at most once.
     // Create each source at most once.
-    cmSourceFile* sf = this->Makefile->GetOrCreateSource(s);
+    cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
     if (!emitted.insert(sf).second) {
     if (!emitted.insert(sf).second) {
       continue;
       continue;
     }
     }
@@ -1161,7 +1188,7 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
     }
     }
 
 
     // Save this classified source file in the result vector.
     // Save this classified source file in the result vector.
-    files.Sources.push_back({ sf, kind });
+    files.Sources.push_back({ BT<cmSourceFile*>(sf, s.Backtrace), kind });
   }
   }
 
 
   if (!badObjLib.empty()) {
   if (!badObjLib.empty()) {
@@ -1197,14 +1224,14 @@ void cmGeneratorTarget::ComputeAllConfigSources() const
     KindedSources const& sources = this->GetKindedSources(configs[ci]);
     KindedSources const& sources = this->GetKindedSources(configs[ci]);
     for (SourceAndKind const& src : sources.Sources) {
     for (SourceAndKind const& src : sources.Sources) {
       std::map<cmSourceFile const*, size_t>::iterator mi =
       std::map<cmSourceFile const*, size_t>::iterator mi =
-        index.find(src.Source);
+        index.find(src.Source.Value);
       if (mi == index.end()) {
       if (mi == index.end()) {
         AllConfigSource acs;
         AllConfigSource acs;
-        acs.Source = src.Source;
+        acs.Source = src.Source.Value;
         acs.Kind = src.Kind;
         acs.Kind = src.Kind;
         this->AllConfigSources.push_back(std::move(acs));
         this->AllConfigSources.push_back(std::move(acs));
         std::map<cmSourceFile const*, size_t>::value_type entry(
         std::map<cmSourceFile const*, size_t>::value_type entry(
-          src.Source, this->AllConfigSources.size() - 1);
+          src.Source.Value, this->AllConfigSources.size() - 1);
         mi = index.insert(entry).first;
         mi = index.insert(entry).first;
       }
       }
       this->AllConfigSources[mi->second].Configs.push_back(ci);
       this->AllConfigSources[mi->second].Configs.push_back(ci);
@@ -2474,7 +2501,7 @@ std::string cmGeneratorTarget::GetCreateRuleVariable(
 static void processIncludeDirectories(
 static void processIncludeDirectories(
   cmGeneratorTarget const* tgt,
   cmGeneratorTarget const* tgt,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<std::string>& includes,
+  std::vector<BT<std::string>>& includes,
   std::unordered_set<std::string>& uniqueIncludes,
   std::unordered_set<std::string>& uniqueIncludes,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   bool debugIncludes, const std::string& language)
   bool debugIncludes, const std::string& language)
@@ -2566,7 +2593,7 @@ static void processIncludeDirectories(
       std::string inc = entryInclude;
       std::string inc = entryInclude;
 
 
       if (uniqueIncludes.insert(inc).second) {
       if (uniqueIncludes.insert(inc).second) {
-        includes.push_back(inc);
+        includes.emplace_back(inc, entry->ge->GetBacktrace());
         if (debugIncludes) {
         if (debugIncludes) {
           usedIncludes += " * " + inc + "\n";
           usedIncludes += " * " + inc + "\n";
         }
         }
@@ -2582,10 +2609,10 @@ static void processIncludeDirectories(
   }
   }
 }
 }
 
 
-std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
+std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories(
   const std::string& config, const std::string& lang) const
   const std::string& config, const std::string& lang) const
 {
 {
-  std::vector<std::string> includes;
+  std::vector<BT<std::string>> includes;
   std::unordered_set<std::string> uniqueIncludes;
   std::unordered_set<std::string> uniqueIncludes;
 
 
   cmGeneratorExpressionDAGChecker dagChecker(this, "INCLUDE_DIRECTORIES",
   cmGeneratorExpressionDAGChecker dagChecker(this, "INCLUDE_DIRECTORIES",
@@ -2655,7 +2682,7 @@ enum class OptionsParse
 static void processOptionsInternal(
 static void processOptionsInternal(
   cmGeneratorTarget const* tgt,
   cmGeneratorTarget const* tgt,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<std::string>& options,
+  std::vector<BT<std::string>>& options,
   std::unordered_set<std::string>& uniqueOptions,
   std::unordered_set<std::string>& uniqueOptions,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   bool debugOptions, const char* logName, std::string const& language,
   bool debugOptions, const char* logName, std::string const& language,
@@ -2672,9 +2699,13 @@ static void processOptionsInternal(
       if (uniqueOptions.insert(opt).second) {
       if (uniqueOptions.insert(opt).second) {
         if (parse == OptionsParse::Shell &&
         if (parse == OptionsParse::Shell &&
             cmHasLiteralPrefix(opt, "SHELL:")) {
             cmHasLiteralPrefix(opt, "SHELL:")) {
-          cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, options);
+          std::vector<std::string> tmp;
+          cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, tmp);
+          for (std::string& o : tmp) {
+            options.emplace_back(std::move(o), entry->ge->GetBacktrace());
+          }
         } else {
         } else {
-          options.push_back(opt);
+          options.emplace_back(opt, entry->ge->GetBacktrace());
         }
         }
         if (debugOptions) {
         if (debugOptions) {
           usedOptions += " * " + opt + "\n";
           usedOptions += " * " + opt + "\n";
@@ -2694,7 +2725,7 @@ static void processOptionsInternal(
 static void processCompileOptions(
 static void processCompileOptions(
   cmGeneratorTarget const* tgt,
   cmGeneratorTarget const* tgt,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<std::string>& options,
+  std::vector<BT<std::string>>& options,
   std::unordered_set<std::string>& uniqueOptions,
   std::unordered_set<std::string>& uniqueOptions,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   bool debugOptions, std::string const& language)
   bool debugOptions, std::string const& language)
@@ -2708,6 +2739,17 @@ void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result,
                                           const std::string& config,
                                           const std::string& config,
                                           const std::string& language) const
                                           const std::string& language) const
 {
 {
+  std::vector<BT<std::string>> tmp = this->GetCompileOptions(config, language);
+  result.reserve(tmp.size());
+  for (BT<std::string>& v : tmp) {
+    result.emplace_back(std::move(v.Value));
+  }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetCompileOptions(
+  std::string const& config, std::string const& language) const
+{
+  std::vector<BT<std::string>> result;
   std::unordered_set<std::string> uniqueOptions;
   std::unordered_set<std::string> uniqueOptions;
 
 
   cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_OPTIONS", nullptr,
   cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_OPTIONS", nullptr,
@@ -2743,12 +2785,13 @@ void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result,
                         language);
                         language);
 
 
   cmDeleteAll(linkInterfaceCompileOptionsEntries);
   cmDeleteAll(linkInterfaceCompileOptionsEntries);
+  return result;
 }
 }
 
 
 static void processCompileFeatures(
 static void processCompileFeatures(
   cmGeneratorTarget const* tgt,
   cmGeneratorTarget const* tgt,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<std::string>& options,
+  std::vector<BT<std::string>>& options,
   std::unordered_set<std::string>& uniqueOptions,
   std::unordered_set<std::string>& uniqueOptions,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   bool debugOptions)
   bool debugOptions)
@@ -2761,6 +2804,17 @@ static void processCompileFeatures(
 void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
 void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
                                            const std::string& config) const
                                            const std::string& config) const
 {
 {
+  std::vector<BT<std::string>> tmp = this->GetCompileFeatures(config);
+  result.reserve(tmp.size());
+  for (BT<std::string>& v : tmp) {
+    result.emplace_back(std::move(v.Value));
+  }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetCompileFeatures(
+  std::string const& config) const
+{
+  std::vector<BT<std::string>> result;
   std::unordered_set<std::string> uniqueFeatures;
   std::unordered_set<std::string> uniqueFeatures;
 
 
   cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_FEATURES", nullptr,
   cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_FEATURES", nullptr,
@@ -2793,12 +2847,13 @@ void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
                          uniqueFeatures, &dagChecker, config, debugFeatures);
                          uniqueFeatures, &dagChecker, config, debugFeatures);
 
 
   cmDeleteAll(linkInterfaceCompileFeaturesEntries);
   cmDeleteAll(linkInterfaceCompileFeaturesEntries);
+  return result;
 }
 }
 
 
 static void processCompileDefinitions(
 static void processCompileDefinitions(
   cmGeneratorTarget const* tgt,
   cmGeneratorTarget const* tgt,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<std::string>& options,
+  std::vector<BT<std::string>>& options,
   std::unordered_set<std::string>& uniqueOptions,
   std::unordered_set<std::string>& uniqueOptions,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   bool debugOptions, std::string const& language)
   bool debugOptions, std::string const& language)
@@ -2809,9 +2864,21 @@ static void processCompileDefinitions(
 }
 }
 
 
 void cmGeneratorTarget::GetCompileDefinitions(
 void cmGeneratorTarget::GetCompileDefinitions(
-  std::vector<std::string>& list, const std::string& config,
+  std::vector<std::string>& result, const std::string& config,
   const std::string& language) const
   const std::string& language) const
 {
 {
+  std::vector<BT<std::string>> tmp =
+    this->GetCompileDefinitions(config, language);
+  result.reserve(tmp.size());
+  for (BT<std::string>& v : tmp) {
+    result.emplace_back(std::move(v.Value));
+  }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions(
+  std::string const& config, std::string const& language) const
+{
+  std::vector<BT<std::string>> list;
   std::unordered_set<std::string> uniqueOptions;
   std::unordered_set<std::string> uniqueOptions;
 
 
   cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_DEFINITIONS",
   cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_DEFINITIONS",
@@ -2872,13 +2939,14 @@ void cmGeneratorTarget::GetCompileDefinitions(
                             language);
                             language);
 
 
   cmDeleteAll(linkInterfaceCompileDefinitionsEntries);
   cmDeleteAll(linkInterfaceCompileDefinitionsEntries);
+  return list;
 }
 }
 
 
 namespace {
 namespace {
 void processLinkOptions(
 void processLinkOptions(
   cmGeneratorTarget const* tgt,
   cmGeneratorTarget const* tgt,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<std::string>& options,
+  std::vector<BT<std::string>>& options,
   std::unordered_set<std::string>& uniqueOptions,
   std::unordered_set<std::string>& uniqueOptions,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   bool debugOptions, std::string const& language)
   bool debugOptions, std::string const& language)
@@ -2893,6 +2961,17 @@ void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
                                        const std::string& config,
                                        const std::string& config,
                                        const std::string& language) const
                                        const std::string& language) const
 {
 {
+  std::vector<BT<std::string>> tmp = this->GetLinkOptions(config, language);
+  result.reserve(tmp.size());
+  for (BT<std::string>& v : tmp) {
+    result.emplace_back(std::move(v.Value));
+  }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions(
+  std::string const& config, std::string const& language) const
+{
+  std::vector<BT<std::string>> result;
   std::unordered_set<std::string> uniqueOptions;
   std::unordered_set<std::string> uniqueOptions;
 
 
   cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_OPTIONS", nullptr,
   cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_OPTIONS", nullptr,
@@ -2946,21 +3025,24 @@ void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
   const std::string SHELL{ "SHELL:" };
   const std::string SHELL{ "SHELL:" };
   const std::string LINKER_SHELL = LINKER + SHELL;
   const std::string LINKER_SHELL = LINKER + SHELL;
 
 
-  std::vector<std::string>::iterator entry;
+  std::vector<BT<std::string>>::iterator entry;
   while ((entry = std::find_if(result.begin(), result.end(),
   while ((entry = std::find_if(result.begin(), result.end(),
-                               [&LINKER](const std::string& item) -> bool {
-                                 return item.compare(0, LINKER.length(),
-                                                     LINKER) == 0;
+                               [&LINKER](BT<std::string> const& item) -> bool {
+                                 return item.Value.compare(0, LINKER.length(),
+                                                           LINKER) == 0;
                                })) != result.end()) {
                                })) != result.end()) {
+    std::string value = std::move(entry->Value);
+    cmListFileBacktrace bt = std::move(entry->Backtrace);
+    entry = result.erase(entry);
+
     std::vector<std::string> linkerOptions;
     std::vector<std::string> linkerOptions;
-    if (entry->compare(0, LINKER_SHELL.length(), LINKER_SHELL) == 0) {
+    if (value.compare(0, LINKER_SHELL.length(), LINKER_SHELL) == 0) {
       cmSystemTools::ParseUnixCommandLine(
       cmSystemTools::ParseUnixCommandLine(
-        entry->c_str() + LINKER_SHELL.length(), linkerOptions);
+        value.c_str() + LINKER_SHELL.length(), linkerOptions);
     } else {
     } else {
       linkerOptions =
       linkerOptions =
-        cmSystemTools::tokenize(entry->substr(LINKER.length()), ",");
+        cmSystemTools::tokenize(value.substr(LINKER.length()), ",");
     }
     }
-    entry = result.erase(entry);
 
 
     if (linkerOptions.empty() ||
     if (linkerOptions.empty() ||
         (linkerOptions.size() == 1 && linkerOptions.front().empty())) {
         (linkerOptions.size() == 1 && linkerOptions.front().empty())) {
@@ -2976,56 +3058,64 @@ void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
         cmake::FATAL_ERROR,
         cmake::FATAL_ERROR,
         "'SHELL:' prefix is not supported as part of 'LINKER:' arguments.",
         "'SHELL:' prefix is not supported as part of 'LINKER:' arguments.",
         this->GetBacktrace());
         this->GetBacktrace());
-      return;
+      return result;
     }
     }
 
 
+    std::vector<BT<std::string>> options;
     if (wrapperFlag.empty()) {
     if (wrapperFlag.empty()) {
       // nothing specified, insert elements as is
       // nothing specified, insert elements as is
-      result.insert(entry, linkerOptions.begin(), linkerOptions.end());
+      options.reserve(linkerOptions.size());
+      for (std::string& o : linkerOptions) {
+        options.emplace_back(std::move(o), bt);
+      }
     } else {
     } else {
-      std::vector<std::string> options;
-
       if (!wrapperSep.empty()) {
       if (!wrapperSep.empty()) {
         if (concatFlagAndArgs) {
         if (concatFlagAndArgs) {
           // insert flag elements except last one
           // insert flag elements except last one
-          options.insert(options.end(), wrapperFlag.begin(),
-                         wrapperFlag.end() - 1);
+          for (auto i = wrapperFlag.begin(); i != wrapperFlag.end() - 1; ++i) {
+            options.emplace_back(*i, bt);
+          }
           // concatenate last flag element and all LINKER list values
           // concatenate last flag element and all LINKER list values
           // in one option
           // in one option
-          options.push_back(wrapperFlag.back() +
-                            cmJoin(linkerOptions, wrapperSep));
+          options.emplace_back(
+            wrapperFlag.back() + cmJoin(linkerOptions, wrapperSep), bt);
         } else {
         } else {
-          options.insert(options.end(), wrapperFlag.begin(),
-                         wrapperFlag.end());
+          for (std::string const& i : wrapperFlag) {
+            options.emplace_back(i, bt);
+          }
           // concatenate all LINKER list values in one option
           // concatenate all LINKER list values in one option
-          options.push_back(cmJoin(linkerOptions, wrapperSep));
+          options.emplace_back(cmJoin(linkerOptions, wrapperSep), bt);
         }
         }
       } else {
       } else {
         // prefix each element of LINKER list with wrapper
         // prefix each element of LINKER list with wrapper
         if (concatFlagAndArgs) {
         if (concatFlagAndArgs) {
-          std::transform(
-            linkerOptions.begin(), linkerOptions.end(), linkerOptions.begin(),
-            [&wrapperFlag](const std::string& value) -> std::string {
-              return wrapperFlag.back() + value;
-            });
+          std::transform(linkerOptions.begin(), linkerOptions.end(),
+                         linkerOptions.begin(),
+                         [&wrapperFlag](std::string const& o) -> std::string {
+                           return wrapperFlag.back() + o;
+                         });
         }
         }
-        for (const auto& value : linkerOptions) {
-          options.insert(options.end(), wrapperFlag.begin(),
-                         concatFlagAndArgs ? wrapperFlag.end() - 1
-                                           : wrapperFlag.end());
-          options.push_back(value);
+        for (std::string& o : linkerOptions) {
+          for (auto i = wrapperFlag.begin(),
+                    e = concatFlagAndArgs ? wrapperFlag.end() - 1
+                                          : wrapperFlag.end();
+               i != e; ++i) {
+            options.emplace_back(*i, bt);
+          }
+          options.emplace_back(std::move(o), bt);
         }
         }
       }
       }
-      result.insert(entry, options.begin(), options.end());
     }
     }
+    result.insert(entry, options.begin(), options.end());
   }
   }
+  return result;
 }
 }
 
 
 namespace {
 namespace {
 void processStaticLibraryLinkOptions(
 void processStaticLibraryLinkOptions(
   cmGeneratorTarget const* tgt,
   cmGeneratorTarget const* tgt,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<std::string>& options,
+  std::vector<BT<std::string>>& options,
   std::unordered_set<std::string>& uniqueOptions,
   std::unordered_set<std::string>& uniqueOptions,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   std::string const& language)
   std::string const& language)
@@ -3040,6 +3130,18 @@ void cmGeneratorTarget::GetStaticLibraryLinkOptions(
   std::vector<std::string>& result, const std::string& config,
   std::vector<std::string>& result, const std::string& config,
   const std::string& language) const
   const std::string& language) const
 {
 {
+  std::vector<BT<std::string>> tmp =
+    this->GetStaticLibraryLinkOptions(config, language);
+  result.reserve(tmp.size());
+  for (BT<std::string>& v : tmp) {
+    result.emplace_back(std::move(v.Value));
+  }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions(
+  std::string const& config, std::string const& language) const
+{
+  std::vector<BT<std::string>> result;
   std::vector<cmGeneratorTarget::TargetPropertyEntry*> entries;
   std::vector<cmGeneratorTarget::TargetPropertyEntry*> entries;
   std::unordered_set<std::string> uniqueOptions;
   std::unordered_set<std::string> uniqueOptions;
 
 
@@ -3060,13 +3162,14 @@ void cmGeneratorTarget::GetStaticLibraryLinkOptions(
                                   &dagChecker, config, language);
                                   &dagChecker, config, language);
 
 
   cmDeleteAll(entries);
   cmDeleteAll(entries);
+  return result;
 }
 }
 
 
 namespace {
 namespace {
 void processLinkDirectories(
 void processLinkDirectories(
   cmGeneratorTarget const* tgt,
   cmGeneratorTarget const* tgt,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<std::string>& directories,
+  std::vector<BT<std::string>>& directories,
   std::unordered_set<std::string>& uniqueDirectories,
   std::unordered_set<std::string>& uniqueDirectories,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   bool debugDirectories, std::string const& language)
   bool debugDirectories, std::string const& language)
@@ -3145,6 +3248,18 @@ void cmGeneratorTarget::GetLinkDirectories(std::vector<std::string>& result,
                                            const std::string& config,
                                            const std::string& config,
                                            const std::string& language) const
                                            const std::string& language) const
 {
 {
+  std::vector<BT<std::string>> tmp =
+    this->GetLinkDirectories(config, language);
+  result.reserve(tmp.size());
+  for (BT<std::string>& v : tmp) {
+    result.emplace_back(std::move(v.Value));
+  }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories(
+  std::string const& config, std::string const& language) const
+{
+  std::vector<BT<std::string>> result;
   std::unordered_set<std::string> uniqueDirectories;
   std::unordered_set<std::string> uniqueDirectories;
 
 
   cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DIRECTORIES", nullptr,
   cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DIRECTORIES", nullptr,
@@ -3180,13 +3295,14 @@ void cmGeneratorTarget::GetLinkDirectories(std::vector<std::string>& result,
                          debugDirectories, language);
                          debugDirectories, language);
 
 
   cmDeleteAll(linkInterfaceLinkDirectoriesEntries);
   cmDeleteAll(linkInterfaceLinkDirectoriesEntries);
+  return result;
 }
 }
 
 
 namespace {
 namespace {
 void processLinkDepends(
 void processLinkDepends(
   cmGeneratorTarget const* tgt,
   cmGeneratorTarget const* tgt,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
   const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
-  std::vector<std::string>& options,
+  std::vector<BT<std::string>>& options,
   std::unordered_set<std::string>& uniqueOptions,
   std::unordered_set<std::string>& uniqueOptions,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
   std::string const& language)
   std::string const& language)
@@ -3201,6 +3317,17 @@ void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result,
                                        const std::string& config,
                                        const std::string& config,
                                        const std::string& language) const
                                        const std::string& language) const
 {
 {
+  std::vector<BT<std::string>> tmp = this->GetLinkDepends(config, language);
+  result.reserve(tmp.size());
+  for (BT<std::string>& v : tmp) {
+    result.emplace_back(std::move(v.Value));
+  }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends(
+  std::string const& config, std::string const& language) const
+{
+  std::vector<BT<std::string>> result;
   std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkDependsEntries;
   std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkDependsEntries;
   std::unordered_set<std::string> uniqueOptions;
   std::unordered_set<std::string> uniqueOptions;
   cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr,
   cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr,
@@ -3222,6 +3349,7 @@ void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result,
                      &dagChecker, config, language);
                      &dagChecker, config, language);
 
 
   cmDeleteAll(linkDependsEntries);
   cmDeleteAll(linkDependsEntries);
+  return result;
 }
 }
 
 
 void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
 void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
@@ -3287,10 +3415,9 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
 
 
 bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const
 bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const
 {
 {
-  std::vector<std::string> features;
-  this->GetCompileFeatures(features, config);
-  for (std::string const& f : features) {
-    if (!this->Makefile->AddRequiredTargetFeature(this->Target, f)) {
+  std::vector<BT<std::string>> features = this->GetCompileFeatures(config);
+  for (BT<std::string> const& f : features) {
+    if (!this->Makefile->AddRequiredTargetFeature(this->Target, f.Value)) {
       return false;
       return false;
     }
     }
   }
   }

+ 25 - 6
Source/cmGeneratorTarget.h

@@ -75,8 +75,8 @@ public:
   bool GetPropertyAsBool(const std::string& prop) const;
   bool GetPropertyAsBool(const std::string& prop) const;
   void GetSourceFiles(std::vector<cmSourceFile*>& files,
   void GetSourceFiles(std::vector<cmSourceFile*>& files,
                       const std::string& config) const;
                       const std::string& config) const;
-  void GetSourceFilesWithoutObjectLibraries(std::vector<cmSourceFile*>& files,
-                                            const std::string& config) const;
+  std::vector<BT<cmSourceFile*>> GetSourceFiles(
+    std::string const& config) const;
 
 
   /** Source file kinds (classifications).
   /** Source file kinds (classifications).
       Generators use this to decide how to treat a source file.  */
       Generators use this to decide how to treat a source file.  */
@@ -99,7 +99,7 @@ public:
   /** A source file paired with a kind (classification).  */
   /** A source file paired with a kind (classification).  */
   struct SourceAndKind
   struct SourceAndKind
   {
   {
-    cmSourceFile* Source;
+    BT<cmSourceFile*> Source;
     SourceKind Kind;
     SourceKind Kind;
   };
   };
 
 
@@ -412,34 +412,49 @@ public:
                                     std::string const& config) const;
                                     std::string const& config) const;
 
 
   /** Get the include directories for this target.  */
   /** Get the include directories for this target.  */
-  std::vector<std::string> GetIncludeDirectories(
+  std::vector<BT<std::string>> GetIncludeDirectories(
     const std::string& config, const std::string& lang) const;
     const std::string& config, const std::string& lang) const;
 
 
   void GetCompileOptions(std::vector<std::string>& result,
   void GetCompileOptions(std::vector<std::string>& result,
                          const std::string& config,
                          const std::string& config,
                          const std::string& language) const;
                          const std::string& language) const;
+  std::vector<BT<std::string>> GetCompileOptions(
+    std::string const& config, std::string const& language) const;
 
 
   void GetCompileFeatures(std::vector<std::string>& features,
   void GetCompileFeatures(std::vector<std::string>& features,
                           const std::string& config) const;
                           const std::string& config) const;
+  std::vector<BT<std::string>> GetCompileFeatures(
+    std::string const& config) const;
 
 
   void GetCompileDefinitions(std::vector<std::string>& result,
   void GetCompileDefinitions(std::vector<std::string>& result,
                              const std::string& config,
                              const std::string& config,
                              const std::string& language) const;
                              const std::string& language) const;
+  std::vector<BT<std::string>> GetCompileDefinitions(
+    std::string const& config, std::string const& language) const;
 
 
   void GetLinkOptions(std::vector<std::string>& result,
   void GetLinkOptions(std::vector<std::string>& result,
                       const std::string& config,
                       const std::string& config,
                       const std::string& language) const;
                       const std::string& language) const;
+  std::vector<BT<std::string>> GetLinkOptions(
+    std::string const& config, std::string const& language) const;
+
   void GetStaticLibraryLinkOptions(std::vector<std::string>& result,
   void GetStaticLibraryLinkOptions(std::vector<std::string>& result,
                                    const std::string& config,
                                    const std::string& config,
                                    const std::string& language) const;
                                    const std::string& language) const;
+  std::vector<BT<std::string>> GetStaticLibraryLinkOptions(
+    std::string const& config, std::string const& language) const;
 
 
   void GetLinkDirectories(std::vector<std::string>& result,
   void GetLinkDirectories(std::vector<std::string>& result,
                           const std::string& config,
                           const std::string& config,
                           const std::string& language) const;
                           const std::string& language) const;
+  std::vector<BT<std::string>> GetLinkDirectories(
+    std::string const& config, std::string const& language) const;
 
 
   void GetLinkDepends(std::vector<std::string>& result,
   void GetLinkDepends(std::vector<std::string>& result,
                       const std::string& config,
                       const std::string& config,
                       const std::string& language) const;
                       const std::string& language) const;
+  std::vector<BT<std::string>> GetLinkDepends(
+    std::string const& config, std::string const& language) const;
 
 
   bool IsSystemIncludeDirectory(const std::string& dir,
   bool IsSystemIncludeDirectory(const std::string& dir,
                                 const std::string& config,
                                 const std::string& config,
@@ -841,8 +856,12 @@ private:
                        cmListFileBacktrace const& bt,
                        cmListFileBacktrace const& bt,
                        std::vector<cmLinkItem>& items) const;
                        std::vector<cmLinkItem>& items) const;
 
 
-  void GetSourceFiles(std::vector<std::string>& files,
-                      const std::string& config) const;
+  std::vector<BT<std::string>> GetSourceFilePaths(
+    std::string const& config) const;
+  std::vector<BT<cmSourceFile*>> GetSourceFilesWithoutObjectLibraries(
+    std::string const& config) const;
+  void GetSourceFilesWithoutObjectLibraries(std::vector<cmSourceFile*>& files,
+                                            const std::string& config) const;
 
 
   struct HeadToLinkImplementationMap
   struct HeadToLinkImplementationMap
     : public std::map<cmGeneratorTarget const*, cmOptionalLinkImplementation>
     : public std::map<cmGeneratorTarget const*, cmOptionalLinkImplementation>

+ 91 - 34
Source/cmLocalGenerator.cxx

@@ -219,6 +219,24 @@ static void MoveSystemIncludesToEnd(std::vector<std::string>& includeDirs,
     });
     });
 }
 }
 
 
+static void MoveSystemIncludesToEnd(std::vector<BT<std::string>>& includeDirs,
+                                    const std::string& config,
+                                    const std::string& lang,
+                                    const cmGeneratorTarget* target)
+{
+  if (!target) {
+    return;
+  }
+
+  std::stable_sort(includeDirs.begin(), includeDirs.end(),
+                   [target, &config, &lang](BT<std::string> const& a,
+                                            BT<std::string> const& b) {
+                     return !target->IsSystemIncludeDirectory(a.Value, config,
+                                                              lang) &&
+                       target->IsSystemIncludeDirectory(b.Value, config, lang);
+                   });
+}
+
 void cmLocalGenerator::TraceDependencies()
 void cmLocalGenerator::TraceDependencies()
 {
 {
   std::vector<std::string> configs;
   std::vector<std::string> configs;
@@ -869,6 +887,21 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
                                              bool stripImplicitDirs,
                                              bool stripImplicitDirs,
                                              bool appendAllImplicitDirs) const
                                              bool appendAllImplicitDirs) const
 {
 {
+  std::vector<BT<std::string>> tmp = this->GetIncludeDirectories(
+    target, lang, config, stripImplicitDirs, appendAllImplicitDirs);
+  dirs.reserve(tmp.size());
+  for (BT<std::string>& v : tmp) {
+    dirs.emplace_back(std::move(v.Value));
+  }
+}
+
+std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectories(
+  cmGeneratorTarget const* target, std::string const& lang,
+  std::string const& config, bool stripImplicitDirs,
+  bool appendAllImplicitDirs) const
+{
+  std::vector<BT<std::string>> result;
+
   // Do not repeat an include path.
   // Do not repeat an include path.
   std::set<std::string> emitted;
   std::set<std::string> emitted;
 
 
@@ -885,7 +918,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
       std::string binDir =
       std::string binDir =
         this->StateSnapshot.GetDirectory().GetCurrentBinary();
         this->StateSnapshot.GetDirectory().GetCurrentBinary();
       if (emitted.insert(binDir).second) {
       if (emitted.insert(binDir).second) {
-        dirs.push_back(std::move(binDir));
+        result.emplace_back(std::move(binDir));
       }
       }
     }
     }
     // Current source directory
     // Current source directory
@@ -893,13 +926,13 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
       std::string srcDir =
       std::string srcDir =
         this->StateSnapshot.GetDirectory().GetCurrentSource();
         this->StateSnapshot.GetDirectory().GetCurrentSource();
       if (emitted.insert(srcDir).second) {
       if (emitted.insert(srcDir).second) {
-        dirs.push_back(std::move(srcDir));
+        result.emplace_back(std::move(srcDir));
       }
       }
     }
     }
   }
   }
 
 
   if (!target) {
   if (!target) {
-    return;
+    return result;
   }
   }
 
 
   // Implicit include directories
   // Implicit include directories
@@ -932,7 +965,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
   }
   }
 
 
   // Get the target-specific include directories.
   // Get the target-specific include directories.
-  std::vector<std::string> userDirs =
+  std::vector<BT<std::string>> userDirs =
     target->GetIncludeDirectories(config, lang);
     target->GetIncludeDirectories(config, lang);
 
 
   // Support putting all the in-project include directories first if
   // Support putting all the in-project include directories first if
@@ -940,44 +973,44 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
   if (this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")) {
   if (this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")) {
     std::string const &topSourceDir = this->GetState()->GetSourceDirectory(),
     std::string const &topSourceDir = this->GetState()->GetSourceDirectory(),
                       &topBinaryDir = this->GetState()->GetBinaryDirectory();
                       &topBinaryDir = this->GetState()->GetBinaryDirectory();
-    for (std::string const& i : userDirs) {
+    for (BT<std::string> const& i : userDirs) {
       // Emit this directory only if it is a subdirectory of the
       // Emit this directory only if it is a subdirectory of the
       // top-level source or binary tree.
       // top-level source or binary tree.
-      if (cmSystemTools::ComparePath(i, topSourceDir) ||
-          cmSystemTools::ComparePath(i, topBinaryDir) ||
-          cmSystemTools::IsSubDirectory(i, topSourceDir) ||
-          cmSystemTools::IsSubDirectory(i, topBinaryDir)) {
-        if (emitted.insert(i).second) {
-          dirs.push_back(i);
+      if (cmSystemTools::ComparePath(i.Value, topSourceDir) ||
+          cmSystemTools::ComparePath(i.Value, topBinaryDir) ||
+          cmSystemTools::IsSubDirectory(i.Value, topSourceDir) ||
+          cmSystemTools::IsSubDirectory(i.Value, topBinaryDir)) {
+        if (emitted.insert(i.Value).second) {
+          result.push_back(i);
         }
         }
       }
       }
     }
     }
   }
   }
 
 
   // Construct the final ordered include directory list.
   // Construct the final ordered include directory list.
-  for (std::string const& i : userDirs) {
-    if (emitted.insert(i).second) {
-      dirs.push_back(i);
+  for (BT<std::string> const& i : userDirs) {
+    if (emitted.insert(i.Value).second) {
+      result.push_back(i);
     }
     }
   }
   }
 
 
-  MoveSystemIncludesToEnd(dirs, config, lang, target);
+  MoveSystemIncludesToEnd(result, config, lang, target);
 
 
   // Add standard include directories for this language.
   // Add standard include directories for this language.
   {
   {
-    std::vector<std::string>::size_type const before = userDirs.size();
+    std::vector<std::string> userStandardDirs;
     {
     {
       std::string key = "CMAKE_";
       std::string key = "CMAKE_";
       key += lang;
       key += lang;
       key += "_STANDARD_INCLUDE_DIRECTORIES";
       key += "_STANDARD_INCLUDE_DIRECTORIES";
       std::string const value = this->Makefile->GetSafeDefinition(key);
       std::string const value = this->Makefile->GetSafeDefinition(key);
-      cmSystemTools::ExpandListArgument(value, userDirs);
+      cmSystemTools::ExpandListArgument(value, userStandardDirs);
     }
     }
-    for (std::vector<std::string>::iterator i = userDirs.begin() + before,
-                                            ie = userDirs.end();
-         i != ie; ++i) {
-      cmSystemTools::ConvertToUnixSlashes(*i);
-      dirs.push_back(*i);
+    userDirs.reserve(userDirs.size() + userStandardDirs.size());
+    for (std::string& d : userStandardDirs) {
+      cmSystemTools::ConvertToUnixSlashes(d);
+      result.emplace_back(d);
+      userDirs.emplace_back(std::move(d));
     }
     }
   }
   }
 
 
@@ -985,18 +1018,20 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
     // Append only implicit directories that were requested by the user
     // Append only implicit directories that were requested by the user
     for (std::string const& i : implicitDirs) {
     for (std::string const& i : implicitDirs) {
       if (std::find(userDirs.begin(), userDirs.end(), i) != userDirs.end()) {
       if (std::find(userDirs.begin(), userDirs.end(), i) != userDirs.end()) {
-        dirs.push_back(i);
+        result.emplace_back(i);
       }
       }
     }
     }
     // Append remaining implicit directories on demand
     // Append remaining implicit directories on demand
     if (appendAllImplicitDirs) {
     if (appendAllImplicitDirs) {
       for (std::string const& i : implicitDirs) {
       for (std::string const& i : implicitDirs) {
-        if (std::find(dirs.begin(), dirs.end(), i) == dirs.end()) {
-          dirs.push_back(i);
+        if (std::find(result.begin(), result.end(), i) == result.end()) {
+          result.emplace_back(i);
         }
         }
       }
       }
     }
     }
   }
   }
+
+  return result;
 }
 }
 
 
 void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags,
 void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags,
@@ -1253,15 +1288,29 @@ void cmLocalGenerator::GetTargetDefines(cmGeneratorTarget const* target,
                                         std::string const& lang,
                                         std::string const& lang,
                                         std::set<std::string>& defines) const
                                         std::set<std::string>& defines) const
 {
 {
+  std::set<BT<std::string>> tmp = this->GetTargetDefines(target, config, lang);
+  for (BT<std::string> const& v : tmp) {
+    defines.emplace(v.Value);
+  }
+}
+
+std::set<BT<std::string>> cmLocalGenerator::GetTargetDefines(
+  cmGeneratorTarget const* target, std::string const& config,
+  std::string const& lang) const
+{
+  std::set<BT<std::string>> defines;
+
   // Add the export symbol definition for shared library objects.
   // Add the export symbol definition for shared library objects.
   if (const std::string* exportMacro = target->GetExportMacro()) {
   if (const std::string* exportMacro = target->GetExportMacro()) {
     this->AppendDefines(defines, *exportMacro);
     this->AppendDefines(defines, *exportMacro);
   }
   }
 
 
   // Add preprocessor definitions for this target and configuration.
   // Add preprocessor definitions for this target and configuration.
-  std::vector<std::string> targetDefines;
-  target->GetCompileDefinitions(targetDefines, config, lang);
+  std::vector<BT<std::string>> targetDefines =
+    target->GetCompileDefinitions(config, lang);
   this->AppendDefines(defines, targetDefines);
   this->AppendDefines(defines, targetDefines);
+
+  return defines;
 }
 }
 
 
 std::string cmLocalGenerator::GetTargetFortranFlags(
 std::string cmLocalGenerator::GetTargetFortranFlags(
@@ -2060,6 +2109,16 @@ void cmLocalGenerator::AppendIncludeDirectories(
 
 
 void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
 void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
                                      const char* defines_list) const
                                      const char* defines_list) const
+{
+  std::set<BT<std::string>> tmp;
+  this->AppendDefines(tmp, ExpandListWithBacktrace(defines_list));
+  for (BT<std::string> const& i : tmp) {
+    defines.emplace(i.Value);
+  }
+}
+
+void cmLocalGenerator::AppendDefines(std::set<BT<std::string>>& defines,
+                                     const char* defines_list) const
 {
 {
   // Short-circuit if there are no definitions.
   // Short-circuit if there are no definitions.
   if (!defines_list) {
   if (!defines_list) {
@@ -2067,18 +2126,16 @@ void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
   }
   }
 
 
   // Expand the list of definitions.
   // Expand the list of definitions.
-  std::vector<std::string> defines_vec;
-  cmSystemTools::ExpandListArgument(defines_list, defines_vec);
-  this->AppendDefines(defines, defines_vec);
+  this->AppendDefines(defines, ExpandListWithBacktrace(defines_list));
 }
 }
 
 
 void cmLocalGenerator::AppendDefines(
 void cmLocalGenerator::AppendDefines(
-  std::set<std::string>& defines,
-  const std::vector<std::string>& defines_vec) const
+  std::set<BT<std::string>>& defines,
+  const std::vector<BT<std::string>>& defines_vec) const
 {
 {
-  for (std::string const& d : defines_vec) {
+  for (BT<std::string> const& d : defines_vec) {
     // Skip unsupported definitions.
     // Skip unsupported definitions.
-    if (!this->CheckDefinition(d)) {
+    if (!this->CheckDefinition(d.Value)) {
       continue;
       continue;
     }
     }
     defines.insert(d);
     defines.insert(d);

+ 16 - 2
Source/cmLocalGenerator.h

@@ -175,8 +175,15 @@ public:
   {
   {
     this->AppendDefines(defines, defines_list.c_str());
     this->AppendDefines(defines, defines_list.c_str());
   }
   }
-  void AppendDefines(std::set<std::string>& defines,
-                     const std::vector<std::string>& defines_vec) const;
+  void AppendDefines(std::set<BT<std::string>>& defines,
+                     const char* defines_list) const;
+  void AppendDefines(std::set<BT<std::string>>& defines,
+                     std::string const& defines_list) const
+  {
+    this->AppendDefines(defines, defines_list.c_str());
+  }
+  void AppendDefines(std::set<BT<std::string>>& defines,
+                     const std::vector<BT<std::string>>& defines_vec) const;
 
 
   /**
   /**
    * Encode a list of compile options for the compiler
    * Encode a list of compile options for the compiler
@@ -249,6 +256,10 @@ public:
                              const std::string& config = "",
                              const std::string& config = "",
                              bool stripImplicitDirs = true,
                              bool stripImplicitDirs = true,
                              bool appendAllImplicitDirs = false) const;
                              bool appendAllImplicitDirs = false) const;
+  std::vector<BT<std::string>> GetIncludeDirectories(
+    cmGeneratorTarget const* target, std::string const& lang = "C",
+    std::string const& config = "", bool stripImplicitDirs = true,
+    bool appendAllImplicitDirs = false) const;
   void AddCompileOptions(std::string& flags, cmGeneratorTarget* target,
   void AddCompileOptions(std::string& flags, cmGeneratorTarget* target,
                          const std::string& lang, const std::string& config);
                          const std::string& lang, const std::string& config);
 
 
@@ -332,6 +343,9 @@ public:
   void GetTargetDefines(cmGeneratorTarget const* target,
   void GetTargetDefines(cmGeneratorTarget const* target,
                         std::string const& config, std::string const& lang,
                         std::string const& config, std::string const& lang,
                         std::set<std::string>& defines) const;
                         std::set<std::string>& defines) const;
+  std::set<BT<std::string>> GetTargetDefines(cmGeneratorTarget const* target,
+                                             std::string const& config,
+                                             std::string const& lang) const;
   void GetTargetCompileFlags(cmGeneratorTarget* target,
   void GetTargetCompileFlags(cmGeneratorTarget* target,
                              std::string const& config,
                              std::string const& config,
                              std::string const& lang, std::string& flags);
                              std::string const& lang, std::string& flags);