[Cmake-commits] CMake branch, next, updated. v3.7.0-rc1-394-g67c528c

Stephen Kelly steveire at gmail.com
Mon Oct 10 18:44:24 EDT 2016


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, next has been updated
       via  67c528c03d2c598e4922f932c5598d5da91bc408 (commit)
       via  6f0cee13fdadd4573e9dd57c1713d9a674abb713 (commit)
       via  a60ea0a957978495bd8a2dacb17447ef9e0bc694 (commit)
       via  8b3af6a7ca2d4938568df8dc70c9d44c62ba9fe1 (commit)
       via  49afda6b4e94d7747058bf5174bda6c333c921c6 (commit)
       via  91bc8ec9b8941f15c9adca532afa2dea9d1c1fa1 (commit)
       via  3743af8aa6db573370b5f4d10b06d35ab507b894 (commit)
       via  780b5ea7c5b416e17f469235c08679fa3417262b (commit)
       via  b9badf851e865ef7076abb49904785b026909a49 (commit)
       via  b2c6630c566344c4289cf312adfa45f939820f54 (commit)
      from  17bef2cd6780731f77be1383f74ddb5d9c44bffc (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=67c528c03d2c598e4922f932c5598d5da91bc408
commit 67c528c03d2c598e4922f932c5598d5da91bc408
Merge: 17bef2c 6f0cee1
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Mon Oct 10 18:44:22 2016 -0400
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Mon Oct 10 18:44:22 2016 -0400

    Merge topic 'extract-cmRulePlaceholderExpander' into next
    
    6f0cee13 cmRulePlaceholderExpander: Port clients to direct-use
    a60ea0a9 cmRulePlaceholderExpander: Extract from cmLocalGenerator
    8b3af6a7 cmLocalGenerator: Use strings instead of a Target in rule replacement
    49afda6b cmLocalGenerator: Use a converter in rule replacement API
    91bc8ec9 cmLocalGenerator: Store variable replacements as state
    3743af8a cmLocalGenerator: Merge loops which populate mapping
    780b5ea7 cmLocalGenerator: Populate variable mapping for all replacements
    b9badf85 cmLocalGenerator: Extract compiler option replacement from loop
    b2c6630c cmLocalGenerator: Populate a container of mappings for replacements


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6f0cee13fdadd4573e9dd57c1713d9a674abb713
commit 6f0cee13fdadd4573e9dd57c1713d9a674abb713
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Oct 9 10:34:50 2016 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Tue Oct 11 00:43:48 2016 +0200

    cmRulePlaceholderExpander: Port clients to direct-use
    
    Add a factory function to cmLocalGenerator so that variableMappings can
    be provided from it, and so that Ninja can always have a hard-coded
    TargetImpLib.

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 615168d..1c3a97d 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -133,6 +133,13 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
   }
 }
 
+cmRulePlaceholderExpander* cmLocalGenerator::CreateRulePlaceholderExpander()
+  const
+{
+  return new cmRulePlaceholderExpander(this->Compilers, this->VariableMappings,
+                                       this->CompilerSysroot);
+}
+
 cmLocalGenerator::~cmLocalGenerator()
 {
   cmDeleteAll(this->GeneratorTargets);
@@ -561,17 +568,6 @@ cmState::Snapshot cmLocalGenerator::GetStateSnapshot() const
   return this->Makefile->GetStateSnapshot();
 }
 
-void cmLocalGenerator::ExpandRuleVariables(cmOutputConverter* outputConverter,
-                                           std::string& s,
-                                           const RuleVariables& replaceValues)
-{
-  cmRulePlaceholderExpander rulePlaceholderExpander(
-    this->Compilers, this->VariableMappings, this->CompilerSysroot);
-  rulePlaceholderExpander.SetTargetImpLib(this->TargetImplib);
-  rulePlaceholderExpander.ExpandRuleVariables(outputConverter, s,
-                                              replaceValues);
-}
-
 const char* cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target,
                                               const std::string& prop)
 {
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 6f8426d..055e1a9 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -24,6 +24,7 @@ class cmComputeLinkInformation;
 class cmCustomCommandGenerator;
 class cmGeneratorTarget;
 class cmGlobalGenerator;
+class cmRulePlaceholderExpander;
 class cmMakefile;
 class cmSourceFile;
 class cmLinkLineComputer;
@@ -85,6 +86,8 @@ public:
     return this->GlobalGenerator;
   }
 
+  virtual cmRulePlaceholderExpander* CreateRulePlaceholderExpander() const;
+
   std::string GetLinkLibsCMP0065(std::string const& linkLanguage,
                                  cmGeneratorTarget& tgt) const;
 
@@ -218,10 +221,6 @@ public:
   // preprocessed files and assembly files.
   void GetIndividualFileTargets(std::vector<std::string>&) {}
 
-  struct RuleVariables : cmRulePlaceholderExpander::RuleVariables
-  {
-  };
-
   /**
    * Get the relative path from the generator output directory to a
    * per-target support directory.
@@ -315,11 +314,6 @@ public:
   void CreateEvaluationFileOutputs(const std::string& config);
   void ProcessEvaluationFiles(std::vector<std::string>& generatedFiles);
 
-  // Expand rule variables in CMake of the type found in language rules
-  void ExpandRuleVariables(cmOutputConverter* outputConverter,
-                           std::string& string,
-                           const RuleVariables& replaceValues);
-
   const char* GetRuleLauncher(cmGeneratorTarget* target,
                               const std::string& prop);
 
@@ -362,10 +356,6 @@ protected:
 
   bool EmitUniversalBinaryFlags;
 
-  // Hack for ExpandRuleVariable until object-oriented version is
-  // committed.
-  std::string TargetImplib;
-
   KWIML_INT_uint64_t BackwardsCompatibility;
   bool BackwardsCompatibilityFinal;
 
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 05596f8..1863376 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -10,6 +10,7 @@
 #include "cmGlobalNinjaGenerator.h"
 #include "cmMakefile.h"
 #include "cmNinjaTargetGenerator.h"
+#include "cmRulePlaceholderExpander.h"
 #include "cmSourceFile.h"
 #include "cmState.h"
 #include "cmSystemTools.h"
@@ -27,11 +28,19 @@ cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
   : cmLocalCommonGenerator(gg, mf, mf->GetState()->GetBinaryDirectory())
   , HomeRelativeOutputPath("")
 {
-  this->TargetImplib = "$TARGET_IMPLIB";
 }
 
 // Virtual public methods.
 
+cmRulePlaceholderExpander*
+cmLocalNinjaGenerator::CreateRulePlaceholderExpander() const
+{
+  cmRulePlaceholderExpander* ret = new cmRulePlaceholderExpander(
+    this->Compilers, this->VariableMappings, this->CompilerSysroot);
+  ret->SetTargetImpLib("$TARGET_IMPLIB");
+  return ret;
+}
+
 cmLocalNinjaGenerator::~cmLocalNinjaGenerator()
 {
 }
@@ -477,7 +486,7 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
 
   // Expand rules in the empty string.  It may insert the launcher and
   // perform replacements.
-  RuleVariables vars;
+  cmRulePlaceholderExpander::RuleVariables vars;
 
   std::string output;
   const std::vector<std::string>& outputs = ccg.GetOutputs();
@@ -494,7 +503,10 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
   std::string launcher = property_value;
   launcher += " ";
 
-  this->ExpandRuleVariables(this, launcher, vars);
+  CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+    this->CreateRulePlaceholderExpander());
+
+  rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars);
   if (!launcher.empty()) {
     launcher += " ";
   }
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index 56aa9bf..95d8eb8 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -42,6 +42,8 @@ public:
 
   void Generate() CM_OVERRIDE;
 
+  cmRulePlaceholderExpander* CreateRulePlaceholderExpander() const CM_OVERRIDE;
+
   std::string GetTargetDirectory(cmGeneratorTarget const* target) const
     CM_OVERRIDE;
 
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 6906cbf..f30414c 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -14,6 +14,7 @@
 #include "cmMakefile.h"
 #include "cmMakefileTargetGenerator.h"
 #include "cmOutputConverter.h"
+#include "cmRulePlaceholderExpander.h"
 #include "cmSourceFile.h"
 #include "cmState.h"
 #include "cmSystemTools.h"
@@ -945,6 +946,9 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
     *content << dir;
   }
 
+  CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+    this->CreateRulePlaceholderExpander());
+
   // Add each command line to the set of commands.
   std::vector<std::string> commands1;
   std::string currentBinDir = this->GetCurrentBinaryDirectory();
@@ -988,7 +992,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
       if (val && *val) {
         // Expand rules in the empty string.  It may insert the launcher and
         // perform replacements.
-        RuleVariables vars;
+        cmRulePlaceholderExpander::RuleVariables vars;
         vars.CMTargetName = target->GetName().c_str();
         vars.CMTargetType = cmState::GetTargetTypeName(target->GetType());
         std::string output;
@@ -1006,7 +1010,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
 
         launcher = val;
         launcher += " ";
-        this->ExpandRuleVariables(this, launcher, vars);
+        rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars);
         if (!launcher.empty()) {
           launcher += " ";
         }
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 8d235c4..dd3fc36 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -11,6 +11,7 @@
 #include "cmMakefile.h"
 #include "cmOSXBundleGenerator.h"
 #include "cmOutputConverter.h"
+#include "cmRulePlaceholderExpander.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
@@ -331,7 +332,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
 
     std::string manifests = this->GetManifests();
 
-    cmLocalGenerator::RuleVariables vars;
+    cmRulePlaceholderExpander::RuleVariables vars;
     vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
     vars.CMTargetType =
       cmState::GetTargetTypeName(this->GeneratorTarget->GetType());
@@ -393,15 +394,17 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
       launcher += " ";
     }
 
+    CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+      this->LocalGenerator->CreateRulePlaceholderExpander());
+
     // Expand placeholders in the commands.
-    this->LocalGenerator->TargetImplib = targetOutPathImport;
+    rulePlaceholderExpander->SetTargetImpLib(targetOutPathImport);
     for (std::vector<std::string>::iterator i = real_link_commands.begin();
          i != real_link_commands.end(); ++i) {
       *i = launcher + *i;
-      this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, *i,
-                                                vars);
+      rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, *i,
+                                                   vars);
     }
-    this->LocalGenerator->TargetImplib = "";
 
     // Restore path conversion to normal shells.
     this->LocalGenerator->SetLinkScriptShell(false);
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index fe37a83..9f5f0c1 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -11,6 +11,7 @@
 #include "cmMakefile.h"
 #include "cmOSXBundleGenerator.h"
 #include "cmOutputConverter.h"
+#include "cmRulePlaceholderExpander.h"
 #include "cmState.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
@@ -532,7 +533,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
 
     std::string manifests = this->GetManifests();
 
-    cmLocalGenerator::RuleVariables vars;
+    cmRulePlaceholderExpander::RuleVariables vars;
     vars.TargetPDB = targetOutPathPDB.c_str();
 
     // Setup the target version.
@@ -623,8 +624,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
       launcher += " ";
     }
 
+    CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+      this->LocalGenerator->CreateRulePlaceholderExpander());
     // Construct the main link rule and expand placeholders.
-    this->LocalGenerator->TargetImplib = targetOutPathImport;
+    rulePlaceholderExpander->SetTargetImpLib(targetOutPathImport);
     if (useArchiveRules) {
       // Construct the individual object list strings.
       std::vector<std::string> object_strings;
@@ -638,8 +641,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
                archiveCreateCommands.begin();
              i != archiveCreateCommands.end(); ++i) {
           std::string cmd = launcher + *i;
-          this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, cmd,
-                                                    vars);
+          rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+                                                       cmd, vars);
           real_link_commands.push_back(cmd);
         }
       }
@@ -650,8 +653,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
                archiveAppendCommands.begin();
              i != archiveAppendCommands.end(); ++i) {
           std::string cmd = launcher + *i;
-          this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, cmd,
-                                                    vars);
+          rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+                                                       cmd, vars);
           real_link_commands.push_back(cmd);
         }
       }
@@ -661,8 +664,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
              archiveFinishCommands.begin();
            i != archiveFinishCommands.end(); ++i) {
         std::string cmd = launcher + *i;
-        this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, cmd,
-                                                  vars);
+        rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, cmd,
+                                                     vars);
         // If there is no ranlib the command will be ":".  Skip it.
         if (!cmd.empty() && cmd[0] != ':') {
           real_link_commands.push_back(cmd);
@@ -685,11 +688,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
       for (std::vector<std::string>::iterator i = real_link_commands.begin();
            i != real_link_commands.end(); ++i) {
         *i = launcher + *i;
-        this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, *i,
-                                                  vars);
+        rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, *i,
+                                                     vars);
       }
     }
-    this->LocalGenerator->TargetImplib = "";
 
     // Restore path conversion to normal shells.
     this->LocalGenerator->SetLinkScriptShell(false);
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index ed1fe16..3947c47 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -18,6 +18,7 @@
 #include "cmMakefileLibraryTargetGenerator.h"
 #include "cmMakefileUtilityTargetGenerator.h"
 #include "cmOutputConverter.h"
+#include "cmRulePlaceholderExpander.h"
 #include "cmSourceFile.h"
 #include "cmState.h"
 #include "cmSystemTools.h"
@@ -543,7 +544,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
       targetOutPathCompilePDB[targetOutPathCompilePDB.size() - 1] = '/';
     }
   }
-  cmLocalGenerator::RuleVariables vars;
+  cmRulePlaceholderExpander::RuleVariables vars;
   vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
   vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
   vars.CMTargetType =
@@ -589,6 +590,9 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
   bool const lang_has_assembly = lang_has_preprocessor;
   bool const lang_can_export_cmds = lang_has_preprocessor;
 
+  CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+    this->LocalGenerator->CreateRulePlaceholderExpander());
+
   // Construct the compile rules.
   {
     std::string compileRuleVar = "CMAKE_";
@@ -602,8 +606,9 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
     if (this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS") &&
         lang_can_export_cmds && compileCommands.size() == 1) {
       std::string compileCommand = compileCommands[0];
-      this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator,
-                                                compileCommand, vars);
+
+      rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+                                                   compileCommand, vars);
       std::string workingDirectory = cmSystemTools::CollapseFullPath(
         this->LocalGenerator->GetCurrentBinaryDirectory());
       compileCommand.replace(compileCommand.find(langFlags), langFlags.size(),
@@ -662,8 +667,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
     // Expand placeholders in the commands.
     for (std::vector<std::string>::iterator i = compileCommands.begin();
          i != compileCommands.end(); ++i) {
-      this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, *i,
-                                                vars);
+      rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, *i,
+                                                   vars);
     }
 
     // Change the command working directory to the local build tree.
@@ -726,8 +731,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
         // Expand placeholders in the commands.
         for (std::vector<std::string>::iterator i = preprocessCommands.begin();
              i != preprocessCommands.end(); ++i) {
-          this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, *i,
-                                                    vars);
+          rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+                                                       *i, vars);
         }
 
         this->LocalGenerator->CreateCDCommand(
@@ -774,8 +779,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
         // Expand placeholders in the commands.
         for (std::vector<std::string>::iterator i = assemblyCommands.begin();
              i != assemblyCommands.end(); ++i) {
-          this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, *i,
-                                                    vars);
+          rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+                                                       *i, vars);
         }
 
         this->LocalGenerator->CreateCDCommand(
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 1f2e4ee..fe51f34 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -15,6 +15,7 @@
 #include "cmNinjaTypes.h"
 #include "cmOSXBundleGenerator.h"
 #include "cmOutputConverter.h"
+#include "cmRulePlaceholderExpander.h"
 #include "cmSourceFile.h"
 #include "cmState.h"
 #include "cmSystemTools.h"
@@ -167,7 +168,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
   std::string rspcontent;
 
   if (!this->GetGlobalGenerator()->HasRule(ruleName)) {
-    cmLocalGenerator::RuleVariables vars;
+    cmRulePlaceholderExpander::RuleVariables vars;
     vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
     vars.CMTargetType =
       cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType());
@@ -248,13 +249,16 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
       launcher += " ";
     }
 
+    CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+      this->GetLocalGenerator()->CreateRulePlaceholderExpander());
+
     // Rule for linking library/executable.
     std::vector<std::string> linkCmds = this->ComputeLinkCmd();
     for (std::vector<std::string>::iterator i = linkCmds.begin();
          i != linkCmds.end(); ++i) {
       *i = launcher + *i;
-      this->GetLocalGenerator()->ExpandRuleVariables(this->GetLocalGenerator(),
-                                                     *i, vars);
+      rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
+                                                   *i, vars);
     }
     {
       // If there is no ranlib the command will be ":".  Skip it.
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 11ecc84..0650e40 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -14,6 +14,7 @@
 #include "cmNinjaNormalTargetGenerator.h"
 #include "cmNinjaUtilityTargetGenerator.h"
 #include "cmOutputConverter.h"
+#include "cmRulePlaceholderExpander.h"
 #include "cmSourceFile.h"
 #include "cmState.h"
 #include "cmSystemTools.h"
@@ -373,7 +374,7 @@ void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language)
 
 void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
 {
-  cmLocalGenerator::RuleVariables vars;
+  cmRulePlaceholderExpander::RuleVariables vars;
   vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
   vars.CMTargetType =
     cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType());
@@ -453,6 +454,9 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
   vars.Flags = flags.c_str();
   vars.DependencyFile = depfile.c_str();
 
+  CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+    this->GetLocalGenerator()->CreateRulePlaceholderExpander());
+
   std::string const tdi = this->GetLocalGenerator()->ConvertToOutputFormat(
     ConvertToNinjaPath(this->GetTargetDependInfoPath(lang)),
     cmLocalGenerator::SHELL);
@@ -475,7 +479,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
     std::string const ppDeptype = ""; // no deps= for multiple outputs
     std::string const ppDepfile = "$DEP_FILE";
 
-    cmLocalGenerator::RuleVariables ppVars;
+    cmRulePlaceholderExpander::RuleVariables ppVars;
     ppVars.CMTargetName = vars.CMTargetName;
     ppVars.CMTargetType = vars.CMTargetType;
     ppVars.Language = vars.Language;
@@ -506,8 +510,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
     for (std::vector<std::string>::iterator i = ppCmds.begin();
          i != ppCmds.end(); ++i) {
       *i = launcher + *i;
-      this->GetLocalGenerator()->ExpandRuleVariables(this->GetLocalGenerator(),
-                                                     *i, ppVars);
+      rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
+                                                   *i, ppVars);
     }
 
     // Run CMake dependency scanner on preprocessed output.
@@ -620,8 +624,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
   for (std::vector<std::string>::iterator i = compileCmds.begin();
        i != compileCmds.end(); ++i) {
     *i = launcher + *i;
-    this->GetLocalGenerator()->ExpandRuleVariables(this->GetLocalGenerator(),
-                                                   *i, vars);
+    rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), *i,
+                                                 vars);
   }
 
   std::string cmdLine =
@@ -974,7 +978,7 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
     return;
   }
 
-  cmLocalGenerator::RuleVariables compileObjectVars;
+  cmRulePlaceholderExpander::RuleVariables compileObjectVars;
   compileObjectVars.Language = language.c_str();
 
   std::string escapedSourceFileName = sourceFileName;
@@ -1006,10 +1010,13 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
   std::vector<std::string> compileCmds;
   cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
 
+  CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+    this->GetLocalGenerator()->CreateRulePlaceholderExpander());
+
   for (std::vector<std::string>::iterator i = compileCmds.begin();
        i != compileCmds.end(); ++i) {
-    this->GetLocalGenerator()->ExpandRuleVariables(this->GetLocalGenerator(),
-                                                   *i, compileObjectVars);
+    rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), *i,
+                                                 compileObjectVars);
   }
 
   std::string cmdLine =

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a60ea0a957978495bd8a2dacb17447ef9e0bc694
commit a60ea0a957978495bd8a2dacb17447ef9e0bc694
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Oct 9 10:34:50 2016 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Tue Oct 11 00:43:48 2016 +0200

    cmRulePlaceholderExpander: Extract from cmLocalGenerator
    
    Implement cmLocalGenerator::ExpandRuleVariables in terms of the new
    class for source compatibility and to reduce diff noise in this commit.

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 048667a..7d82a51 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -309,6 +309,8 @@ set(SRCS
   cmLocalCommonGenerator.h
   cmLocalGenerator.cxx
   cmLocalGenerator.h
+  cmRulePlaceholderExpander.cxx
+  cmRulePlaceholderExpander.h
   cmLocalUnixMakefileGenerator3.cxx
   cmLocale.h
   ${MACH_SRCS}
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 3489188..615168d 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -14,6 +14,7 @@
 #include "cmInstallTargetGenerator.h"
 #include "cmLinkLineComputer.h"
 #include "cmMakefile.h"
+#include "cmRulePlaceholderExpander.h"
 #include "cmSourceFile.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
@@ -560,287 +561,15 @@ cmState::Snapshot cmLocalGenerator::GetStateSnapshot() const
   return this->Makefile->GetStateSnapshot();
 }
 
-std::string cmLocalGenerator::ExpandRuleVariable(
-  cmOutputConverter* outputConverter, std::string const& variable,
-  const RuleVariables& replaceValues)
-{
-  if (replaceValues.LinkFlags) {
-    if (variable == "LINK_FLAGS") {
-      return replaceValues.LinkFlags;
-    }
-  }
-  if (replaceValues.Manifests) {
-    if (variable == "MANIFESTS") {
-      return replaceValues.Manifests;
-    }
-  }
-  if (replaceValues.Flags) {
-    if (variable == "FLAGS") {
-      return replaceValues.Flags;
-    }
-  }
-
-  if (replaceValues.Source) {
-    if (variable == "SOURCE") {
-      return replaceValues.Source;
-    }
-  }
-  if (replaceValues.PreprocessedSource) {
-    if (variable == "PREPROCESSED_SOURCE") {
-      return replaceValues.PreprocessedSource;
-    }
-  }
-  if (replaceValues.AssemblySource) {
-    if (variable == "ASSEMBLY_SOURCE") {
-      return replaceValues.AssemblySource;
-    }
-  }
-  if (replaceValues.Object) {
-    if (variable == "OBJECT") {
-      return replaceValues.Object;
-    }
-  }
-  if (replaceValues.ObjectDir) {
-    if (variable == "OBJECT_DIR") {
-      return replaceValues.ObjectDir;
-    }
-  }
-  if (replaceValues.ObjectFileDir) {
-    if (variable == "OBJECT_FILE_DIR") {
-      return replaceValues.ObjectFileDir;
-    }
-  }
-  if (replaceValues.Objects) {
-    if (variable == "OBJECTS") {
-      return replaceValues.Objects;
-    }
-  }
-  if (replaceValues.ObjectsQuoted) {
-    if (variable == "OBJECTS_QUOTED") {
-      return replaceValues.ObjectsQuoted;
-    }
-  }
-  if (replaceValues.Defines && variable == "DEFINES") {
-    return replaceValues.Defines;
-  }
-  if (replaceValues.Includes && variable == "INCLUDES") {
-    return replaceValues.Includes;
-  }
-  if (replaceValues.TargetPDB) {
-    if (variable == "TARGET_PDB") {
-      return replaceValues.TargetPDB;
-    }
-  }
-  if (replaceValues.TargetCompilePDB) {
-    if (variable == "TARGET_COMPILE_PDB") {
-      return replaceValues.TargetCompilePDB;
-    }
-  }
-  if (replaceValues.DependencyFile) {
-    if (variable == "DEP_FILE") {
-      return replaceValues.DependencyFile;
-    }
-  }
-
-  if (replaceValues.Target) {
-    if (variable == "TARGET_QUOTED") {
-      std::string targetQuoted = replaceValues.Target;
-      if (!targetQuoted.empty() && targetQuoted[0] != '\"') {
-        targetQuoted = '\"';
-        targetQuoted += replaceValues.Target;
-        targetQuoted += '\"';
-      }
-      return targetQuoted;
-    }
-    if (variable == "TARGET_UNQUOTED") {
-      std::string unquoted = replaceValues.Target;
-      std::string::size_type sz = unquoted.size();
-      if (sz > 2 && unquoted[0] == '\"' && unquoted[sz - 1] == '\"') {
-        unquoted = unquoted.substr(1, sz - 2);
-      }
-      return unquoted;
-    }
-    if (replaceValues.LanguageCompileFlags) {
-      if (variable == "LANGUAGE_COMPILE_FLAGS") {
-        return replaceValues.LanguageCompileFlags;
-      }
-    }
-    if (replaceValues.Target) {
-      if (variable == "TARGET") {
-        return replaceValues.Target;
-      }
-    }
-    if (variable == "TARGET_IMPLIB") {
-      return this->TargetImplib;
-    }
-    if (variable == "TARGET_VERSION_MAJOR") {
-      if (replaceValues.TargetVersionMajor) {
-        return replaceValues.TargetVersionMajor;
-      }
-      return "0";
-    }
-    if (variable == "TARGET_VERSION_MINOR") {
-      if (replaceValues.TargetVersionMinor) {
-        return replaceValues.TargetVersionMinor;
-      }
-      return "0";
-    }
-    if (replaceValues.Target) {
-      if (variable == "TARGET_BASE") {
-        // Strip the last extension off the target name.
-        std::string targetBase = replaceValues.Target;
-        std::string::size_type pos = targetBase.rfind('.');
-        if (pos != targetBase.npos) {
-          return targetBase.substr(0, pos);
-        }
-        return targetBase;
-      }
-    }
-  }
-  if (variable == "TARGET_SONAME" || variable == "SONAME_FLAG" ||
-      variable == "TARGET_INSTALLNAME_DIR") {
-    // All these variables depend on TargetSOName
-    if (replaceValues.TargetSOName) {
-      if (variable == "TARGET_SONAME") {
-        return replaceValues.TargetSOName;
-      }
-      if (variable == "SONAME_FLAG" && replaceValues.SONameFlag) {
-        return replaceValues.SONameFlag;
-      }
-      if (replaceValues.TargetInstallNameDir &&
-          variable == "TARGET_INSTALLNAME_DIR") {
-        return replaceValues.TargetInstallNameDir;
-      }
-    }
-    return "";
-  }
-  if (replaceValues.LinkLibraries) {
-    if (variable == "LINK_LIBRARIES") {
-      return replaceValues.LinkLibraries;
-    }
-  }
-  if (replaceValues.Language) {
-    if (variable == "LANGUAGE") {
-      return replaceValues.Language;
-    }
-  }
-  if (replaceValues.CMTargetName) {
-    if (variable == "TARGET_NAME") {
-      return replaceValues.CMTargetName;
-    }
-  }
-  if (replaceValues.CMTargetType) {
-    if (variable == "TARGET_TYPE") {
-      return replaceValues.CMTargetType;
-    }
-  }
-  if (replaceValues.Output) {
-    if (variable == "OUTPUT") {
-      return replaceValues.Output;
-    }
-  }
-  if (variable == "CMAKE_COMMAND") {
-    return outputConverter->ConvertToOutputFormat(
-      cmSystemTools::CollapseFullPath(cmSystemTools::GetCMakeCommand()),
-      SHELL);
-  }
-
-  std::map<std::string, std::string>::iterator compIt =
-    this->Compilers.find(variable);
-
-  if (compIt != this->Compilers.end()) {
-    std::string ret = outputConverter->ConvertToOutputForExisting(
-      this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER"]);
-    std::string const& compilerArg1 =
-      this->VariableMappings[compIt->first + "_COMPILER_ARG1"];
-    std::string const& compilerTarget =
-      this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER_TARGET"];
-    std::string const& compilerOptionTarget =
-      this->VariableMappings["CMAKE_" + compIt->second +
-                             "_COMPILE_OPTIONS_TARGET"];
-    std::string const& compilerExternalToolchain =
-      this->VariableMappings["CMAKE_" + compIt->second +
-                             "_COMPILER_EXTERNAL_TOOLCHAIN"];
-    std::string const& compilerOptionExternalToolchain =
-      this->VariableMappings["CMAKE_" + compIt->second +
-                             "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN"];
-    std::string const& compilerOptionSysroot =
-      this->VariableMappings["CMAKE_" + compIt->second +
-                             "_COMPILE_OPTIONS_SYSROOT"];
-
-    // if there is a required first argument to the compiler add it
-    // to the compiler string
-    if (!compilerArg1.empty()) {
-      ret += " ";
-      ret += compilerArg1;
-    }
-    if (!compilerTarget.empty() && !compilerOptionTarget.empty()) {
-      ret += " ";
-      ret += compilerOptionTarget;
-      ret += compilerTarget;
-    }
-    if (!compilerExternalToolchain.empty() &&
-        !compilerOptionExternalToolchain.empty()) {
-      ret += " ";
-      ret += compilerOptionExternalToolchain;
-      ret += outputConverter->EscapeForShell(compilerExternalToolchain, true);
-    }
-    if (this->CompilerSysroot.empty() && !compilerOptionSysroot.empty()) {
-      ret += " ";
-      ret += compilerOptionSysroot;
-      ret += outputConverter->EscapeForShell(this->CompilerSysroot, true);
-    }
-    return ret;
-  }
-
-  std::map<std::string, std::string>::iterator mapIt =
-    this->VariableMappings.find(variable);
-  if (mapIt != this->VariableMappings.end()) {
-    if (variable.find("_FLAG") == variable.npos) {
-      return outputConverter->ConvertToOutputForExisting(mapIt->second);
-    }
-    return mapIt->second;
-  }
-  return variable;
-}
-
 void cmLocalGenerator::ExpandRuleVariables(cmOutputConverter* outputConverter,
                                            std::string& s,
                                            const RuleVariables& replaceValues)
 {
-  std::string::size_type start = s.find('<');
-  // no variables to expand
-  if (start == s.npos) {
-    return;
-  }
-  std::string::size_type pos = 0;
-  std::string expandedInput;
-  while (start != s.npos && start < s.size() - 2) {
-    std::string::size_type end = s.find('>', start);
-    // if we find a < with no > we are done
-    if (end == s.npos) {
-      return;
-    }
-    char c = s[start + 1];
-    // if the next char after the < is not A-Za-z then
-    // skip it and try to find the next < in the string
-    if (!isalpha(c)) {
-      start = s.find('<', start + 1);
-    } else {
-      // extract the var
-      std::string var = s.substr(start + 1, end - start - 1);
-      std::string replace =
-        this->ExpandRuleVariable(outputConverter, var, replaceValues);
-      expandedInput += s.substr(pos, start - pos);
-      expandedInput += replace;
-      // move to next one
-      start = s.find('<', start + var.size() + 2);
-      pos = end + 1;
-    }
-  }
-  // add the rest of the input
-  expandedInput += s.substr(pos, s.size() - pos);
-  s = expandedInput;
+  cmRulePlaceholderExpander rulePlaceholderExpander(
+    this->Compilers, this->VariableMappings, this->CompilerSysroot);
+  rulePlaceholderExpander.SetTargetImpLib(this->TargetImplib);
+  rulePlaceholderExpander.ExpandRuleVariables(outputConverter, s,
+                                              replaceValues);
 }
 
 const char* cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target,
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index c51aa85..6f8426d 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -8,6 +8,7 @@
 #include "cmListFileCache.h"
 #include "cmOutputConverter.h"
 #include "cmPolicies.h"
+#include "cmRulePlaceholderExpander.h"
 #include "cmState.h"
 #include "cmake.h"
 
@@ -217,41 +218,8 @@ public:
   // preprocessed files and assembly files.
   void GetIndividualFileTargets(std::vector<std::string>&) {}
 
-  // Create a struct to hold the varibles passed into
-  // ExpandRuleVariables
-  struct RuleVariables
+  struct RuleVariables : cmRulePlaceholderExpander::RuleVariables
   {
-    RuleVariables() { memset(this, 0, sizeof(*this)); }
-    const char* CMTargetName;
-    const char* CMTargetType;
-    const char* TargetPDB;
-    const char* TargetCompilePDB;
-    const char* TargetVersionMajor;
-    const char* TargetVersionMinor;
-    const char* Language;
-    const char* Objects;
-    const char* Target;
-    const char* LinkLibraries;
-    const char* Source;
-    const char* AssemblySource;
-    const char* PreprocessedSource;
-    const char* Output;
-    const char* Object;
-    const char* ObjectDir;
-    const char* ObjectFileDir;
-    const char* Flags;
-    const char* ObjectsQuoted;
-    const char* SONameFlag;
-    const char* TargetSOName;
-    const char* TargetInstallNameDir;
-    const char* LinkFlags;
-    const char* Manifests;
-    const char* LanguageCompileFlags;
-    const char* Defines;
-    const char* Includes;
-    const char* RuleLauncher;
-    const char* DependencyFile;
-    const char* FilterPrefix;
   };
 
   /**
@@ -362,11 +330,6 @@ protected:
                            std::string& linkLibraries,
                            std::string& frameworkPath, std::string& linkPath);
 
-  // Expand rule variables in a single string
-  std::string ExpandRuleVariable(cmOutputConverter* outputConverter,
-                                 std::string const& variable,
-                                 const RuleVariables& replaceValues);
-
   // Handle old-style install rules stored in the targets.
   void GenerateTargetInstallRules(
     std::ostream& os, const std::string& config,
diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx
new file mode 100644
index 0000000..601c3b4
--- /dev/null
+++ b/Source/cmRulePlaceholderExpander.cxx
@@ -0,0 +1,299 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmRulePlaceholderExpander.h"
+
+#include "cmOutputConverter.h"
+#include "cmSystemTools.h"
+
+cmRulePlaceholderExpander::cmRulePlaceholderExpander(
+  std::map<std::string, std::string> const& compilers,
+  std::map<std::string, std::string> const& variableMappings,
+  std::string const& compilerSysroot)
+  : Compilers(compilers)
+  , VariableMappings(variableMappings)
+  , CompilerSysroot(compilerSysroot)
+{
+}
+
+std::string cmRulePlaceholderExpander::ExpandRuleVariable(
+  cmOutputConverter* outputConverter, std::string const& variable,
+  const RuleVariables& replaceValues)
+{
+  if (replaceValues.LinkFlags) {
+    if (variable == "LINK_FLAGS") {
+      return replaceValues.LinkFlags;
+    }
+  }
+  if (replaceValues.Manifests) {
+    if (variable == "MANIFESTS") {
+      return replaceValues.Manifests;
+    }
+  }
+  if (replaceValues.Flags) {
+    if (variable == "FLAGS") {
+      return replaceValues.Flags;
+    }
+  }
+
+  if (replaceValues.Source) {
+    if (variable == "SOURCE") {
+      return replaceValues.Source;
+    }
+  }
+  if (replaceValues.PreprocessedSource) {
+    if (variable == "PREPROCESSED_SOURCE") {
+      return replaceValues.PreprocessedSource;
+    }
+  }
+  if (replaceValues.AssemblySource) {
+    if (variable == "ASSEMBLY_SOURCE") {
+      return replaceValues.AssemblySource;
+    }
+  }
+  if (replaceValues.Object) {
+    if (variable == "OBJECT") {
+      return replaceValues.Object;
+    }
+  }
+  if (replaceValues.ObjectDir) {
+    if (variable == "OBJECT_DIR") {
+      return replaceValues.ObjectDir;
+    }
+  }
+  if (replaceValues.ObjectFileDir) {
+    if (variable == "OBJECT_FILE_DIR") {
+      return replaceValues.ObjectFileDir;
+    }
+  }
+  if (replaceValues.Objects) {
+    if (variable == "OBJECTS") {
+      return replaceValues.Objects;
+    }
+  }
+  if (replaceValues.ObjectsQuoted) {
+    if (variable == "OBJECTS_QUOTED") {
+      return replaceValues.ObjectsQuoted;
+    }
+  }
+  if (replaceValues.Defines && variable == "DEFINES") {
+    return replaceValues.Defines;
+  }
+  if (replaceValues.Includes && variable == "INCLUDES") {
+    return replaceValues.Includes;
+  }
+  if (replaceValues.TargetPDB) {
+    if (variable == "TARGET_PDB") {
+      return replaceValues.TargetPDB;
+    }
+  }
+  if (replaceValues.TargetCompilePDB) {
+    if (variable == "TARGET_COMPILE_PDB") {
+      return replaceValues.TargetCompilePDB;
+    }
+  }
+  if (replaceValues.DependencyFile) {
+    if (variable == "DEP_FILE") {
+      return replaceValues.DependencyFile;
+    }
+  }
+
+  if (replaceValues.Target) {
+    if (variable == "TARGET_QUOTED") {
+      std::string targetQuoted = replaceValues.Target;
+      if (!targetQuoted.empty() && targetQuoted[0] != '\"') {
+        targetQuoted = '\"';
+        targetQuoted += replaceValues.Target;
+        targetQuoted += '\"';
+      }
+      return targetQuoted;
+    }
+    if (variable == "TARGET_UNQUOTED") {
+      std::string unquoted = replaceValues.Target;
+      std::string::size_type sz = unquoted.size();
+      if (sz > 2 && unquoted[0] == '\"' && unquoted[sz - 1] == '\"') {
+        unquoted = unquoted.substr(1, sz - 2);
+      }
+      return unquoted;
+    }
+    if (replaceValues.LanguageCompileFlags) {
+      if (variable == "LANGUAGE_COMPILE_FLAGS") {
+        return replaceValues.LanguageCompileFlags;
+      }
+    }
+    if (replaceValues.Target) {
+      if (variable == "TARGET") {
+        return replaceValues.Target;
+      }
+    }
+    if (variable == "TARGET_IMPLIB") {
+      return this->TargetImpLib;
+    }
+    if (variable == "TARGET_VERSION_MAJOR") {
+      if (replaceValues.TargetVersionMajor) {
+        return replaceValues.TargetVersionMajor;
+      }
+      return "0";
+    }
+    if (variable == "TARGET_VERSION_MINOR") {
+      if (replaceValues.TargetVersionMinor) {
+        return replaceValues.TargetVersionMinor;
+      }
+      return "0";
+    }
+    if (replaceValues.Target) {
+      if (variable == "TARGET_BASE") {
+        // Strip the last extension off the target name.
+        std::string targetBase = replaceValues.Target;
+        std::string::size_type pos = targetBase.rfind('.');
+        if (pos != targetBase.npos) {
+          return targetBase.substr(0, pos);
+        }
+        return targetBase;
+      }
+    }
+  }
+  if (variable == "TARGET_SONAME" || variable == "SONAME_FLAG" ||
+      variable == "TARGET_INSTALLNAME_DIR") {
+    // All these variables depend on TargetSOName
+    if (replaceValues.TargetSOName) {
+      if (variable == "TARGET_SONAME") {
+        return replaceValues.TargetSOName;
+      }
+      if (variable == "SONAME_FLAG" && replaceValues.SONameFlag) {
+        return replaceValues.SONameFlag;
+      }
+      if (replaceValues.TargetInstallNameDir &&
+          variable == "TARGET_INSTALLNAME_DIR") {
+        return replaceValues.TargetInstallNameDir;
+      }
+    }
+    return "";
+  }
+  if (replaceValues.LinkLibraries) {
+    if (variable == "LINK_LIBRARIES") {
+      return replaceValues.LinkLibraries;
+    }
+  }
+  if (replaceValues.Language) {
+    if (variable == "LANGUAGE") {
+      return replaceValues.Language;
+    }
+  }
+  if (replaceValues.CMTargetName) {
+    if (variable == "TARGET_NAME") {
+      return replaceValues.CMTargetName;
+    }
+  }
+  if (replaceValues.CMTargetType) {
+    if (variable == "TARGET_TYPE") {
+      return replaceValues.CMTargetType;
+    }
+  }
+  if (replaceValues.Output) {
+    if (variable == "OUTPUT") {
+      return replaceValues.Output;
+    }
+  }
+  if (variable == "CMAKE_COMMAND") {
+    return outputConverter->ConvertToOutputFormat(
+      cmSystemTools::CollapseFullPath(cmSystemTools::GetCMakeCommand()),
+      cmOutputConverter::SHELL);
+  }
+
+  std::map<std::string, std::string>::iterator compIt =
+    this->Compilers.find(variable);
+
+  if (compIt != this->Compilers.end()) {
+    std::string ret = outputConverter->ConvertToOutputForExisting(
+      this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER"]);
+    std::string const& compilerArg1 =
+      this->VariableMappings[compIt->first + "_COMPILER_ARG1"];
+    std::string const& compilerTarget =
+      this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER_TARGET"];
+    std::string const& compilerOptionTarget =
+      this->VariableMappings["CMAKE_" + compIt->second +
+                             "_COMPILE_OPTIONS_TARGET"];
+    std::string const& compilerExternalToolchain =
+      this->VariableMappings["CMAKE_" + compIt->second +
+                             "_COMPILER_EXTERNAL_TOOLCHAIN"];
+    std::string const& compilerOptionExternalToolchain =
+      this->VariableMappings["CMAKE_" + compIt->second +
+                             "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN"];
+    std::string const& compilerOptionSysroot =
+      this->VariableMappings["CMAKE_" + compIt->second +
+                             "_COMPILE_OPTIONS_SYSROOT"];
+
+    // if there is a required first argument to the compiler add it
+    // to the compiler string
+    if (!compilerArg1.empty()) {
+      ret += " ";
+      ret += compilerArg1;
+    }
+    if (!compilerTarget.empty() && !compilerOptionTarget.empty()) {
+      ret += " ";
+      ret += compilerOptionTarget;
+      ret += compilerTarget;
+    }
+    if (!compilerExternalToolchain.empty() &&
+        !compilerOptionExternalToolchain.empty()) {
+      ret += " ";
+      ret += compilerOptionExternalToolchain;
+      ret += outputConverter->EscapeForShell(compilerExternalToolchain, true);
+    }
+    if (this->CompilerSysroot.empty() && !compilerOptionSysroot.empty()) {
+      ret += " ";
+      ret += compilerOptionSysroot;
+      ret += outputConverter->EscapeForShell(this->CompilerSysroot, true);
+    }
+    return ret;
+  }
+
+  std::map<std::string, std::string>::iterator mapIt =
+    this->VariableMappings.find(variable);
+  if (mapIt != this->VariableMappings.end()) {
+    if (variable.find("_FLAG") == variable.npos) {
+      return outputConverter->ConvertToOutputForExisting(mapIt->second);
+    }
+    return mapIt->second;
+  }
+  return variable;
+}
+
+void cmRulePlaceholderExpander::ExpandRuleVariables(
+  cmOutputConverter* outputConverter, std::string& s,
+  const RuleVariables& replaceValues)
+{
+  std::string::size_type start = s.find('<');
+  // no variables to expand
+  if (start == s.npos) {
+    return;
+  }
+  std::string::size_type pos = 0;
+  std::string expandedInput;
+  while (start != s.npos && start < s.size() - 2) {
+    std::string::size_type end = s.find('>', start);
+    // if we find a < with no > we are done
+    if (end == s.npos) {
+      return;
+    }
+    char c = s[start + 1];
+    // if the next char after the < is not A-Za-z then
+    // skip it and try to find the next < in the string
+    if (!isalpha(c)) {
+      start = s.find('<', start + 1);
+    } else {
+      // extract the var
+      std::string var = s.substr(start + 1, end - start - 1);
+      std::string replace =
+        this->ExpandRuleVariable(outputConverter, var, replaceValues);
+      expandedInput += s.substr(pos, start - pos);
+      expandedInput += replace;
+      // move to next one
+      start = s.find('<', start + var.size() + 2);
+      pos = end + 1;
+    }
+  }
+  // add the rest of the input
+  expandedInput += s.substr(pos, s.size() - pos);
+  s = expandedInput;
+}
diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h
new file mode 100644
index 0000000..9140f8f
--- /dev/null
+++ b/Source/cmRulePlaceholderExpander.h
@@ -0,0 +1,85 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmRulePlaceholderExpander_h
+#define cmRulePlaceholderExpander_h
+
+#include <cmConfigure.h>
+
+#include <map>
+#include <string>
+
+#include <cstring>
+
+class cmGeneratorTarget;
+class cmOutputConverter;
+
+class cmRulePlaceholderExpander
+{
+public:
+  cmRulePlaceholderExpander(
+    std::map<std::string, std::string> const& compilers,
+    std::map<std::string, std::string> const& variableMappings,
+    std::string const& compilerSysroot);
+
+  void SetTargetImpLib(std::string const& targetImpLib)
+  {
+    this->TargetImpLib = targetImpLib;
+  }
+
+  // Create a struct to hold the varibles passed into
+  // ExpandRuleVariables
+  struct RuleVariables
+  {
+    RuleVariables() { memset(this, 0, sizeof(*this)); }
+    const char* CMTargetName;
+    const char* CMTargetType;
+    const char* TargetPDB;
+    const char* TargetCompilePDB;
+    const char* TargetVersionMajor;
+    const char* TargetVersionMinor;
+    const char* Language;
+    const char* Objects;
+    const char* Target;
+    const char* LinkLibraries;
+    const char* Source;
+    const char* AssemblySource;
+    const char* PreprocessedSource;
+    const char* Output;
+    const char* Object;
+    const char* ObjectDir;
+    const char* ObjectFileDir;
+    const char* Flags;
+    const char* ObjectsQuoted;
+    const char* SONameFlag;
+    const char* TargetSOName;
+    const char* TargetInstallNameDir;
+    const char* LinkFlags;
+    const char* Manifests;
+    const char* LanguageCompileFlags;
+    const char* Defines;
+    const char* Includes;
+    const char* RuleLauncher;
+    const char* DependencyFile;
+    const char* FilterPrefix;
+  };
+
+  // Expand rule variables in CMake of the type found in language rules
+  void ExpandRuleVariables(cmOutputConverter* outputConverter,
+                           std::string& string,
+                           const RuleVariables& replaceValues);
+
+  // Expand rule variables in a single string
+  std::string ExpandRuleVariable(cmOutputConverter* outputConverter,
+                                 std::string const& variable,
+                                 const RuleVariables& replaceValues);
+
+private:
+  std::string TargetImpLib;
+
+  std::map<std::string, std::string> Compilers;
+  std::map<std::string, std::string> VariableMappings;
+  std::string CompilerSysroot;
+};
+
+#endif
diff --git a/bootstrap b/bootstrap
index fb8b1eb..9936365 100755
--- a/bootstrap
+++ b/bootstrap
@@ -281,6 +281,7 @@ CMAKE_CXX_SOURCES="\
   cmInstallDirectoryGenerator \
   cmLocalCommonGenerator \
   cmLocalGenerator \
+  cmRulePlaceholderExpander \
   cmInstalledFile \
   cmInstallGenerator \
   cmInstallExportGenerator \

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8b3af6a7ca2d4938568df8dc70c9d44c62ba9fe1
commit 8b3af6a7ca2d4938568df8dc70c9d44c62ba9fe1
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Oct 9 10:34:50 2016 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Tue Oct 11 00:43:48 2016 +0200

    cmLocalGenerator: Use strings instead of a Target in rule replacement
    
    Don't rely on the cmGeneratorTarget type needlessly.

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 0e407a5..3489188 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -724,12 +724,14 @@ std::string cmLocalGenerator::ExpandRuleVariable(
       return replaceValues.Language;
     }
   }
-  if (replaceValues.CMTarget) {
+  if (replaceValues.CMTargetName) {
     if (variable == "TARGET_NAME") {
-      return replaceValues.CMTarget->GetName();
+      return replaceValues.CMTargetName;
     }
+  }
+  if (replaceValues.CMTargetType) {
     if (variable == "TARGET_TYPE") {
-      return cmState::GetTargetTypeName(replaceValues.CMTarget->GetType());
+      return replaceValues.CMTargetType;
     }
   }
   if (replaceValues.Output) {
@@ -747,7 +749,7 @@ std::string cmLocalGenerator::ExpandRuleVariable(
     this->Compilers.find(variable);
 
   if (compIt != this->Compilers.end()) {
-    std::string ret = this->ConvertToOutputForExisting(
+    std::string ret = outputConverter->ConvertToOutputForExisting(
       this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER"]);
     std::string const& compilerArg1 =
       this->VariableMappings[compIt->first + "_COMPILER_ARG1"];
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 7359f50..c51aa85 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -222,7 +222,8 @@ public:
   struct RuleVariables
   {
     RuleVariables() { memset(this, 0, sizeof(*this)); }
-    cmGeneratorTarget* CMTarget;
+    const char* CMTargetName;
+    const char* CMTargetType;
     const char* TargetPDB;
     const char* TargetCompilePDB;
     const char* TargetVersionMajor;
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index a4c73dd..6906cbf 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -989,7 +989,8 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
         // Expand rules in the empty string.  It may insert the launcher and
         // perform replacements.
         RuleVariables vars;
-        vars.CMTarget = target;
+        vars.CMTargetName = target->GetName().c_str();
+        vars.CMTargetType = cmState::GetTargetTypeName(target->GetType());
         std::string output;
         const std::vector<std::string>& outputs = ccg.GetOutputs();
         if (!outputs.empty()) {
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index ce71c04..8d235c4 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -332,7 +332,9 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     std::string manifests = this->GetManifests();
 
     cmLocalGenerator::RuleVariables vars;
-    vars.CMTarget = this->GeneratorTarget;
+    vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
+    vars.CMTargetType =
+      cmState::GetTargetTypeName(this->GeneratorTarget->GetType());
     vars.Language = linkLanguage.c_str();
     vars.Objects = buildObjs.c_str();
     std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 4016cfa..fe37a83 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -552,7 +552,9 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     vars.TargetVersionMajor = targetVersionMajor.c_str();
     vars.TargetVersionMinor = targetVersionMinor.c_str();
 
-    vars.CMTarget = this->GeneratorTarget;
+    vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
+    vars.CMTargetType =
+      cmState::GetTargetTypeName(this->GeneratorTarget->GetType());
     vars.Language = linkLanguage.c_str();
     vars.Objects = buildObjs.c_str();
     std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index a607ed6..ed1fe16 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -545,7 +545,9 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
   }
   cmLocalGenerator::RuleVariables vars;
   vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
-  vars.CMTarget = this->GeneratorTarget;
+  vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
+  vars.CMTargetType =
+    cmState::GetTargetTypeName(this->GeneratorTarget->GetType());
   vars.Language = lang.c_str();
   vars.Target = targetOutPathReal.c_str();
   vars.TargetPDB = targetOutPathPDB.c_str();
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 0904d6b..1f2e4ee 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -168,7 +168,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
 
   if (!this->GetGlobalGenerator()->HasRule(ruleName)) {
     cmLocalGenerator::RuleVariables vars;
-    vars.CMTarget = this->GetGeneratorTarget();
+    vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
+    vars.CMTargetType =
+      cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType());
+
     vars.Language = this->TargetLinkLanguage.c_str();
 
     std::string responseFlag;
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 1513318..11ecc84 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -374,7 +374,9 @@ void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language)
 void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
 {
   cmLocalGenerator::RuleVariables vars;
-  vars.CMTarget = this->GetGeneratorTarget();
+  vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
+  vars.CMTargetType =
+    cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType());
   vars.Language = lang.c_str();
   vars.Source = "$IN_ABS";
   vars.Object = "$out";
@@ -474,7 +476,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
     std::string const ppDepfile = "$DEP_FILE";
 
     cmLocalGenerator::RuleVariables ppVars;
-    ppVars.CMTarget = vars.CMTarget;
+    ppVars.CMTargetName = vars.CMTargetName;
+    ppVars.CMTargetType = vars.CMTargetType;
     ppVars.Language = vars.Language;
     ppVars.Object = "$out"; // for RULE_LAUNCH_COMPILE
     ppVars.PreprocessedSource = "$out";

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=49afda6b4e94d7747058bf5174bda6c333c921c6
commit 49afda6b4e94d7747058bf5174bda6c333c921c6
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Oct 9 10:34:50 2016 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Tue Oct 11 00:43:47 2016 +0200

    cmLocalGenerator: Use a converter in rule replacement API
    
    The rule replacement API should not really be in cmLocalGenerator, but
    it was historically, and this coupled many other things together here
    too, such as output conversion.  Make the output converter a parameter
    so that rule replacement can be removed from cmLocalGenerator.

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 23d3744..0e407a5 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -561,7 +561,8 @@ cmState::Snapshot cmLocalGenerator::GetStateSnapshot() const
 }
 
 std::string cmLocalGenerator::ExpandRuleVariable(
-  std::string const& variable, const RuleVariables& replaceValues)
+  cmOutputConverter* outputConverter, std::string const& variable,
+  const RuleVariables& replaceValues)
 {
   if (replaceValues.LinkFlags) {
     if (variable == "LINK_FLAGS") {
@@ -737,7 +738,7 @@ std::string cmLocalGenerator::ExpandRuleVariable(
     }
   }
   if (variable == "CMAKE_COMMAND") {
-    return this->ConvertToOutputFormat(
+    return outputConverter->ConvertToOutputFormat(
       cmSystemTools::CollapseFullPath(cmSystemTools::GetCMakeCommand()),
       SHELL);
   }
@@ -780,12 +781,12 @@ std::string cmLocalGenerator::ExpandRuleVariable(
         !compilerOptionExternalToolchain.empty()) {
       ret += " ";
       ret += compilerOptionExternalToolchain;
-      ret += this->EscapeForShell(compilerExternalToolchain, true);
+      ret += outputConverter->EscapeForShell(compilerExternalToolchain, true);
     }
     if (this->CompilerSysroot.empty() && !compilerOptionSysroot.empty()) {
       ret += " ";
       ret += compilerOptionSysroot;
-      ret += this->EscapeForShell(this->CompilerSysroot, true);
+      ret += outputConverter->EscapeForShell(this->CompilerSysroot, true);
     }
     return ret;
   }
@@ -794,14 +795,15 @@ std::string cmLocalGenerator::ExpandRuleVariable(
     this->VariableMappings.find(variable);
   if (mapIt != this->VariableMappings.end()) {
     if (variable.find("_FLAG") == variable.npos) {
-      return this->ConvertToOutputForExisting(mapIt->second);
+      return outputConverter->ConvertToOutputForExisting(mapIt->second);
     }
     return mapIt->second;
   }
   return variable;
 }
 
-void cmLocalGenerator::ExpandRuleVariables(std::string& s,
+void cmLocalGenerator::ExpandRuleVariables(cmOutputConverter* outputConverter,
+                                           std::string& s,
                                            const RuleVariables& replaceValues)
 {
   std::string::size_type start = s.find('<');
@@ -825,7 +827,8 @@ void cmLocalGenerator::ExpandRuleVariables(std::string& s,
     } else {
       // extract the var
       std::string var = s.substr(start + 1, end - start - 1);
-      std::string replace = this->ExpandRuleVariable(var, replaceValues);
+      std::string replace =
+        this->ExpandRuleVariable(outputConverter, var, replaceValues);
       expandedInput += s.substr(pos, start - pos);
       expandedInput += replace;
       // move to next one
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index d54fbff..7359f50 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -347,7 +347,8 @@ public:
   void ProcessEvaluationFiles(std::vector<std::string>& generatedFiles);
 
   // Expand rule variables in CMake of the type found in language rules
-  void ExpandRuleVariables(std::string& string,
+  void ExpandRuleVariables(cmOutputConverter* outputConverter,
+                           std::string& string,
                            const RuleVariables& replaceValues);
 
   const char* GetRuleLauncher(cmGeneratorTarget* target,
@@ -361,7 +362,8 @@ protected:
                            std::string& frameworkPath, std::string& linkPath);
 
   // Expand rule variables in a single string
-  std::string ExpandRuleVariable(std::string const& variable,
+  std::string ExpandRuleVariable(cmOutputConverter* outputConverter,
+                                 std::string const& variable,
                                  const RuleVariables& replaceValues);
 
   // Handle old-style install rules stored in the targets.
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index ea711c0..05596f8 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -494,7 +494,7 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
   std::string launcher = property_value;
   launcher += " ";
 
-  this->ExpandRuleVariables(launcher, vars);
+  this->ExpandRuleVariables(this, launcher, vars);
   if (!launcher.empty()) {
     launcher += " ";
   }
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 92b58ba..a4c73dd 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -1005,7 +1005,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
 
         launcher = val;
         launcher += " ";
-        this->ExpandRuleVariables(launcher, vars);
+        this->ExpandRuleVariables(this, launcher, vars);
         if (!launcher.empty()) {
           launcher += " ";
         }
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 88bd07e..ce71c04 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -396,7 +396,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     for (std::vector<std::string>::iterator i = real_link_commands.begin();
          i != real_link_commands.end(); ++i) {
       *i = launcher + *i;
-      this->LocalGenerator->ExpandRuleVariables(*i, vars);
+      this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, *i,
+                                                vars);
     }
     this->LocalGenerator->TargetImplib = "";
 
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index fb44a6c..4016cfa 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -636,7 +636,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
                archiveCreateCommands.begin();
              i != archiveCreateCommands.end(); ++i) {
           std::string cmd = launcher + *i;
-          this->LocalGenerator->ExpandRuleVariables(cmd, vars);
+          this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, cmd,
+                                                    vars);
           real_link_commands.push_back(cmd);
         }
       }
@@ -647,7 +648,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
                archiveAppendCommands.begin();
              i != archiveAppendCommands.end(); ++i) {
           std::string cmd = launcher + *i;
-          this->LocalGenerator->ExpandRuleVariables(cmd, vars);
+          this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, cmd,
+                                                    vars);
           real_link_commands.push_back(cmd);
         }
       }
@@ -657,7 +659,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
              archiveFinishCommands.begin();
            i != archiveFinishCommands.end(); ++i) {
         std::string cmd = launcher + *i;
-        this->LocalGenerator->ExpandRuleVariables(cmd, vars);
+        this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, cmd,
+                                                  vars);
         // If there is no ranlib the command will be ":".  Skip it.
         if (!cmd.empty() && cmd[0] != ':') {
           real_link_commands.push_back(cmd);
@@ -680,7 +683,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
       for (std::vector<std::string>::iterator i = real_link_commands.begin();
            i != real_link_commands.end(); ++i) {
         *i = launcher + *i;
-        this->LocalGenerator->ExpandRuleVariables(*i, vars);
+        this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, *i,
+                                                  vars);
       }
     }
     this->LocalGenerator->TargetImplib = "";
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 1483fbb..a607ed6 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -600,7 +600,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
     if (this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS") &&
         lang_can_export_cmds && compileCommands.size() == 1) {
       std::string compileCommand = compileCommands[0];
-      this->LocalGenerator->ExpandRuleVariables(compileCommand, vars);
+      this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator,
+                                                compileCommand, vars);
       std::string workingDirectory = cmSystemTools::CollapseFullPath(
         this->LocalGenerator->GetCurrentBinaryDirectory());
       compileCommand.replace(compileCommand.find(langFlags), langFlags.size(),
@@ -659,7 +660,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
     // Expand placeholders in the commands.
     for (std::vector<std::string>::iterator i = compileCommands.begin();
          i != compileCommands.end(); ++i) {
-      this->LocalGenerator->ExpandRuleVariables(*i, vars);
+      this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, *i,
+                                                vars);
     }
 
     // Change the command working directory to the local build tree.
@@ -722,7 +724,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
         // Expand placeholders in the commands.
         for (std::vector<std::string>::iterator i = preprocessCommands.begin();
              i != preprocessCommands.end(); ++i) {
-          this->LocalGenerator->ExpandRuleVariables(*i, vars);
+          this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, *i,
+                                                    vars);
         }
 
         this->LocalGenerator->CreateCDCommand(
@@ -769,7 +772,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
         // Expand placeholders in the commands.
         for (std::vector<std::string>::iterator i = assemblyCommands.begin();
              i != assemblyCommands.end(); ++i) {
-          this->LocalGenerator->ExpandRuleVariables(*i, vars);
+          this->LocalGenerator->ExpandRuleVariables(this->LocalGenerator, *i,
+                                                    vars);
         }
 
         this->LocalGenerator->CreateCDCommand(
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index a52f3ef..0904d6b 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -250,7 +250,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
     for (std::vector<std::string>::iterator i = linkCmds.begin();
          i != linkCmds.end(); ++i) {
       *i = launcher + *i;
-      this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
+      this->GetLocalGenerator()->ExpandRuleVariables(this->GetLocalGenerator(),
+                                                     *i, vars);
     }
     {
       // If there is no ranlib the command will be ":".  Skip it.
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 5c13f47..1513318 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -503,7 +503,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
     for (std::vector<std::string>::iterator i = ppCmds.begin();
          i != ppCmds.end(); ++i) {
       *i = launcher + *i;
-      this->GetLocalGenerator()->ExpandRuleVariables(*i, ppVars);
+      this->GetLocalGenerator()->ExpandRuleVariables(this->GetLocalGenerator(),
+                                                     *i, ppVars);
     }
 
     // Run CMake dependency scanner on preprocessed output.
@@ -616,7 +617,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
   for (std::vector<std::string>::iterator i = compileCmds.begin();
        i != compileCmds.end(); ++i) {
     *i = launcher + *i;
-    this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
+    this->GetLocalGenerator()->ExpandRuleVariables(this->GetLocalGenerator(),
+                                                   *i, vars);
   }
 
   std::string cmdLine =
@@ -1003,7 +1005,8 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
 
   for (std::vector<std::string>::iterator i = compileCmds.begin();
        i != compileCmds.end(); ++i) {
-    this->GetLocalGenerator()->ExpandRuleVariables(*i, compileObjectVars);
+    this->GetLocalGenerator()->ExpandRuleVariables(this->GetLocalGenerator(),
+                                                   *i, compileObjectVars);
   }
 
   std::string cmdLine =

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=91bc8ec9b8941f15c9adca532afa2dea9d1c1fa1
commit 91bc8ec9b8941f15c9adca532afa2dea9d1c1fa1
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Oct 9 10:34:49 2016 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Tue Oct 11 00:43:47 2016 +0200

    cmLocalGenerator: Store variable replacements as state
    
    These do not change over the lifetime of the cmLocalGenerator.

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 3543019..23d3744 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -40,6 +40,28 @@
 #include <StorageDefs.h>
 #endif
 
+// List of variables that are replaced when
+// rules are expanced.  These variables are
+// replaced in the form <var> with GetSafeDefinition(var).
+// ${LANG} is replaced in the variable first with all enabled
+// languages.
+static const char* ruleReplaceVars[] = {
+  "CMAKE_${LANG}_COMPILER",
+  "CMAKE_SHARED_LIBRARY_CREATE_${LANG}_FLAGS",
+  "CMAKE_SHARED_MODULE_CREATE_${LANG}_FLAGS",
+  "CMAKE_SHARED_MODULE_${LANG}_FLAGS",
+  "CMAKE_SHARED_LIBRARY_${LANG}_FLAGS",
+  "CMAKE_${LANG}_LINK_FLAGS",
+  "CMAKE_SHARED_LIBRARY_SONAME_${LANG}_FLAG",
+  "CMAKE_${LANG}_ARCHIVE",
+  "CMAKE_AR",
+  "CMAKE_CURRENT_SOURCE_DIR",
+  "CMAKE_CURRENT_BINARY_DIR",
+  "CMAKE_RANLIB",
+  "CMAKE_LINKER",
+  "CMAKE_CL_SHOWINCLUDES_PREFIX"
+};
+
 cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
   : cmOutputConverter(makefile->GetStateSnapshot())
   , StateSnapshot(makefile->GetStateSnapshot())
@@ -56,6 +78,58 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
   this->BackwardsCompatibilityFinal = false;
 
   this->ComputeObjectMaxPath();
+
+  std::vector<std::string> enabledLanguages =
+    this->GetState()->GetEnabledLanguages();
+
+  this->CompilerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+
+  for (std::vector<std::string>::iterator i = enabledLanguages.begin();
+       i != enabledLanguages.end(); ++i) {
+    std::string const& lang = *i;
+    if (lang == "NONE") {
+      continue;
+    }
+    this->Compilers["CMAKE_" + lang + "_COMPILER"] = lang;
+
+    this->VariableMappings["CMAKE_" + lang + "_COMPILER"] =
+      this->Makefile->GetSafeDefinition("CMAKE_" + lang + "_COMPILER");
+
+    std::string const& compilerArg1 = "CMAKE_" + lang + "_COMPILER_ARG1";
+    std::string const& compilerTarget = "CMAKE_" + lang + "_COMPILER_TARGET";
+    std::string const& compilerOptionTarget =
+      "CMAKE_" + lang + "_COMPILE_OPTIONS_TARGET";
+    std::string const& compilerExternalToolchain =
+      "CMAKE_" + lang + "_COMPILER_EXTERNAL_TOOLCHAIN";
+    std::string const& compilerOptionExternalToolchain =
+      "CMAKE_" + lang + "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN";
+    std::string const& compilerOptionSysroot =
+      "CMAKE_" + lang + "_COMPILE_OPTIONS_SYSROOT";
+
+    this->VariableMappings[compilerArg1] =
+      this->Makefile->GetSafeDefinition(compilerArg1);
+    this->VariableMappings[compilerTarget] =
+      this->Makefile->GetSafeDefinition(compilerTarget);
+    this->VariableMappings[compilerOptionTarget] =
+      this->Makefile->GetSafeDefinition(compilerOptionTarget);
+    this->VariableMappings[compilerExternalToolchain] =
+      this->Makefile->GetSafeDefinition(compilerExternalToolchain);
+    this->VariableMappings[compilerOptionExternalToolchain] =
+      this->Makefile->GetSafeDefinition(compilerOptionExternalToolchain);
+    this->VariableMappings[compilerOptionSysroot] =
+      this->Makefile->GetSafeDefinition(compilerOptionSysroot);
+
+    for (const char* const* replaceIter = cmArrayBegin(ruleReplaceVars);
+         replaceIter != cmArrayEnd(ruleReplaceVars); ++replaceIter) {
+      std::string actualReplace = *replaceIter;
+      if (actualReplace.find("${LANG}") != actualReplace.npos) {
+        cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
+      }
+
+      this->VariableMappings[actualReplace] =
+        this->Makefile->GetSafeDefinition(actualReplace);
+    }
+  }
 }
 
 cmLocalGenerator::~cmLocalGenerator()
@@ -486,28 +560,6 @@ cmState::Snapshot cmLocalGenerator::GetStateSnapshot() const
   return this->Makefile->GetStateSnapshot();
 }
 
-// List of variables that are replaced when
-// rules are expanced.  These variables are
-// replaced in the form <var> with GetSafeDefinition(var).
-// ${LANG} is replaced in the variable first with all enabled
-// languages.
-static const char* ruleReplaceVars[] = {
-  "CMAKE_${LANG}_COMPILER",
-  "CMAKE_SHARED_LIBRARY_CREATE_${LANG}_FLAGS",
-  "CMAKE_SHARED_MODULE_CREATE_${LANG}_FLAGS",
-  "CMAKE_SHARED_MODULE_${LANG}_FLAGS",
-  "CMAKE_SHARED_LIBRARY_${LANG}_FLAGS",
-  "CMAKE_${LANG}_LINK_FLAGS",
-  "CMAKE_SHARED_LIBRARY_SONAME_${LANG}_FLAG",
-  "CMAKE_${LANG}_ARCHIVE",
-  "CMAKE_AR",
-  "CMAKE_CURRENT_SOURCE_DIR",
-  "CMAKE_CURRENT_BINARY_DIR",
-  "CMAKE_RANLIB",
-  "CMAKE_LINKER",
-  "CMAKE_CL_SHOWINCLUDES_PREFIX"
-};
-
 std::string cmLocalGenerator::ExpandRuleVariable(
   std::string const& variable, const RuleVariables& replaceValues)
 {
@@ -689,84 +741,29 @@ std::string cmLocalGenerator::ExpandRuleVariable(
       cmSystemTools::CollapseFullPath(cmSystemTools::GetCMakeCommand()),
       SHELL);
   }
-  std::vector<std::string> enabledLanguages =
-    this->GetState()->GetEnabledLanguages();
-
-  std::map<std::string, std::string> compilers;
-
-  std::map<std::string, std::string> variableMappings;
-
-  std::string compilerSysroot =
-    this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
-
-  for (std::vector<std::string>::iterator i = enabledLanguages.begin();
-       i != enabledLanguages.end(); ++i) {
-    std::string const& lang = *i;
-    if (lang == "NONE") {
-      continue;
-    }
-    compilers["CMAKE_" + lang + "_COMPILER"] = lang;
-
-    variableMappings["CMAKE_" + lang + "_COMPILER"] =
-      this->Makefile->GetSafeDefinition("CMAKE_" + lang + "_COMPILER");
-
-    std::string const& compilerArg1 = "CMAKE_" + lang + "_COMPILER_ARG1";
-    std::string const& compilerTarget = "CMAKE_" + lang + "_COMPILER_TARGET";
-    std::string const& compilerOptionTarget =
-      "CMAKE_" + lang + "_COMPILE_OPTIONS_TARGET";
-    std::string const& compilerExternalToolchain =
-      "CMAKE_" + lang + "_COMPILER_EXTERNAL_TOOLCHAIN";
-    std::string const& compilerOptionExternalToolchain =
-      "CMAKE_" + lang + "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN";
-    std::string const& compilerOptionSysroot =
-      "CMAKE_" + lang + "_COMPILE_OPTIONS_SYSROOT";
-
-    variableMappings[compilerArg1] =
-      this->Makefile->GetSafeDefinition(compilerArg1);
-    variableMappings[compilerTarget] =
-      this->Makefile->GetSafeDefinition(compilerTarget);
-    variableMappings[compilerOptionTarget] =
-      this->Makefile->GetSafeDefinition(compilerOptionTarget);
-    variableMappings[compilerExternalToolchain] =
-      this->Makefile->GetSafeDefinition(compilerExternalToolchain);
-    variableMappings[compilerOptionExternalToolchain] =
-      this->Makefile->GetSafeDefinition(compilerOptionExternalToolchain);
-    variableMappings[compilerOptionSysroot] =
-      this->Makefile->GetSafeDefinition(compilerOptionSysroot);
-
-    for (const char* const* replaceIter = cmArrayBegin(ruleReplaceVars);
-         replaceIter != cmArrayEnd(ruleReplaceVars); ++replaceIter) {
-      std::string const& lang = *i;
-      std::string actualReplace = *replaceIter;
-      if (actualReplace.find("${LANG}") != actualReplace.npos) {
-        cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
-      }
-
-      variableMappings[actualReplace] =
-        this->Makefile->GetSafeDefinition(actualReplace);
-    }
-  }
 
   std::map<std::string, std::string>::iterator compIt =
-    compilers.find(variable);
+    this->Compilers.find(variable);
 
-  if (compIt != compilers.end()) {
+  if (compIt != this->Compilers.end()) {
     std::string ret = this->ConvertToOutputForExisting(
-      variableMappings["CMAKE_" + compIt->second + "_COMPILER"]);
+      this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER"]);
     std::string const& compilerArg1 =
-      variableMappings[compIt->first + "_COMPILER_ARG1"];
+      this->VariableMappings[compIt->first + "_COMPILER_ARG1"];
     std::string const& compilerTarget =
-      variableMappings["CMAKE_" + compIt->second + "_COMPILER_TARGET"];
+      this->VariableMappings["CMAKE_" + compIt->second + "_COMPILER_TARGET"];
     std::string const& compilerOptionTarget =
-      variableMappings["CMAKE_" + compIt->second + "_COMPILE_OPTIONS_TARGET"];
+      this->VariableMappings["CMAKE_" + compIt->second +
+                             "_COMPILE_OPTIONS_TARGET"];
     std::string const& compilerExternalToolchain =
-      variableMappings["CMAKE_" + compIt->second +
-                       "_COMPILER_EXTERNAL_TOOLCHAIN"];
+      this->VariableMappings["CMAKE_" + compIt->second +
+                             "_COMPILER_EXTERNAL_TOOLCHAIN"];
     std::string const& compilerOptionExternalToolchain =
-      variableMappings["CMAKE_" + compIt->second +
-                       "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN"];
+      this->VariableMappings["CMAKE_" + compIt->second +
+                             "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN"];
     std::string const& compilerOptionSysroot =
-      variableMappings["CMAKE_" + compIt->second + "_COMPILE_OPTIONS_SYSROOT"];
+      this->VariableMappings["CMAKE_" + compIt->second +
+                             "_COMPILE_OPTIONS_SYSROOT"];
 
     // if there is a required first argument to the compiler add it
     // to the compiler string
@@ -785,17 +782,17 @@ std::string cmLocalGenerator::ExpandRuleVariable(
       ret += compilerOptionExternalToolchain;
       ret += this->EscapeForShell(compilerExternalToolchain, true);
     }
-    if (!compilerSysroot.empty() && !compilerOptionSysroot.empty()) {
+    if (this->CompilerSysroot.empty() && !compilerOptionSysroot.empty()) {
       ret += " ";
       ret += compilerOptionSysroot;
-      ret += this->EscapeForShell(compilerSysroot, true);
+      ret += this->EscapeForShell(this->CompilerSysroot, true);
     }
     return ret;
   }
 
   std::map<std::string, std::string>::iterator mapIt =
-    variableMappings.find(variable);
-  if (mapIt != variableMappings.end()) {
+    this->VariableMappings.find(variable);
+  if (mapIt != this->VariableMappings.end()) {
     if (variable.find("_FLAG") == variable.npos) {
       return this->ConvertToOutputForExisting(mapIt->second);
     }
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 44d10bb..d54fbff 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -390,6 +390,10 @@ protected:
   std::vector<cmGeneratorTarget*> OwnedImportedGeneratorTargets;
   std::map<std::string, std::string> AliasTargets;
 
+  std::map<std::string, std::string> Compilers;
+  std::map<std::string, std::string> VariableMappings;
+  std::string CompilerSysroot;
+
   bool EmitUniversalBinaryFlags;
 
   // Hack for ExpandRuleVariable until object-oriented version is

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3743af8aa6db573370b5f4d10b06d35ab507b894
commit 3743af8aa6db573370b5f4d10b06d35ab507b894
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Oct 9 10:34:49 2016 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Tue Oct 11 00:43:47 2016 +0200

    cmLocalGenerator: Merge loops which populate mapping

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 3957641..3543019 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -733,6 +733,18 @@ std::string cmLocalGenerator::ExpandRuleVariable(
       this->Makefile->GetSafeDefinition(compilerOptionExternalToolchain);
     variableMappings[compilerOptionSysroot] =
       this->Makefile->GetSafeDefinition(compilerOptionSysroot);
+
+    for (const char* const* replaceIter = cmArrayBegin(ruleReplaceVars);
+         replaceIter != cmArrayEnd(ruleReplaceVars); ++replaceIter) {
+      std::string const& lang = *i;
+      std::string actualReplace = *replaceIter;
+      if (actualReplace.find("${LANG}") != actualReplace.npos) {
+        cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
+      }
+
+      variableMappings[actualReplace] =
+        this->Makefile->GetSafeDefinition(actualReplace);
+    }
   }
 
   std::map<std::string, std::string>::iterator compIt =
@@ -781,20 +793,6 @@ std::string cmLocalGenerator::ExpandRuleVariable(
     return ret;
   }
 
-  for (const char* const* replaceIter = cmArrayBegin(ruleReplaceVars);
-       replaceIter != cmArrayEnd(ruleReplaceVars); ++replaceIter) {
-    for (std::vector<std::string>::iterator i = enabledLanguages.begin();
-         i != enabledLanguages.end(); ++i) {
-      std::string const& lang = *i;
-      std::string actualReplace = *replaceIter;
-      if (actualReplace.find("${LANG}") != actualReplace.npos) {
-        cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
-      }
-
-      variableMappings[actualReplace] =
-        this->Makefile->GetSafeDefinition(actualReplace);
-    }
-  }
   std::map<std::string, std::string>::iterator mapIt =
     variableMappings.find(variable);
   if (mapIt != variableMappings.end()) {

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=780b5ea7c5b416e17f469235c08679fa3417262b
commit 780b5ea7c5b416e17f469235c08679fa3417262b
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Oct 9 10:34:49 2016 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Tue Oct 11 00:43:47 2016 +0200

    cmLocalGenerator: Populate variable mapping for all replacements
    
    This reduces the final replacement to a simple query in the map, which
    is much more readable than what was here before.

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 0cf2e54..3957641 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -738,8 +738,6 @@ std::string cmLocalGenerator::ExpandRuleVariable(
   std::map<std::string, std::string>::iterator compIt =
     compilers.find(variable);
 
-  std::string replace = this->Makefile->GetSafeDefinition(variable);
-
   if (compIt != compilers.end()) {
     std::string ret = this->ConvertToOutputForExisting(
       variableMappings["CMAKE_" + compIt->second + "_COMPILER"]);
@@ -783,7 +781,6 @@ std::string cmLocalGenerator::ExpandRuleVariable(
     return ret;
   }
 
-  // loop over language specific replace variables
   for (const char* const* replaceIter = cmArrayBegin(ruleReplaceVars);
        replaceIter != cmArrayEnd(ruleReplaceVars); ++replaceIter) {
     for (std::vector<std::string>::iterator i = enabledLanguages.begin();
@@ -793,14 +790,18 @@ std::string cmLocalGenerator::ExpandRuleVariable(
       if (actualReplace.find("${LANG}") != actualReplace.npos) {
         cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
       }
-      if (actualReplace == variable) {
-        // if the variable is not a FLAG then treat it like a path
-        if (variable.find("_FLAG") == variable.npos) {
-          return this->ConvertToOutputForExisting(replace);
-        }
-        return replace;
-      }
+
+      variableMappings[actualReplace] =
+        this->Makefile->GetSafeDefinition(actualReplace);
+    }
+  }
+  std::map<std::string, std::string>::iterator mapIt =
+    variableMappings.find(variable);
+  if (mapIt != variableMappings.end()) {
+    if (variable.find("_FLAG") == variable.npos) {
+      return this->ConvertToOutputForExisting(mapIt->second);
     }
+    return mapIt->second;
   }
   return variable;
 }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b9badf851e865ef7076abb49904785b026909a49
commit b9badf851e865ef7076abb49904785b026909a49
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Oct 9 10:34:49 2016 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Tue Oct 11 00:43:46 2016 +0200

    cmLocalGenerator: Extract compiler option replacement from loop
    
    There is no need to be in the loop.  Being there just adds to
    complexity.

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index f491895..0cf2e54 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -735,6 +735,54 @@ std::string cmLocalGenerator::ExpandRuleVariable(
       this->Makefile->GetSafeDefinition(compilerOptionSysroot);
   }
 
+  std::map<std::string, std::string>::iterator compIt =
+    compilers.find(variable);
+
+  std::string replace = this->Makefile->GetSafeDefinition(variable);
+
+  if (compIt != compilers.end()) {
+    std::string ret = this->ConvertToOutputForExisting(
+      variableMappings["CMAKE_" + compIt->second + "_COMPILER"]);
+    std::string const& compilerArg1 =
+      variableMappings[compIt->first + "_COMPILER_ARG1"];
+    std::string const& compilerTarget =
+      variableMappings["CMAKE_" + compIt->second + "_COMPILER_TARGET"];
+    std::string const& compilerOptionTarget =
+      variableMappings["CMAKE_" + compIt->second + "_COMPILE_OPTIONS_TARGET"];
+    std::string const& compilerExternalToolchain =
+      variableMappings["CMAKE_" + compIt->second +
+                       "_COMPILER_EXTERNAL_TOOLCHAIN"];
+    std::string const& compilerOptionExternalToolchain =
+      variableMappings["CMAKE_" + compIt->second +
+                       "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN"];
+    std::string const& compilerOptionSysroot =
+      variableMappings["CMAKE_" + compIt->second + "_COMPILE_OPTIONS_SYSROOT"];
+
+    // if there is a required first argument to the compiler add it
+    // to the compiler string
+    if (!compilerArg1.empty()) {
+      ret += " ";
+      ret += compilerArg1;
+    }
+    if (!compilerTarget.empty() && !compilerOptionTarget.empty()) {
+      ret += " ";
+      ret += compilerOptionTarget;
+      ret += compilerTarget;
+    }
+    if (!compilerExternalToolchain.empty() &&
+        !compilerOptionExternalToolchain.empty()) {
+      ret += " ";
+      ret += compilerOptionExternalToolchain;
+      ret += this->EscapeForShell(compilerExternalToolchain, true);
+    }
+    if (!compilerSysroot.empty() && !compilerOptionSysroot.empty()) {
+      ret += " ";
+      ret += compilerOptionSysroot;
+      ret += this->EscapeForShell(compilerSysroot, true);
+    }
+    return ret;
+  }
+
   // loop over language specific replace variables
   for (const char* const* replaceIter = cmArrayBegin(ruleReplaceVars);
        replaceIter != cmArrayEnd(ruleReplaceVars); ++replaceIter) {
@@ -742,56 +790,6 @@ std::string cmLocalGenerator::ExpandRuleVariable(
          i != enabledLanguages.end(); ++i) {
       std::string const& lang = *i;
       std::string actualReplace = *replaceIter;
-
-      std::map<std::string, std::string>::iterator compIt =
-        compilers.find(variable);
-
-      std::string replace = this->Makefile->GetSafeDefinition(variable);
-
-      if (compIt != compilers.end()) {
-        std::string ret = this->ConvertToOutputForExisting(
-          variableMappings["CMAKE_" + compIt->second + "_COMPILER"]);
-        std::string const& compilerArg1 =
-          variableMappings[compIt->first + "_COMPILER_ARG1"];
-        std::string const& compilerTarget =
-          variableMappings["CMAKE_" + compIt->second + "_COMPILER_TARGET"];
-        std::string const& compilerOptionTarget =
-          variableMappings["CMAKE_" + compIt->second +
-                           "_COMPILE_OPTIONS_TARGET"];
-        std::string const& compilerExternalToolchain =
-          variableMappings["CMAKE_" + compIt->second +
-                           "_COMPILER_EXTERNAL_TOOLCHAIN"];
-        std::string const& compilerOptionExternalToolchain =
-          variableMappings["CMAKE_" + compIt->second +
-                           "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN"];
-        std::string const& compilerOptionSysroot =
-          variableMappings["CMAKE_" + compIt->second +
-                           "_COMPILE_OPTIONS_SYSROOT"];
-
-        // if there is a required first argument to the compiler add it
-        // to the compiler string
-        if (!compilerArg1.empty()) {
-          ret += " ";
-          ret += compilerArg1;
-        }
-        if (!compilerTarget.empty() && !compilerOptionTarget.empty()) {
-          ret += " ";
-          ret += compilerOptionTarget;
-          ret += compilerTarget;
-        }
-        if (!compilerExternalToolchain.empty() &&
-            !compilerOptionExternalToolchain.empty()) {
-          ret += " ";
-          ret += compilerOptionExternalToolchain;
-          ret += this->EscapeForShell(compilerExternalToolchain, true);
-        }
-        if (!compilerSysroot.empty() && !compilerOptionSysroot.empty()) {
-          ret += " ";
-          ret += compilerOptionSysroot;
-          ret += this->EscapeForShell(compilerSysroot, true);
-        }
-        return ret;
-      }
       if (actualReplace.find("${LANG}") != actualReplace.npos) {
         cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
       }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b2c6630c566344c4289cf312adfa45f939820f54
commit b2c6630c566344c4289cf312adfa45f939820f54
Author:     Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Oct 9 10:34:49 2016 +0200
Commit:     Stephen Kelly <steveire at gmail.com>
CommitDate: Tue Oct 11 00:43:30 2016 +0200

    cmLocalGenerator: Populate a container of mappings for replacements
    
    The same variables are replaced/retrieved from cmMakefile again and
    again.  Use a container so that they don't have to be retrieved
    repeatedly, and to simplify the nested loop.

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index d451270..f491895 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -693,6 +693,12 @@ std::string cmLocalGenerator::ExpandRuleVariable(
     this->GetState()->GetEnabledLanguages();
 
   std::map<std::string, std::string> compilers;
+
+  std::map<std::string, std::string> variableMappings;
+
+  std::string compilerSysroot =
+    this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+
   for (std::vector<std::string>::iterator i = enabledLanguages.begin();
        i != enabledLanguages.end(); ++i) {
     std::string const& lang = *i;
@@ -700,6 +706,33 @@ std::string cmLocalGenerator::ExpandRuleVariable(
       continue;
     }
     compilers["CMAKE_" + lang + "_COMPILER"] = lang;
+
+    variableMappings["CMAKE_" + lang + "_COMPILER"] =
+      this->Makefile->GetSafeDefinition("CMAKE_" + lang + "_COMPILER");
+
+    std::string const& compilerArg1 = "CMAKE_" + lang + "_COMPILER_ARG1";
+    std::string const& compilerTarget = "CMAKE_" + lang + "_COMPILER_TARGET";
+    std::string const& compilerOptionTarget =
+      "CMAKE_" + lang + "_COMPILE_OPTIONS_TARGET";
+    std::string const& compilerExternalToolchain =
+      "CMAKE_" + lang + "_COMPILER_EXTERNAL_TOOLCHAIN";
+    std::string const& compilerOptionExternalToolchain =
+      "CMAKE_" + lang + "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN";
+    std::string const& compilerOptionSysroot =
+      "CMAKE_" + lang + "_COMPILE_OPTIONS_SYSROOT";
+
+    variableMappings[compilerArg1] =
+      this->Makefile->GetSafeDefinition(compilerArg1);
+    variableMappings[compilerTarget] =
+      this->Makefile->GetSafeDefinition(compilerTarget);
+    variableMappings[compilerOptionTarget] =
+      this->Makefile->GetSafeDefinition(compilerOptionTarget);
+    variableMappings[compilerExternalToolchain] =
+      this->Makefile->GetSafeDefinition(compilerExternalToolchain);
+    variableMappings[compilerOptionExternalToolchain] =
+      this->Makefile->GetSafeDefinition(compilerOptionExternalToolchain);
+    variableMappings[compilerOptionSysroot] =
+      this->Makefile->GetSafeDefinition(compilerOptionSysroot);
   }
 
   // loop over language specific replace variables
@@ -707,17 +740,8 @@ std::string cmLocalGenerator::ExpandRuleVariable(
        replaceIter != cmArrayEnd(ruleReplaceVars); ++replaceIter) {
     for (std::vector<std::string>::iterator i = enabledLanguages.begin();
          i != enabledLanguages.end(); ++i) {
-      const char* lang = i->c_str();
+      std::string const& lang = *i;
       std::string actualReplace = *replaceIter;
-      // If this is the compiler then look for the extra variable
-      // _COMPILER_ARG1 which must be the first argument to the compiler
-      const char* compilerArg1 = CM_NULLPTR;
-      const char* compilerTarget = CM_NULLPTR;
-      const char* compilerOptionTarget = CM_NULLPTR;
-      const char* compilerExternalToolchain = CM_NULLPTR;
-      const char* compilerOptionExternalToolchain = CM_NULLPTR;
-      const char* compilerSysroot = CM_NULLPTR;
-      const char* compilerOptionSysroot = CM_NULLPTR;
 
       std::map<std::string, std::string>::iterator compIt =
         compilers.find(variable);
@@ -725,40 +749,43 @@ std::string cmLocalGenerator::ExpandRuleVariable(
       std::string replace = this->Makefile->GetSafeDefinition(variable);
 
       if (compIt != compilers.end()) {
-        std::string arg1 = compIt->first + "_ARG1";
-        compilerArg1 = this->Makefile->GetDefinition(arg1);
-        compilerTarget = this->Makefile->GetDefinition(
-          std::string("CMAKE_") + compIt->second + "_COMPILER_TARGET");
-        compilerOptionTarget = this->Makefile->GetDefinition(
-          std::string("CMAKE_") + compIt->second + "_COMPILE_OPTIONS_TARGET");
-        compilerExternalToolchain = this->Makefile->GetDefinition(
-          std::string("CMAKE_") + compIt->second +
-          "_COMPILER_EXTERNAL_TOOLCHAIN");
-        compilerOptionExternalToolchain = this->Makefile->GetDefinition(
-          std::string("CMAKE_") + compIt->second +
-          "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN");
-        compilerSysroot = this->Makefile->GetDefinition("CMAKE_SYSROOT");
-        compilerOptionSysroot = this->Makefile->GetDefinition(
-          std::string("CMAKE_") + compIt->second + "_COMPILE_OPTIONS_SYSROOT");
-
-        std::string ret = this->ConvertToOutputForExisting(replace);
+        std::string ret = this->ConvertToOutputForExisting(
+          variableMappings["CMAKE_" + compIt->second + "_COMPILER"]);
+        std::string const& compilerArg1 =
+          variableMappings[compIt->first + "_COMPILER_ARG1"];
+        std::string const& compilerTarget =
+          variableMappings["CMAKE_" + compIt->second + "_COMPILER_TARGET"];
+        std::string const& compilerOptionTarget =
+          variableMappings["CMAKE_" + compIt->second +
+                           "_COMPILE_OPTIONS_TARGET"];
+        std::string const& compilerExternalToolchain =
+          variableMappings["CMAKE_" + compIt->second +
+                           "_COMPILER_EXTERNAL_TOOLCHAIN"];
+        std::string const& compilerOptionExternalToolchain =
+          variableMappings["CMAKE_" + compIt->second +
+                           "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN"];
+        std::string const& compilerOptionSysroot =
+          variableMappings["CMAKE_" + compIt->second +
+                           "_COMPILE_OPTIONS_SYSROOT"];
+
         // if there is a required first argument to the compiler add it
         // to the compiler string
-        if (compilerArg1) {
+        if (!compilerArg1.empty()) {
           ret += " ";
           ret += compilerArg1;
         }
-        if (compilerTarget && compilerOptionTarget) {
+        if (!compilerTarget.empty() && !compilerOptionTarget.empty()) {
           ret += " ";
           ret += compilerOptionTarget;
           ret += compilerTarget;
         }
-        if (compilerExternalToolchain && compilerOptionExternalToolchain) {
+        if (!compilerExternalToolchain.empty() &&
+            !compilerOptionExternalToolchain.empty()) {
           ret += " ";
           ret += compilerOptionExternalToolchain;
           ret += this->EscapeForShell(compilerExternalToolchain, true);
         }
-        if (compilerSysroot && compilerOptionSysroot) {
+        if (!compilerSysroot.empty() && !compilerOptionSysroot.empty()) {
           ret += " ";
           ret += compilerOptionSysroot;
           ret += this->EscapeForShell(compilerSysroot, true);

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

Summary of changes:


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list