diff options
Diffstat (limited to 'Source')
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; |