summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/cmGeneratorTarget.cxx16
-rw-r--r--Source/cmGeneratorTarget.h3
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx4
-rw-r--r--Source/cmGlobalGenerator.cxx2
-rw-r--r--Source/cmGlobalGenerator.h3
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx6
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx4
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx4
-rw-r--r--Source/cmLocalGenerator.cxx412
-rw-r--r--Source/cmLocalGenerator.h63
-rw-r--r--Source/cmLocalNinjaGenerator.cxx28
-rw-r--r--Source/cmLocalNinjaGenerator.h8
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx17
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx27
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx40
-rw-r--r--Source/cmMakefileTargetGenerator.cxx23
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx24
-rw-r--r--Source/cmNinjaTargetGenerator.cxx41
-rw-r--r--Source/cmRulePlaceholderExpander.cxx304
-rw-r--r--Source/cmRulePlaceholderExpander.h83
-rw-r--r--Source/cmcldeps.cxx11
23 files changed, 665 insertions, 462 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index c9e77c3..71892ba 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/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 662ba9f..3640ea8 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 7)
-set(CMake_VERSION_PATCH 20161014)
+set(CMake_VERSION_PATCH 20161017)
#set(CMake_VERSION_RC 1)
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index b0ff13e..b16cfc6 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -1822,6 +1822,22 @@ std::string cmGeneratorTarget::GetMacContentDirectory(
return fpath;
}
+std::string cmGeneratorTarget::GetEffectiveFolderName() const
+{
+ std::string effectiveFolder;
+
+ if (!this->GlobalGenerator->UseFolderProperty()) {
+ return effectiveFolder;
+ }
+
+ const char* targetFolder = this->GetProperty("FOLDER");
+ if (targetFolder) {
+ effectiveFolder += targetFolder;
+ }
+
+ return effectiveFolder;
+}
+
cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo(
const std::string& config) const
{
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 15e46b8..8e5a02d 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -222,6 +222,9 @@ public:
std::string GetMacContentDirectory(const std::string& config = CM_NULLPTR,
bool implib = false) const;
+ /** @return folder prefix for IDEs. */
+ std::string GetEffectiveFolderName() const;
+
cmTarget* Target;
cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator;
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 5fbaea4..3154f8d 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -44,9 +44,7 @@ cmGhsMultiTargetGenerator::~cmGhsMultiTargetGenerator()
std::string cmGhsMultiTargetGenerator::GetRelBuildFilePath(
const cmGeneratorTarget* target)
{
- std::string output;
- char const* folderProp = target->GetProperty("FOLDER");
- output = NULL == folderProp ? "" : folderProp;
+ std::string output = target->GetEffectiveFolderName();
cmSystemTools::ConvertToUnixSlashes(output);
if (!output.empty()) {
output += "/";
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 1aa6af1..7d0c2da 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -2377,7 +2377,7 @@ const char* cmGlobalGenerator::GetPredefinedTargetsFolder()
return "CMakePredefinedTargets";
}
-bool cmGlobalGenerator::UseFolderProperty()
+bool cmGlobalGenerator::UseFolderProperty() const
{
const char* prop =
this->GetCMakeInstance()->GetState()->GetGlobalProperty("USE_FOLDERS");
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 38eaa76..c3498e0 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -334,6 +334,8 @@ public:
i.e. "Can I build Debug and Release in the same tree?" */
virtual bool IsMultiConfig() const { return false; }
+ virtual bool UseFolderProperty() const;
+
std::string GetSharedLibFlagsForLanguage(std::string const& lang) const;
/** Generate an <output>.rule file path for a given command output. */
@@ -463,7 +465,6 @@ protected:
std::string const& name) const;
const char* GetPredefinedTargetsFolder();
- virtual bool UseFolderProperty();
private:
#if defined(CMAKE_BUILD_WITH_CMAKE)
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 0eac338..d4ae677 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -439,11 +439,7 @@ void cmGlobalGhsMultiGenerator::UpdateBuildFiles(
tgtsI != tgts.end(); ++tgtsI) {
const cmGeneratorTarget* tgt = *tgtsI;
if (IsTgtForBuild(tgt)) {
- char const* rawFolderName = tgt->GetProperty("FOLDER");
- if (NULL == rawFolderName) {
- rawFolderName = "";
- }
- std::string folderName(rawFolderName);
+ std::string folderName = tgt->GetEffectiveFolderName();
if (this->TargetFolderBuildStreams.end() ==
this->TargetFolderBuildStreams.find(folderName)) {
this->AddFilesUpToPath(
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 3637fed..0287def 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -409,8 +409,8 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
// Create "solution folder" information from FOLDER target property
//
if (written && this->UseFolderProperty()) {
- const char* targetFolder = target->GetProperty("FOLDER");
- if (targetFolder) {
+ const std::string targetFolder = target->GetEffectiveFolderName();
+ if (!targetFolder.empty()) {
std::vector<cmsys::String> tokens =
cmSystemTools::SplitString(targetFolder, '/', false);
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 0ddfc9a..7b1afa5 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -2723,8 +2723,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup(
{
std::string s;
std::string target;
- const char* targetFolder = gtgt->GetProperty("FOLDER");
- if (targetFolder) {
+ const std::string targetFolder = gtgt->GetEffectiveFolderName();
+ if (!targetFolder.empty()) {
target = targetFolder;
target += "/";
}
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 3b19694..1c3a97d 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"
@@ -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)
{
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 69c4101..055e1a9 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"
@@ -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;
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index e25eb0f..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()
{
}
@@ -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) {
return std::string();
@@ -477,8 +486,8 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
// Expand rules in the empty string. It may insert the launcher and
// perform replacements.
- RuleVariables vars;
- vars.RuleLauncher = property;
+ cmRulePlaceholderExpander::RuleVariables vars;
+
std::string output;
const std::vector<std::string>& outputs = ccg.GetOutputs();
if (!outputs.empty()) {
@@ -491,8 +500,13 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
}
vars.Output = output.c_str();
- std::string launcher;
- this->ExpandRuleVariables(launcher, vars);
+ std::string launcher = property_value;
+ launcher += " ";
+
+ 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 b04788d..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;
@@ -58,12 +60,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..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();
@@ -984,14 +988,13 @@ 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;
+ cmRulePlaceholderExpander::RuleVariables vars;
+ 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()) {
@@ -1005,7 +1008,9 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
}
vars.Output = output.c_str();
- this->ExpandRuleVariables(launcher, vars);
+ launcher = val;
+ launcher += " ";
+ rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars);
if (!launcher.empty()) {
launcher += " ";
}
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index ed34ce6..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,9 +332,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
std::string manifests = this->GetManifests();
- cmLocalGenerator::RuleVariables vars;
- vars.RuleLauncher = "RULE_LAUNCH_LINK";
- vars.CMTarget = this->GeneratorTarget;
+ cmRulePlaceholderExpander::RuleVariables vars;
+ 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();
@@ -383,13 +385,26 @@ 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 += " ";
+ }
+
+ 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) {
- this->LocalGenerator->ExpandRuleVariables(*i, vars);
+ *i = launcher + *i;
+ 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 a19d70e..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.
@@ -540,8 +541,9 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
vars.TargetVersionMajor = targetVersionMajor.c_str();
vars.TargetVersionMinor = targetVersionMinor.c_str();
- vars.RuleLauncher = "RULE_LAUNCH_LINK";
- 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();
@@ -597,8 +599,18 @@ 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 += " ";
+ }
+
+ 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;
@@ -611,8 +623,9 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
for (std::vector<std::string>::const_iterator i =
archiveCreateCommands.begin();
i != archiveCreateCommands.end(); ++i) {
- std::string cmd = *i;
- this->LocalGenerator->ExpandRuleVariables(cmd, vars);
+ std::string cmd = launcher + *i;
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ cmd, vars);
real_link_commands.push_back(cmd);
}
}
@@ -622,8 +635,9 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
for (std::vector<std::string>::const_iterator i =
archiveAppendCommands.begin();
i != archiveAppendCommands.end(); ++i) {
- std::string cmd = *i;
- this->LocalGenerator->ExpandRuleVariables(cmd, vars);
+ std::string cmd = launcher + *i;
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ cmd, vars);
real_link_commands.push_back(cmd);
}
}
@@ -632,8 +646,9 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
for (std::vector<std::string>::const_iterator i =
archiveFinishCommands.begin();
i != archiveFinishCommands.end(); ++i) {
- std::string cmd = *i;
- this->LocalGenerator->ExpandRuleVariables(cmd, vars);
+ std::string cmd = launcher + *i;
+ 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);
@@ -655,10 +670,11 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// Expand placeholders.
for (std::vector<std::string>::iterator i = real_link_commands.begin();
i != real_link_commands.end(); ++i) {
- this->LocalGenerator->ExpandRuleVariables(*i, vars);
+ *i = launcher + *i;
+ 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 84ae726..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,9 +544,11 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
targetOutPathCompilePDB[targetOutPathCompilePDB.size() - 1] = '/';
}
}
- cmLocalGenerator::RuleVariables vars;
+ cmRulePlaceholderExpander::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();
@@ -587,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_";
@@ -600,7 +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(compileCommand, vars);
+
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ compileCommand, vars);
std::string workingDirectory = cmSystemTools::CollapseFullPath(
this->LocalGenerator->GetCurrentBinaryDirectory());
compileCommand.replace(compileCommand.find(langFlags), langFlags.size(),
@@ -659,7 +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(*i, vars);
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, *i,
+ vars);
}
// Change the command working directory to the local build tree.
@@ -722,7 +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(*i, vars);
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ *i, vars);
}
this->LocalGenerator->CreateCDCommand(
@@ -769,7 +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(*i, vars);
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ *i, vars);
}
this->LocalGenerator->CreateCDCommand(
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index d729114..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,9 +168,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
std::string rspcontent;
if (!this->GetGlobalGenerator()->HasRule(ruleName)) {
- cmLocalGenerator::RuleVariables vars;
- vars.RuleLauncher = "RULE_LAUNCH_LINK";
- vars.CMTarget = this->GetGeneratorTarget();
+ cmRulePlaceholderExpander::RuleVariables vars;
+ vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
+ vars.CMTargetType =
+ cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType());
+
vars.Language = this->TargetLinkLanguage.c_str();
std::string responseFlag;
@@ -238,11 +241,24 @@ 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 += " ";
+ }
+
+ 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) {
- this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
+ *i = launcher + *i;
+ 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 46a6161..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,9 +374,10 @@ 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();
+ cmRulePlaceholderExpander::RuleVariables vars;
+ 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";
@@ -452,10 +454,21 @@ 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);
+ 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";
@@ -466,9 +479,9 @@ 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;
- ppVars.RuleLauncher = vars.RuleLauncher;
- ppVars.CMTarget = vars.CMTarget;
+ cmRulePlaceholderExpander::RuleVariables ppVars;
+ ppVars.CMTargetName = vars.CMTargetName;
+ ppVars.CMTargetType = vars.CMTargetType;
ppVars.Language = vars.Language;
ppVars.Object = "$out"; // for RULE_LAUNCH_COMPILE
ppVars.PreprocessedSource = "$out";
@@ -496,7 +509,9 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
for (std::vector<std::string>::iterator i = ppCmds.begin();
i != ppCmds.end(); ++i) {
- this->GetLocalGenerator()->ExpandRuleVariables(*i, ppVars);
+ *i = launcher + *i;
+ rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
+ *i, ppVars);
}
// Run CMake dependency scanner on preprocessed output.
@@ -608,7 +623,9 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
for (std::vector<std::string>::iterator i = compileCmds.begin();
i != compileCmds.end(); ++i) {
- this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
+ *i = launcher + *i;
+ rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), *i,
+ vars);
}
std::string cmdLine =
@@ -961,7 +978,7 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
return;
}
- cmLocalGenerator::RuleVariables compileObjectVars;
+ cmRulePlaceholderExpander::RuleVariables compileObjectVars;
compileObjectVars.Language = language.c_str();
std::string escapedSourceFileName = sourceFileName;
@@ -993,9 +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(*i, compileObjectVars);
+ rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), *i,
+ compileObjectVars);
}
std::string cmdLine =
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/Source/cmcldeps.cxx b/Source/cmcldeps.cxx
index 167d60a..b86ad6e 100644
--- a/Source/cmcldeps.cxx
+++ b/Source/cmcldeps.cxx
@@ -205,7 +205,7 @@ static int process(const std::string& srcfilename, const std::string& dfile,
std::vector<std::string> command;
for (std::vector<std::string>::iterator i = args.begin(); i != args.end();
++i) {
- command.push_back(i->c_str());
+ command.push_back(*i);
}
// run the command
int exit_code = 0;
@@ -258,7 +258,7 @@ int main()
// needed to suppress filename output of msvc tools
std::string srcfilename;
{
- std::string::size_type pos = srcfile.rfind("\\");
+ std::string::size_type pos = srcfile.rfind('\\');
if (pos == std::string::npos) {
srcfilename = srcfile;
} else {
@@ -279,12 +279,7 @@ int main()
clrest = replace(clrest, "/fo", "/out:");
clrest = replace(clrest, objfile, objfile + ".dep.obj ");
- // rc: src\x\x.rc -> cl: /Tc src\x\x.rc
- if (srcfile.find(" ") != std::string::npos)
- srcfile = "\"" + srcfile + "\"";
- clrest = replace(clrest, srcfile, "/Tc " + srcfile);
-
- cl = "\"" + cl + "\" /P /DRC_INVOKED ";
+ cl = "\"" + cl + "\" /P /DRC_INVOKED /TC ";
// call cl in object dir so the .i is generated there
std::string objdir;