From 100407394209e44cd8a2dae555d2424161f45a6e Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Tue, 12 Apr 2005 13:27:07 -0400 Subject: [PATCH] ENH: performance improvements --- Source/cmLocalGenerator.cxx | 295 +++++++++++++++-------- Source/cmLocalGenerator.h | 14 ++ Source/cmLocalVisualStudio7Generator.cxx | 23 +- Source/cmMacroCommand.cxx | 12 +- Source/cmMakefile.cxx | 9 +- Source/cmMakefile.h | 3 +- 6 files changed, 238 insertions(+), 118 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index db9010827f..41c3c2321b 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -592,11 +592,6 @@ void cmLocalGenerator::CreateCustomTargetsAndCommands(std::set cons } -struct RuleVariables -{ - const char* variable; -}; - // List of variables that are replaced when // rules are expanced. These variables are @@ -605,6 +600,7 @@ struct RuleVariables // 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", @@ -612,7 +608,6 @@ static const char* ruleReplaceVars[] = "CMAKE_${LANG}_LINK_FLAGS", "CMAKE_SHARED_LIBRARY_SONAME_${LANG}_FLAG", "CMAKE_${LANG}_ARCHIVE", - "CMAKE_${LANG}_COMPILER", "CMAKE_AR", "CMAKE_CURRENT_SOURCE_DIR", "CMAKE_CURRENT_BINARY_DIR", @@ -620,9 +615,165 @@ static const char* ruleReplaceVars[] = 0 }; +std::string +cmLocalGenerator::ExpandRuleVariable(std::string const& variable, + const char* lang, + const char* objects, + const char* target, + const char* linkLibs, + const char* source, + const char* object, + const char* flags, + const char* objectsquoted, + const char* targetBase, + const char* targetSOName, + const char* linkFlags) +{ + if(linkFlags) + { + if(variable == "LINK_FLAGS") + { + return linkFlags; + } + } + if(flags) + { + if(variable == "FLAGS") + { + return flags; + } + } + + if(source) + { + if(variable == "SOURCE") + { + return source; + } + } + if(object) + { + if(variable == "OBJECT") + { + return object; + } + } + if(objects) + { + if(variable == "OBJECTS") + { + return objects; + } + } + if(objectsquoted) + { + if(variable == "OBJECTS_QUOTED") + { + return objectsquoted; + } + } + if(target) + { + if(variable == "TARGET_QUOTED") + { + std::string targetQuoted = target; + if(targetQuoted.size() && targetQuoted[0] != '\"') + { + targetQuoted = '\"'; + targetQuoted += target; + targetQuoted += '\"'; + return targetQuoted; + } + } + if(variable == "TARGET") + { + return target; + } + } + if(targetBase) + { + if(variable == "TARGET_BASE.lib" || variable == "TARGET_BASE.dll") + { + // special case for quoted paths with spaces + // if you see .lib then put the .lib inside + // the quotes, same for .dll + if((strlen(targetBase) > 1) && targetBase[0] == '\"') + { + std::string base = targetBase; + base[base.size()-1] = '.'; + std::string baseLib = base + "lib\""; + std::string baseDll = base + "dll\""; + if(variable == "TARGET_BASE.lib" ) + { + return baseLib; + } + if(variable == "TARGET_BASE.dll" ) + { + return baseDll; + } + } + } + if(variable == "TARGET_BASE") + { + return targetBase; + } + } + if(targetSOName) + { + if(variable == "TARGET_SONAME") + { + if(lang) + { + std::string name = "CMAKE_SHARED_LIBRARY_SONAME_"; + name += lang; + name += "_FLAG"; + if(m_Makefile->GetDefinition(name.c_str())) + { + return targetSOName; + } + } + return ""; + } + } + if(linkLibs) + { + if(variable == "LINK_LIBRARIES") + { + return linkLibs; + } + } + std::vector enabledLanguages; + m_GlobalGenerator->GetEnabledLanguages(enabledLanguages); + // loop over language specific replace variables + int pos = 0; + while(ruleReplaceVars[pos]) + { + for(std::vector::iterator i = enabledLanguages.begin(); + i != enabledLanguages.end(); ++i) + { + lang = i->c_str(); + std::string actualReplace = ruleReplaceVars[pos]; + if(actualReplace.find("${LANG}") != actualReplace.npos) + { + cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang); + } + if(actualReplace == variable) + { + std::string replace = m_Makefile->GetSafeDefinition(variable.c_str()); + // if the variable is not a FLAG then treat it like a path + if(variable.find("_FLAG") == variable.npos) + { + return this->ConvertToOutputForExisting(replace.c_str()); + } + return replace; + } + } + pos++; + } + return variable; +} - void cmLocalGenerator::ExpandRuleVariables(std::string& s, const char* lang, @@ -639,113 +790,49 @@ cmLocalGenerator::ExpandRuleVariables(std::string& s, { std::vector enabledLanguages; m_GlobalGenerator->GetEnabledLanguages(enabledLanguages); - - if(linkFlags) + std::string::size_type start = s.find('<'); + // no variables to expand + if(start == s.npos) { - cmSystemTools::ReplaceString(s, "", linkFlags); + return; } - if(flags) + std::string::size_type pos = 0; + std::string expandedInput; + while(start != s.npos && start < s.size()-2) { - cmSystemTools::ReplaceString(s, "", flags); - } - - if(source) - { - cmSystemTools::ReplaceString(s, "", source); - } - if(object) - { - cmSystemTools::ReplaceString(s, "", object); - } - if(objects) - { - cmSystemTools::ReplaceString(s, "", objects); - } - if(objectsquoted) - { - cmSystemTools::ReplaceString(s, "", objectsquoted); - } - if(target) - { - std::string targetQuoted = target; - if(targetQuoted.size() && targetQuoted[0] != '\"') + std::string::size_type end = s.find('>', start); + // if we find a < with no > we are done + if(end == s.npos) { - targetQuoted = '\"'; - targetQuoted += target; - targetQuoted += '\"'; + return; } - cmSystemTools::ReplaceString(s, "", targetQuoted.c_str()); - cmSystemTools::ReplaceString(s, "", target); - } - if(targetBase) - { - // special case for quoted paths with spaces - // if you see .lib then put the .lib inside - // the quotes, same for .dll - if((strlen(targetBase) > 1) && targetBase[0] == '\"') + 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)) { - std::string base = targetBase; - base[base.size()-1] = '.'; - std::string baseLib = base + "lib\""; - std::string baseDll = base + "dll\""; - cmSystemTools::ReplaceString(s, ".lib", baseLib.c_str()); - cmSystemTools::ReplaceString(s, ".dll", baseDll.c_str()); + start = s.find('<', start+1); } - cmSystemTools::ReplaceString(s, "", targetBase); - } - if(targetSOName) - { - bool replaced = false; - if(lang) + else { - std::string name = "CMAKE_SHARED_LIBRARY_SONAME_"; - name += lang; - name += "_FLAG"; - if(m_Makefile->GetDefinition(name.c_str())) - { - replaced = true; - cmSystemTools::ReplaceString(s, "", targetSOName); - } - } - if(!replaced) - { - cmSystemTools::ReplaceString(s, "", ""); + // extract the var + std::string var = s.substr(start+1, end - start-1); + std::string replace = this->ExpandRuleVariable(var, lang, objects, + target, linkLibs, + source, object, flags, + objectsquoted, + targetBase, targetSOName, + linkFlags); + expandedInput += s.substr(pos, start-pos); + expandedInput += replace; + // move to next one + start = s.find('<', start+var.size()+2); + pos = end+1; } } - if(linkLibs) - { - cmSystemTools::ReplaceString(s, "", linkLibs); - } - - // loop over language specific replace variables - int pos = 0; - while(ruleReplaceVars[pos]) - { - for(std::vector::iterator i = enabledLanguages.begin(); - i != enabledLanguages.end(); ++i) - { - lang = i->c_str(); - std::string replace = "<"; - replace += ruleReplaceVars[pos]; - replace += ">"; - std::string replaceWith = ruleReplaceVars[pos]; - std::string actualReplace = replace; - cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang); - std::string actualReplaceWith = replaceWith; - cmSystemTools::ReplaceString(actualReplaceWith, "${LANG}", lang); - replace = m_Makefile->GetSafeDefinition(actualReplaceWith.c_str()); - // if the variable is not a FLAG then treat it like a path - if(actualReplaceWith.find("_FLAG") == actualReplaceWith.npos) - { - replace = this->ConvertToOutputForExisting(replace.c_str()); - } - if(actualReplace.size()) - { - cmSystemTools::ReplaceString(s, actualReplace.c_str(), replace.c_str()); - } - } - pos++; - } + // add the rest of the input + expandedInput += s.substr(pos, s.size()-pos); + s = expandedInput; } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 8d3009ba5b..bea6c67fee 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -162,6 +162,20 @@ protected: const char* targetBase = 0, const char* targetSOName = 0, const char* linkFlags = 0); + // Expand rule variables in a single string + std::string ExpandRuleVariable(std::string const& variable, + const char* lang, + const char* objects, + const char* target, + const char* linkLibs, + const char* source, + const char* object, + const char* flags, + const char* objectsquoted, + const char* targetBase, + const char* targetSOName, + const char* linkFlags); + ///! Convert a target to a utility target for unsupported languages of a generator void AddBuildTargetRule(const char* llang, cmTarget& target); ///! add a custom command to build a .o file that is part of a target diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 6e64b1b541..e623d2c06d 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -540,19 +540,30 @@ void cmLocalVisualStudio7Generator::FillFlagMapFromCommandFlags( std::string& flags) { std::string replace; + std::string option; while(flagTable->IDEName) { - std::string regex = "((/|-)"; - regex += flagTable->commandFlag; - regex += ")"; - cmsys::RegularExpression reg(regex.c_str()); - while(reg.find(flags)) + option.reserve(strlen(flagTable->commandFlag+2)); + // first do the - version + option.insert(0, 1, '-'); + option.append(flagTable->commandFlag); + while(flags.find(option) != flags.npos) { // replace the flag - cmSystemTools::ReplaceString(flags, reg.match(1).c_str(), ""); + cmSystemTools::ReplaceString(flags, option.c_str(), ""); // now put value into flag map flagMap[flagTable->IDEName] = flagTable->value; } + // now do the / version + option[0] = '/'; + while(flags.find(option) != flags.npos) + { + // replace the flag + cmSystemTools::ReplaceString(flags, option.c_str(), ""); + // now put value into flag map + flagMap[flagTable->IDEName] = flagTable->value; + } + // move to next flag flagTable++; } } diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 338754681f..7780920ffc 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -119,6 +119,14 @@ bool cmMacroHelperCommand::InvokeInitialPass newLFF.m_Name = m_Functions[c].m_Name; newLFF.m_FilePath = m_Functions[c].m_FilePath; newLFF.m_Line = m_Functions[c].m_Line; + const char* def = + m_Makefile->GetDefinition("CMAKE_MACRO_REPORT_DEFINITION_LOCATION"); + bool macroReportLocation = false; + if(def && !cmSystemTools::IsOff(def)) + { + macroReportLocation = true; + } + // for each argument of the current function for (std::vector::const_iterator k = m_Functions[c].m_Arguments.begin(); @@ -194,9 +202,7 @@ bool cmMacroHelperCommand::InvokeInitialPass arg.Value = tmps; arg.Quoted = k->Quoted; - const char* def = - m_Makefile->GetDefinition("CMAKE_MACRO_REPORT_DEFINITION_LOCATION"); - if(def && !cmSystemTools::IsOff(def)) + if(macroReportLocation) { // Report the location of the argument where the macro was // defined. diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 130d04a346..61ab3ba783 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1355,7 +1355,8 @@ const char *cmMakefile::ExpandVariablesInString(std::string& source, bool escapeQuotes, bool atOnly, const char* filename, - long line) const + long line, + bool removeEmpty) const { // This method replaces ${VAR} and @VAR@ where VAR is looked up // with GetDefinition(), if not found in the map, nothing is expanded. @@ -1491,7 +1492,7 @@ const char *cmMakefile::ExpandVariablesInString(std::string& source, if (!found) { // if no definition is found then add the var back - if(endVariableMarker == '@') + if(!removeEmpty && endVariableMarker == '@') { result += "@"; result += var; @@ -2311,8 +2312,8 @@ void cmMakefile::ConfigureString(const std::string& input, } // Perform variable replacements. - this->ExpandVariablesInString(output, escapeQuotes, atOnly); - this->RemoveVariablesInString(output, atOnly); + this->ExpandVariablesInString(output, escapeQuotes, atOnly, 0, -1, true); +// this->RemoveVariablesInString(output, atOnly); } int cmMakefile::ConfigureFile(const char* infile, const char* outfile, diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index d796d96a1d..75dfb7ef4b 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -542,7 +542,8 @@ public: const char *ExpandVariablesInString(std::string& source, bool escapeQuotes, bool atOnly = false, const char* filename = 0, - long line = -1) const; + long line = -1, + bool removeEmpty = false) const; /** * Remove any remaining variables in the string. Anything with ${var} or