Commit 9a2048f1 authored by Brad King's avatar Brad King Committed by Kitware Robot

Merge topic 'extract-cmRulePlaceholderExpander'

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
parents 248527ed b59b6dd9
......@@ -309,6 +309,8 @@ set(SRCS
cmLocalCommonGenerator.h
cmLocalGenerator.cxx
cmLocalGenerator.h
cmRulePlaceholderExpander.cxx
cmRulePlaceholderExpander.h
cmLocalUnixMakefileGenerator3.cxx
cmLocale.h
${MACH_SRCS}
......
......@@ -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"
......@@ -40,6 +41,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 +79,65 @@ 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);
}
}
}
cmRulePlaceholderExpander* cmLocalGenerator::CreateRulePlaceholderExpander()
const
{
return new cmRulePlaceholderExpander(this->Compilers, this->VariableMappings,
this->CompilerSysroot);
}
cmLocalGenerator::~cmLocalGenerator()
......@@ -486,325 +568,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",
CM_NULLPTR
};
std::string cmLocalGenerator::ExpandRuleVariable(
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.CMTarget) {
if (variable == "TARGET_NAME") {
return replaceValues.CMTarget->GetName();
}
if (variable == "TARGET_TYPE") {
return cmState::GetTargetTypeName(replaceValues.CMTarget->GetType());
}
}
if (replaceValues.Output) {
if (variable == "OUTPUT") {
return replaceValues.Output;
}
}
if (variable == "CMAKE_COMMAND") {
return this->ConvertToOutputFormat(
cmSystemTools::CollapseFullPath(cmSystemTools::GetCMakeCommand()),
SHELL);
}
std::vector<std::string> enabledLanguages =
this->GetState()->GetEnabledLanguages();
// loop over language specific replace variables
int pos = 0;
while (ruleReplaceVars[pos]) {
for (std::vector<std::string>::iterator i = enabledLanguages.begin();
i != enabledLanguages.end(); ++i) {
const char* lang = i->c_str();
std::string actualReplace = ruleReplaceVars[pos];
// 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;
if (actualReplace == "CMAKE_${LANG}_COMPILER") {
std::string arg1 = actualReplace + "_ARG1";
cmSystemTools::ReplaceString(arg1, "${LANG}", lang);
compilerArg1 = this->Makefile->GetDefinition(arg1);
compilerTarget = this->Makefile->GetDefinition(
std::string("CMAKE_") + lang + "_COMPILER_TARGET");
compilerOptionTarget = this->Makefile->GetDefinition(
std::string("CMAKE_") + lang + "_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");
compilerSysroot = this->Makefile->GetDefinition("CMAKE_SYSROOT");
compilerOptionSysroot = this->Makefile->GetDefinition(
std::string("CMAKE_") + lang + "_COMPILE_OPTIONS_SYSROOT");
}
if (actualReplace.find("${LANG}") != actualReplace.npos) {
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);
// 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 replace;
}
}
pos++;
}
return variable;
}
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) {
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(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;
}
const char* cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target,
const std::string& prop)
{
......@@ -814,17 +577,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)
{
......
......@@ -8,6 +8,7 @@
#include "cmListFileCache.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmRulePlaceholderExpander.h"
#include "cmState.h"
#include "cmake.h"
......@@ -23,6 +24,7 @@ class cmComputeLinkInformation;
class cmCustomCommandGenerator;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmRulePlaceholderExpander;
class cmMakefile;
class cmSourceFile;
class cmLinkLineComputer;
......@@ -84,6 +86,8 @@ public:
return this->GlobalGenerator;
}
virtual cmRulePlaceholderExpander* CreateRulePlaceholderExpander() const;
std::string GetLinkLibsCMP0065(std::string const& linkLanguage,
cmGeneratorTarget& tgt) const;
......@@ -217,42 +221,6 @@ public:
// preprocessed files and assembly files.
void GetIndividualFileTargets(std::vector<std::string>&) {}
// Create a struct to hold the varibles passed into
// ExpandRuleVariables
struct RuleVariables
{
RuleVariables() { memset(this, 0, sizeof(*this)); }
cmGeneratorTarget* CMTarget;
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;
};
/**
* Get the relative path from the generator output directory to a
* per-target support directory.
......@@ -346,6 +314,9 @@ public:
void CreateEvaluationFileOutputs(const std::string& config);
void ProcessEvaluationFiles(std::vector<std::string>& generatedFiles);
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 +324,6 @@ 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,
......@@ -391,11 +350,11 @@ protected:
std::vector<cmGeneratorTarget*> OwnedImportedGeneratorTargets;
std::map<std::string, std::string> AliasTargets;
bool EmitUniversalBinaryFlags;
std::map<std::string, std::string> Compilers;
std::map<std::string, std::string> VariableMappings;
std::string CompilerSysroot;
// Hack for ExpandRuleVariable until object-oriented version is
// committed.
std::string TargetImplib;
bool EmitUniversalBinaryFlags;
KWIML_INT_uint64_t BackwardsCompatibility;
bool BackwardsCompatibilityFinal;
......
......@@ -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()
{
}
......@@ -468,8 +477,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) {