Преглед изворни кода

cmRulePlaceholderExpander: Extract from cmLocalGenerator

Implement cmLocalGenerator::ExpandRuleVariables in terms of the new
class for source compatibility and to reduce diff noise in this commit.
Stephen Kelly пре 9 година
родитељ
комит
bdddd4234e

+ 2 - 0
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}

+ 6 - 282
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,

+ 2 - 39
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,

+ 304 - 0
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;
+}

+ 83 - 0
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

+ 1 - 0
bootstrap

@@ -281,6 +281,7 @@ CMAKE_CXX_SOURCES="\
   cmInstallDirectoryGenerator \
   cmLocalCommonGenerator \
   cmLocalGenerator \
+  cmRulePlaceholderExpander \
   cmInstalledFile \
   cmInstallGenerator \
   cmInstallExportGenerator \