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  2c0f3a34e5bd163b5194da61c9d1c0d89dc4f68d (commit)
       via  b59b6dd9d27de7839c7b23a3094db33298038896 (commit)
       via  bdddd4234e977f65ee7df8adcd3888706dfd0dda (commit)
       via  f796e1b6f6984b200453a13e6b8640353ff9488b (commit)
       via  c75a9d660169ddd1e7be57486d3813ca73886b55 (commit)
       via  46ad0d2183230d1af93242efbdcce20d55514efb (commit)
       via  2628dec12cb22546d2a21032f53fb0ef096faec8 (commit)
       via  315b9a31895ca6bb26eba12bff3a0fe9cd37568a (commit)
       via  d5feb5b34cd9f595bf42aa934738b918785e3e87 (commit)
       via  efba22e1deebcfc3924d5f14c026104eb4b62d28 (commit)
       via  b29425f7aafe07eff526f3c7defb317856b72984 (commit)
       via  f009d8f5e2e4007b93494c5d22ba25b41a4872a1 (commit)
       via  6cd27a853a1c77e5da0a9a14140284a7674cf18c (commit)
       via  8b0e4795687a2ea289d1313db24d75bcf3cd13bc (commit)
       via  88016e2e9f13d60c4a0b88fb64ffd802a2d9e534 (commit)
       via  be87cb0c444595fa1970e257031252669c201d3e (commit)
       via  425cd1670fdd40b752af71e5f28952ae4fcec4ac (commit)
      from  590f2a365ed4ee2cc3a7fd93f55b2ab869fc3004 (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=2c0f3a34e5bd163b5194da61c9d1c0d89dc4f68d
commit 2c0f3a34e5bd163b5194da61c9d1c0d89dc4f68d
Merge: 590f2a3 b59b6dd
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sat Oct 15 05:26:07 2016 -0400
Commit:     CMake Topic Stage <kwro...@kitware.com>
CommitDate: Sat Oct 15 05:26:07 2016 -0400

    Merge topic 'extract-cmRulePlaceholderExpander' into next
    
    b59b6dd9 cmRulePlaceholderExpander: Port clients to direct-use
    bdddd423 cmRulePlaceholderExpander: Extract from cmLocalGenerator
    f796e1b6 cmLocalGenerator: Move memset to cxx file
    c75a9d66 cmLocalGenerator: Use strings instead of a Target in rule 
replacement
    46ad0d21 cmLocalGenerator: Use a converter in rule replacement API
    2628dec1 cmLocalGenerator: Store variable replacements as state
    315b9a31 cmLocalGenerator: Merge loops which populate mapping
    d5feb5b3 cmLocalGenerator: Populate variable mapping for all replacements
    efba22e1 cmLocalGenerator: Extract compiler option replacement from loop
    b29425f7 cmLocalGenerator: Populate a container of mappings for replacements
    f009d8f5 cmLocalGenerator: Move compiler option handling to be more direct
    6cd27a85 cmLocalGenerator: Move variable to where it can be used easily
    8b0e4795 cmLocalGenerator: Use the language from the compiler container
    88016e2e cmLocalGenerator: Introduce a container of compiler names
    be87cb0c cmLocalGenerator: Simplify loop with range algorithm
    425cd167 cmLocalGenerator: Remove the launcher from RuleVariables


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b59b6dd9d27de7839c7b23a3094db33298038896
commit b59b6dd9d27de7839c7b23a3094db33298038896
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:50 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 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 fafff01..7eca0a8 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 1ae34d6..00a9100 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"
@@ -520,7 +521,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
 
     std::string manifests = this->GetManifests();
 
-    cmLocalGenerator::RuleVariables vars;
+    cmRulePlaceholderExpander::RuleVariables vars;
     vars.TargetPDB = targetOutPathPDB.c_str();
 
     // Setup the target version.
@@ -606,8 +607,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;
@@ -621,8 +624,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);
         }
       }
@@ -633,8 +636,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);
         }
       }
@@ -644,8 +647,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);
@@ -668,11 +671,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 9492a61..cbfe850 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 3adc068..b28b19a 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 c718ad4..1ac6cd4 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=bdddd4234e977f65ee7df8adcd3888706dfd0dda
commit bdddd4234e977f65ee7df8adcd3888706dfd0dda
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:50 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 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 849ffe4..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,292 +561,15 @@ cmState::Snapshot cmLocalGenerator::GetStateSnapshot() 
const
   return this->Makefile->GetStateSnapshot();
 }
 
-cmLocalGenerator::RuleVariables::RuleVariables()
-{
-  memset(this, 0, sizeof(*this));
-}
-
-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 6e6791d..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();
-    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..361321e
--- /dev/null
+++ b/Source/cmRulePlaceholderExpander.cxx
@@ -0,0 +1,304 @@
+/* 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)
+{
+}
+
+cmRulePlaceholderExpander::RuleVariables::RuleVariables()
+{
+  memset(this, 0, sizeof(*this));
+}
+
+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..444419c
--- /dev/null
+++ b/Source/cmRulePlaceholderExpander.h
@@ -0,0 +1,83 @@
+/* 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> // IWYU pragma: keep
+
+#include <map>
+#include <string>
+
+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();
+    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=f796e1b6f6984b200453a13e6b8640353ff9488b
commit f796e1b6f6984b200453a13e6b8640353ff9488b
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Tue Oct 11 19:33:42 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 2016 +0200

    cmLocalGenerator: Move memset to cxx file

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index fad7fae..849ffe4 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -560,6 +560,11 @@ cmState::Snapshot cmLocalGenerator::GetStateSnapshot() 
const
   return this->Makefile->GetStateSnapshot();
 }
 
+cmLocalGenerator::RuleVariables::RuleVariables()
+{
+  memset(this, 0, sizeof(*this));
+}
+
 std::string cmLocalGenerator::ExpandRuleVariable(
   cmOutputConverter* outputConverter, std::string const& variable,
   const RuleVariables& replaceValues)
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index c51aa85..6e6791d 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -221,7 +221,7 @@ public:
   // ExpandRuleVariables
   struct RuleVariables
   {
-    RuleVariables() { memset(this, 0, sizeof(*this)); }
+    RuleVariables();
     const char* CMTargetName;
     const char* CMTargetType;
     const char* TargetPDB;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c75a9d660169ddd1e7be57486d3813ca73886b55
commit c75a9d660169ddd1e7be57486d3813ca73886b55
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:50 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 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 6dd90c8..fad7fae 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 92d6185..fafff01 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 0566c1b..1ae34d6 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -540,7 +540,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 77643d1..9492a61 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 154f3c3..3adc068 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 8ae055f..c718ad4 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=46ad0d2183230d1af93242efbdcce20d55514efb
commit 46ad0d2183230d1af93242efbdcce20d55514efb
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:50 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 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 42e4b63..6dd90c8 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 da29b60..92d6185 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 5700c62..0566c1b 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -619,7 +619,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);
         }
       }
@@ -630,7 +631,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);
         }
       }
@@ -640,7 +642,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);
@@ -663,7 +666,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 84ae726..77643d1 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 64c434a..154f3c3 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 f85ea81..8ae055f 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=2628dec12cb22546d2a21032f53fb0ef096faec8
commit 2628dec12cb22546d2a21032f53fb0ef096faec8
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:49 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 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..42e4b63 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=315b9a31895ca6bb26eba12bff3a0fe9cd37568a
commit 315b9a31895ca6bb26eba12bff3a0fe9cd37568a
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:49 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 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=d5feb5b34cd9f595bf42aa934738b918785e3e87
commit d5feb5b34cd9f595bf42aa934738b918785e3e87
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:49 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 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=efba22e1deebcfc3924d5f14c026104eb4b62d28
commit efba22e1deebcfc3924d5f14c026104eb4b62d28
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:49 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 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=b29425f7aafe07eff526f3c7defb317856b72984
commit b29425f7aafe07eff526f3c7defb317856b72984
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:49 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 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);

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f009d8f5e2e4007b93494c5d22ba25b41a4872a1
commit f009d8f5e2e4007b93494c5d22ba25b41a4872a1
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:48 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 2016 +0200

    cmLocalGenerator: Move compiler option handling to be more direct

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 03f5d2c..d451270 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -740,6 +740,30 @@ std::string cmLocalGenerator::ExpandRuleVariable(
         compilerSysroot = this->Makefile->GetDefinition("CMAKE_SYSROOT");
         compilerOptionSysroot = this->Makefile->GetDefinition(
           std::string("CMAKE_") + compIt->second + "_COMPILE_OPTIONS_SYSROOT");
+
+        std::string ret = this->ConvertToOutputForExisting(replace);
+        // if there is a required first argument to the compiler add it
+        // to the compiler string
+        if (compilerArg1) {
+          ret += " ";
+          ret += compilerArg1;
+        }
+        if (compilerTarget && compilerOptionTarget) {
+          ret += " ";
+          ret += compilerOptionTarget;
+          ret += compilerTarget;
+        }
+        if (compilerExternalToolchain && compilerOptionExternalToolchain) {
+          ret += " ";
+          ret += compilerOptionExternalToolchain;
+          ret += this->EscapeForShell(compilerExternalToolchain, true);
+        }
+        if (compilerSysroot && compilerOptionSysroot) {
+          ret += " ";
+          ret += compilerOptionSysroot;
+          ret += this->EscapeForShell(compilerSysroot, true);
+        }
+        return ret;
       }
       if (actualReplace.find("${LANG}") != actualReplace.npos) {
         cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
@@ -747,29 +771,7 @@ std::string cmLocalGenerator::ExpandRuleVariable(
       if (actualReplace == variable) {
         // if the variable is not a FLAG then treat it like a path
         if (variable.find("_FLAG") == variable.npos) {
-          std::string ret = this->ConvertToOutputForExisting(replace);
-          // if there is a required first argument to the compiler add it
-          // to the compiler string
-          if (compilerArg1) {
-            ret += " ";
-            ret += compilerArg1;
-          }
-          if (compilerTarget && compilerOptionTarget) {
-            ret += " ";
-            ret += compilerOptionTarget;
-            ret += compilerTarget;
-          }
-          if (compilerExternalToolchain && compilerOptionExternalToolchain) {
-            ret += " ";
-            ret += compilerOptionExternalToolchain;
-            ret += this->EscapeForShell(compilerExternalToolchain, true);
-          }
-          if (compilerSysroot && compilerOptionSysroot) {
-            ret += " ";
-            ret += compilerOptionSysroot;
-            ret += this->EscapeForShell(compilerSysroot, true);
-          }
-          return ret;
+          return this->ConvertToOutputForExisting(replace);
         }
         return replace;
       }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6cd27a853a1c77e5da0a9a14140284a7674cf18c
commit 6cd27a853a1c77e5da0a9a14140284a7674cf18c
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:48 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 2016 +0200

    cmLocalGenerator: Move variable to where it can be used easily

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index c405180..03f5d2c 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -722,6 +722,8 @@ 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 arg1 = compIt->first + "_ARG1";
         compilerArg1 = this->Makefile->GetDefinition(arg1);
@@ -743,7 +745,6 @@ std::string cmLocalGenerator::ExpandRuleVariable(
         cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
       }
       if (actualReplace == variable) {
-        std::string replace = this->Makefile->GetSafeDefinition(variable);
         // if the variable is not a FLAG then treat it like a path
         if (variable.find("_FLAG") == variable.npos) {
           std::string ret = this->ConvertToOutputForExisting(replace);

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8b0e4795687a2ea289d1313db24d75bcf3cd13bc
commit 8b0e4795687a2ea289d1313db24d75bcf3cd13bc
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:48 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 2016 +0200

    cmLocalGenerator: Use the language from the compiler container
    
    This is just to make follow-up diffs smaller.

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index a9de948..c405180 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -726,17 +726,18 @@ std::string cmLocalGenerator::ExpandRuleVariable(
         std::string arg1 = compIt->first + "_ARG1";
         compilerArg1 = this->Makefile->GetDefinition(arg1);
         compilerTarget = this->Makefile->GetDefinition(
-          std::string("CMAKE_") + lang + "_COMPILER_TARGET");
+          std::string("CMAKE_") + compIt->second + "_COMPILER_TARGET");
         compilerOptionTarget = this->Makefile->GetDefinition(
-          std::string("CMAKE_") + lang + "_COMPILE_OPTIONS_TARGET");
+          std::string("CMAKE_") + compIt->second + "_COMPILE_OPTIONS_TARGET");
         compilerExternalToolchain = this->Makefile->GetDefinition(
-          std::string("CMAKE_") + lang + "_COMPILER_EXTERNAL_TOOLCHAIN");
-        compilerOptionExternalToolchain =
-          this->Makefile->GetDefinition(std::string("CMAKE_") + lang +
-                                        "_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN");
+          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_") + lang + "_COMPILE_OPTIONS_SYSROOT");
+          std::string("CMAKE_") + compIt->second + "_COMPILE_OPTIONS_SYSROOT");
       }
       if (actualReplace.find("${LANG}") != actualReplace.npos) {
         cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=88016e2e9f13d60c4a0b88fb64ffd802a2d9e534
commit 88016e2e9f13d60c4a0b88fb64ffd802a2d9e534
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:48 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 2016 +0200

    cmLocalGenerator: Introduce a container of compiler names
    
    Use it to determine when a rule replacement should gain extra options.

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 4f285cf..a9de948 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -691,6 +691,17 @@ std::string cmLocalGenerator::ExpandRuleVariable(
   }
   std::vector<std::string> enabledLanguages =
     this->GetState()->GetEnabledLanguages();
+
+  std::map<std::string, std::string> compilers;
+  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;
+  }
+
   // loop over language specific replace variables
   for (const char* const* replaceIter = cmArrayBegin(ruleReplaceVars);
        replaceIter != cmArrayEnd(ruleReplaceVars); ++replaceIter) {
@@ -707,9 +718,12 @@ std::string cmLocalGenerator::ExpandRuleVariable(
       const char* compilerOptionExternalToolchain = CM_NULLPTR;
       const char* compilerSysroot = CM_NULLPTR;
       const char* compilerOptionSysroot = CM_NULLPTR;
-      if (actualReplace == "CMAKE_${LANG}_COMPILER") {
-        std::string arg1 = actualReplace + "_ARG1";
-        cmSystemTools::ReplaceString(arg1, "${LANG}", lang);
+
+      std::map<std::string, std::string>::iterator compIt =
+        compilers.find(variable);
+
+      if (compIt != compilers.end()) {
+        std::string arg1 = compIt->first + "_ARG1";
         compilerArg1 = this->Makefile->GetDefinition(arg1);
         compilerTarget = this->Makefile->GetDefinition(
           std::string("CMAKE_") + lang + "_COMPILER_TARGET");

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=be87cb0c444595fa1970e257031252669c201d3e
commit be87cb0c444595fa1970e257031252669c201d3e
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:48 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 2016 +0200

    cmLocalGenerator: Simplify loop with range algorithm

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 138fe55..4f285cf 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -505,8 +505,7 @@ static const char* ruleReplaceVars[] = {
   "CMAKE_CURRENT_BINARY_DIR",
   "CMAKE_RANLIB",
   "CMAKE_LINKER",
-  "CMAKE_CL_SHOWINCLUDES_PREFIX",
-  CM_NULLPTR
+  "CMAKE_CL_SHOWINCLUDES_PREFIX"
 };
 
 std::string cmLocalGenerator::ExpandRuleVariable(
@@ -693,12 +692,12 @@ std::string cmLocalGenerator::ExpandRuleVariable(
   std::vector<std::string> enabledLanguages =
     this->GetState()->GetEnabledLanguages();
   // loop over language specific replace variables
-  int pos = 0;
-  while (ruleReplaceVars[pos]) {
+  for (const char* const* replaceIter = cmArrayBegin(ruleReplaceVars);
+       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 actualReplace = ruleReplaceVars[pos];
+      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;
@@ -759,7 +758,6 @@ std::string cmLocalGenerator::ExpandRuleVariable(
         return replace;
       }
     }
-    pos++;
   }
   return variable;
 }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=425cd1670fdd40b752af71e5f28952ae4fcec4ac
commit 425cd1670fdd40b752af71e5f28952ae4fcec4ac
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Sun Oct 9 10:34:47 2016 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Sat Oct 15 11:25:12 2016 +0200

    cmLocalGenerator: Remove the launcher from RuleVariables
    
    This one is not like the others as it doesn't participate in
    substitutions.  Keep ExpandRuleVariables doing only one thing and make
    callers responsible for inserting a launcher prefix, simplifying the
    code all-around.
    
    Remove now-obsolete InsertRuleLauncher method.

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 3b19694..138fe55 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -767,10 +767,6 @@ std::string cmLocalGenerator::ExpandRuleVariable(
 void cmLocalGenerator::ExpandRuleVariables(std::string& s,
                                            const RuleVariables& replaceValues)
 {
-  if (replaceValues.RuleLauncher) {
-    this->InsertRuleLauncher(s, replaceValues.CMTarget,
-                             replaceValues.RuleLauncher);
-  }
   std::string::size_type start = s.find('<');
   // no variables to expand
   if (start == s.npos) {
@@ -814,17 +810,6 @@ const char* 
cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target,
   return this->Makefile->GetProperty(prop);
 }
 
-void cmLocalGenerator::InsertRuleLauncher(std::string& s,
-                                          cmGeneratorTarget* target,
-                                          const std::string& prop)
-{
-  if (const char* val = this->GetRuleLauncher(target, prop)) {
-    std::ostringstream wrapped;
-    wrapped << val << " " << s;
-    s = wrapped.str();
-  }
-}
-
 std::string cmLocalGenerator::ConvertToIncludeReference(
   std::string const& path, OutputFormat format, bool forceFullPaths)
 {
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 69c4101..44d10bb 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -346,6 +346,13 @@ 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(std::string& string,
+                           const RuleVariables& replaceValues);
+
+  const char* GetRuleLauncher(cmGeneratorTarget* target,
+                              const std::string& prop);
+
 protected:
   ///! put all the libraries for a target on into the given stream
   void OutputLinkLibraries(cmComputeLinkInformation* pcli,
@@ -353,18 +360,10 @@ protected:
                            std::string& linkLibraries,
                            std::string& frameworkPath, std::string& linkPath);
 
-  // Expand rule variables in CMake of the type found in language rules
-  void ExpandRuleVariables(std::string& string,
-                           const RuleVariables& replaceValues);
   // Expand rule variables in a single string
   std::string ExpandRuleVariable(std::string const& variable,
                                  const RuleVariables& replaceValues);
 
-  const char* GetRuleLauncher(cmGeneratorTarget* target,
-                              const std::string& prop);
-  void InsertRuleLauncher(std::string& s, cmGeneratorTarget* target,
-                          const std::string& prop);
-
   // Handle old-style install rules stored in the targets.
   void GenerateTargetInstallRules(
     std::ostream& os, const std::string& config,
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index e25eb0f..ea711c0 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -468,8 +468,8 @@ void 
cmLocalNinjaGenerator::WriteCustomCommandBuildStatements()
 std::string cmLocalNinjaGenerator::MakeCustomLauncher(
   cmCustomCommandGenerator const& ccg)
 {
-  const char* property = "RULE_LAUNCH_CUSTOM";
-  const char* property_value = this->Makefile->GetProperty(property);
+  const char* property_value =
+    this->Makefile->GetProperty("RULE_LAUNCH_CUSTOM");
 
   if (!property_value || !*property_value) {
     return std::string();
@@ -478,7 +478,7 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
   // Expand rules in the empty string.  It may insert the launcher and
   // perform replacements.
   RuleVariables vars;
-  vars.RuleLauncher = property;
+
   std::string output;
   const std::vector<std::string>& outputs = ccg.GetOutputs();
   if (!outputs.empty()) {
@@ -491,7 +491,9 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
   }
   vars.Output = output.c_str();
 
-  std::string launcher;
+  std::string launcher = property_value;
+  launcher += " ";
+
   this->ExpandRuleVariables(launcher, vars);
   if (!launcher.empty()) {
     launcher += " ";
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index b04788d..56aa9bf 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -58,12 +58,6 @@ public:
     return this->HomeRelativeOutputPath;
   }
 
-  void ExpandRuleVariables(std::string& string,
-                           const RuleVariables& replaceValues)
-  {
-    cmLocalGenerator::ExpandRuleVariables(string, replaceValues);
-  }
-
   std::string BuildCommandLine(const std::vector<std::string>& cmdLines);
 
   void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs);
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx 
b/Source/cmLocalUnixMakefileGenerator3.cxx
index 02eef59..92b58ba 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -984,13 +984,11 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
 
       std::string launcher;
       // Short-circuit if there is no launcher.
-      const char* prop = "RULE_LAUNCH_CUSTOM";
-      const char* val = this->GetRuleLauncher(target, prop);
+      const char* val = this->GetRuleLauncher(target, "RULE_LAUNCH_CUSTOM");
       if (val && *val) {
         // Expand rules in the empty string.  It may insert the launcher and
         // perform replacements.
         RuleVariables vars;
-        vars.RuleLauncher = prop;
         vars.CMTarget = target;
         std::string output;
         const std::vector<std::string>& outputs = ccg.GetOutputs();
@@ -1005,6 +1003,8 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
         }
         vars.Output = output.c_str();
 
+        launcher = val;
+        launcher += " ";
         this->ExpandRuleVariables(launcher, vars);
         if (!launcher.empty()) {
           launcher += " ";
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx 
b/Source/cmMakefileExecutableTargetGenerator.cxx
index ed34ce6..da29b60 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -332,7 +332,6 @@ void 
cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     std::string manifests = this->GetManifests();
 
     cmLocalGenerator::RuleVariables vars;
-    vars.RuleLauncher = "RULE_LAUNCH_LINK";
     vars.CMTarget = this->GeneratorTarget;
     vars.Language = linkLanguage.c_str();
     vars.Objects = buildObjs.c_str();
@@ -383,10 +382,20 @@ void 
cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
       real_link_commands.push_back(cmakeCommand);
     }
 
+    std::string launcher;
+
+    const char* val = this->LocalGenerator->GetRuleLauncher(
+      this->GeneratorTarget, "RULE_LAUNCH_LINK");
+    if (val && *val) {
+      launcher = val;
+      launcher += " ";
+    }
+
     // Expand placeholders in the commands.
     this->LocalGenerator->TargetImplib = targetOutPathImport;
     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->TargetImplib = "";
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx 
b/Source/cmMakefileLibraryTargetGenerator.cxx
index a19d70e..5700c62 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -540,7 +540,6 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     vars.TargetVersionMajor = targetVersionMajor.c_str();
     vars.TargetVersionMinor = targetVersionMinor.c_str();
 
-    vars.RuleLauncher = "RULE_LAUNCH_LINK";
     vars.CMTarget = this->GeneratorTarget;
     vars.Language = linkLanguage.c_str();
     vars.Objects = buildObjs.c_str();
@@ -597,6 +596,14 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
 
     vars.LanguageCompileFlags = langFlags.c_str();
 
+    std::string launcher;
+    const char* val = this->LocalGenerator->GetRuleLauncher(
+      this->GeneratorTarget, "RULE_LAUNCH_LINK");
+    if (val && *val) {
+      launcher = val;
+      launcher += " ";
+    }
+
     // Construct the main link rule and expand placeholders.
     this->LocalGenerator->TargetImplib = targetOutPathImport;
     if (useArchiveRules) {
@@ -611,7 +618,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
         for (std::vector<std::string>::const_iterator i =
                archiveCreateCommands.begin();
              i != archiveCreateCommands.end(); ++i) {
-          std::string cmd = *i;
+          std::string cmd = launcher + *i;
           this->LocalGenerator->ExpandRuleVariables(cmd, vars);
           real_link_commands.push_back(cmd);
         }
@@ -622,7 +629,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
         for (std::vector<std::string>::const_iterator i =
                archiveAppendCommands.begin();
              i != archiveAppendCommands.end(); ++i) {
-          std::string cmd = *i;
+          std::string cmd = launcher + *i;
           this->LocalGenerator->ExpandRuleVariables(cmd, vars);
           real_link_commands.push_back(cmd);
         }
@@ -632,7 +639,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
       for (std::vector<std::string>::const_iterator i =
              archiveFinishCommands.begin();
            i != archiveFinishCommands.end(); ++i) {
-        std::string cmd = *i;
+        std::string cmd = launcher + *i;
         this->LocalGenerator->ExpandRuleVariables(cmd, vars);
         // If there is no ranlib the command will be ":".  Skip it.
         if (!cmd.empty() && cmd[0] != ':') {
@@ -655,6 +662,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
       // Expand placeholders.
       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);
       }
     }
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx 
b/Source/cmNinjaNormalTargetGenerator.cxx
index d729114..64c434a 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -168,7 +168,6 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool 
useResponseFile)
 
   if (!this->GetGlobalGenerator()->HasRule(ruleName)) {
     cmLocalGenerator::RuleVariables vars;
-    vars.RuleLauncher = "RULE_LAUNCH_LINK";
     vars.CMTarget = this->GetGeneratorTarget();
     vars.Language = this->TargetLinkLanguage.c_str();
 
@@ -238,10 +237,19 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool 
useResponseFile)
       vars.LanguageCompileFlags = langFlags.c_str();
     }
 
+    std::string launcher;
+    const char* val = this->GetLocalGenerator()->GetRuleLauncher(
+      this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
+    if (val && *val) {
+      launcher = val;
+      launcher += " ";
+    }
+
     // 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(*i, vars);
     }
     {
diff --git a/Source/cmNinjaTargetGenerator.cxx 
b/Source/cmNinjaTargetGenerator.cxx
index 46a6161..f85ea81 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -374,7 +374,6 @@ void cmNinjaTargetGenerator::WriteLanguageRules(const 
std::string& language)
 void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
 {
   cmLocalGenerator::RuleVariables vars;
-  vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
   vars.CMTarget = this->GetGeneratorTarget();
   vars.Language = lang.c_str();
   vars.Source = "$IN_ABS";
@@ -456,6 +455,14 @@ void cmNinjaTargetGenerator::WriteCompileRule(const 
std::string& lang)
     ConvertToNinjaPath(this->GetTargetDependInfoPath(lang)),
     cmLocalGenerator::SHELL);
 
+  std::string launcher;
+  const char* val = this->GetLocalGenerator()->GetRuleLauncher(
+    this->GetGeneratorTarget(), "RULE_LAUNCH_COMPILE");
+  if (val && *val) {
+    launcher = val;
+    launcher += " ";
+  }
+
   if (explicitPP) {
     // Lookup the explicit preprocessing rule.
     std::string const ppVar = "CMAKE_" + lang + "_PREPROCESS_SOURCE";
@@ -467,7 +474,6 @@ void cmNinjaTargetGenerator::WriteCompileRule(const 
std::string& lang)
     std::string const ppDepfile = "$DEP_FILE";
 
     cmLocalGenerator::RuleVariables ppVars;
-    ppVars.RuleLauncher = vars.RuleLauncher;
     ppVars.CMTarget = vars.CMTarget;
     ppVars.Language = vars.Language;
     ppVars.Object = "$out"; // for RULE_LAUNCH_COMPILE
@@ -496,6 +502,7 @@ 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);
     }
 
@@ -608,6 +615,7 @@ 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);
   }
 

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

Summary of changes:
 Source/CMakeLists.txt                          |    2 +
 Source/cmLocalGenerator.cxx                    |  412 +++++-------------------
 Source/cmLocalGenerator.h                      |   63 +---
 Source/cmLocalNinjaGenerator.cxx               |   28 +-
 Source/cmLocalNinjaGenerator.h                 |    8 +-
 Source/cmLocalUnixMakefileGenerator3.cxx       |   17 +-
 Source/cmMakefileExecutableTargetGenerator.cxx |   27 +-
 Source/cmMakefileLibraryTargetGenerator.cxx    |   40 ++-
 Source/cmMakefileTargetGenerator.cxx           |   23 +-
 Source/cmNinjaNormalTargetGenerator.cxx        |   24 +-
 Source/cmNinjaTargetGenerator.cxx              |   41 ++-
 Source/cmRulePlaceholderExpander.cxx           |  304 +++++++++++++++++
 Source/cmRulePlaceholderExpander.h             |   83 +++++
 bootstrap                                      |    1 +
 14 files changed, 634 insertions(+), 439 deletions(-)
 create mode 100644 Source/cmRulePlaceholderExpander.cxx
 create mode 100644 Source/cmRulePlaceholderExpander.h


hooks/post-receive
-- 
CMake
_______________________________________________
Cmake-commits mailing list
Cmake-commits@cmake.org
http://public.kitware.com/mailman/listinfo/cmake-commits

Reply via email to