From 9043436e67a8512792bd4f0fa73a453ab5c37c5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 20 Nov 2016 22:44:50 +0100 Subject: [PATCH] Visual Studio: Improved --project handling. --- lib/importproject.cpp | 96 +++++++++++++++++++++++++++++-------------- lib/importproject.h | 2 +- 2 files changed, 66 insertions(+), 32 deletions(-) diff --git a/lib/importproject.cpp b/lib/importproject.cpp index 5b9122f6f..a2c7284c6 100644 --- a/lib/importproject.cpp +++ b/lib/importproject.cpp @@ -91,6 +91,29 @@ void ImportProject::FileSettings::setDefines(std::string defs) defines.swap(defs); } +static bool simplifyPathWithVariables(std::string &s, const std::map &variables) +{ + std::set expanded; + std::string::size_type start = 0; + while ((start = s.find("$(")) != std::string::npos) { + std::string::size_type end = s.find(")",start); + if (end == std::string::npos) + break; + const std::string &var = s.substr(start+2,end-start-2); + if (expanded.find(var) != expanded.end()) + break; + expanded.insert(var); + std::map::const_iterator it1 = variables.find(var); + if (it1 == variables.end()) + break; + s = s.substr(0,start) + it1->second + s.substr(end+1); + } + if (s.find("$(") != std::string::npos) + return false; + s = Path::simplifyPath(Path::fromNativeSeparators(s)); + return true; +} + void ImportProject::FileSettings::setIncludePaths(const std::string &basepath, const std::list &in, const std::map &variables) { std::list I; @@ -113,24 +136,8 @@ void ImportProject::FileSettings::setIncludePaths(const std::string &basepath, c if (s.find("$(")==std::string::npos) { s = Path::simplifyPath(basepath + s); } else { - std::set expanded; - std::string::size_type start = 0; - while ((start = s.find("$(")) != std::string::npos) { - std::string::size_type end = s.find(")",start); - if (end == std::string::npos) - break; - const std::string &var = s.substr(start+2,end-start-2); - if (expanded.find(var) != expanded.end()) - break; - expanded.insert(var); - std::map::const_iterator it1 = variables.find(var); - if (it1 == variables.end()) - break; - s = s.substr(0,start) + it1->second + s.substr(end+1); - } - if (s.find("$(") != std::string::npos) + if (!simplifyPathWithVariables(s,variables)) continue; - s = Path::simplifyPath(Path::fromNativeSeparators(s)); } if (s.empty()) continue; @@ -213,10 +220,13 @@ void ImportProject::importCompileCommands(std::istream &istr) } } -static void loadVisualStudioProperties(const std::string &props, std::map *variables, std::string *additionalIncludeDirectories) +static void loadVisualStudioProperties(const std::string &props, std::map *variables, std::string *includePath, std::string *additionalIncludeDirectories) { + std::string filename(props); + if (!simplifyPathWithVariables(filename,*variables)) + return; tinyxml2::XMLDocument doc; - if (doc.LoadFile(props.c_str()) != tinyxml2::XML_SUCCESS) + if (doc.LoadFile(filename.c_str()) != tinyxml2::XML_SUCCESS) return; const tinyxml2::XMLElement * const rootnode = doc.FirstChildElement(); if (rootnode == nullptr) @@ -225,14 +235,29 @@ static void loadVisualStudioProperties(const std::string &props, std::mapName(), "ImportGroup") == 0 && node->Attribute("Label") && std::strcmp(node->Attribute("Label"),"PropertySheets")==0) { for (const tinyxml2::XMLElement *importGroup = node->FirstChildElement(); importGroup; importGroup = importGroup->NextSiblingElement()) { if (std::strcmp(importGroup->Name(), "Import") == 0 && importGroup->Attribute("Project")) { - loadVisualStudioProperties(Path::getPathFromFilename(props)+importGroup->Attribute("Project"), variables, additionalIncludeDirectories); + loadVisualStudioProperties(importGroup->Attribute("Project"), variables, includePath, additionalIncludeDirectories); } } - } else if (std::strcmp(node->Name(),"PropertyGroup")==0 && node->Attribute("Label") && std::strcmp(node->Attribute("Label"),"UserMacros")==0) { - for (const tinyxml2::XMLElement *propertyGroup = node->FirstChildElement(); propertyGroup; propertyGroup = propertyGroup->NextSiblingElement()) { - const std::string name(propertyGroup->Name()); - const char *text = propertyGroup->GetText(); - (*variables)[name] = std::string(text ? text : ""); + } else if (std::strcmp(node->Name(),"PropertyGroup")==0) { + if (node->Attribute("Label") && std::strcmp(node->Attribute("Label"),"UserMacros")==0) { + for (const tinyxml2::XMLElement *propertyGroup = node->FirstChildElement(); propertyGroup; propertyGroup = propertyGroup->NextSiblingElement()) { + const std::string name(propertyGroup->Name()); + const char *text = propertyGroup->GetText(); + (*variables)[name] = std::string(text ? text : ""); + } + } else if (!node->Attribute("Label")) { + for (const tinyxml2::XMLElement *propertyGroup = node->FirstChildElement(); propertyGroup; propertyGroup = propertyGroup->NextSiblingElement()) { + if (std::strcmp(propertyGroup->Name(), "IncludePath") != 0) + continue; + const char *text = propertyGroup->GetText(); + if (!text) + continue; + std::string s(text); + std::string::size_type pos = s.find("$(IncludePath)"); + if (pos != std::string::npos) + s = s.substr(0,pos) + *includePath + s.substr(pos+14U); + *includePath = s; + } } } else if (std::strcmp(node->Name(),"ItemDefinitionGroup")==0) { for (const tinyxml2::XMLElement *clcompile = node->FirstChildElement(); clcompile; clcompile = clcompile->NextSiblingElement()) { @@ -257,7 +282,6 @@ void ImportProject::importSln(std::istream &istr, const std::string &path) std::map variables; variables["SolutionDir"] = path; std::string additionalIncludeDirectories; - loadVisualStudioProperties(path + "propertysheets/custom.props", &variables, &additionalIncludeDirectories); std::string line; while (std::getline(istr,line)) { @@ -270,7 +294,6 @@ void ImportProject::importSln(std::istream &istr, const std::string &path) if (pos == std::string::npos) continue; const std::string vcxproj(line.substr(pos1+1, pos-pos1+7)); - //std::cout << "Importing " << vcxproj << "..." << std::endl; importVcxproj(path + Path::fromNativeSeparators(vcxproj), variables, additionalIncludeDirectories); } } @@ -326,7 +349,7 @@ namespace { } bool conditionIsTrue(const ProjectConfiguration &p) const { - std::string c = condition; + std::string c = '(' + condition + ");"; replaceAll(c, "$(Configuration)", p.configuration); replaceAll(c, "$(Platform)", p.platform); @@ -367,13 +390,14 @@ static std::list toStringList(const std::string &s) return ret; } -void ImportProject::importVcxproj(const std::string &filename, std::map variables, const std::string &additionalIncludeDirectories) +void ImportProject::importVcxproj(const std::string &filename, std::map variables, std::string additionalIncludeDirectories) { - variables["ProjectDir"] = Path::getPathFromFilename(filename); + variables["ProjectDir"] = Path::simplifyPath(Path::getPathFromFilename(filename)); std::list projectConfigurationList; std::list compileList; std::list itemDefinitionGroupList; + std::string includePath; bool useOfMfc = false; @@ -404,6 +428,16 @@ void ImportProject::importVcxproj(const std::string &filename, std::mapName(), "UseOfMfc") == 0) useOfMfc = true; } + } else if (std::strcmp(node->Name(), "ImportGroup") == 0) { + if (node->Attribute("Label") && std::strcmp(node->Attribute("Label"), "PropertySheets") == 0) { + for (const tinyxml2::XMLElement *e = node->FirstChildElement(); e; e = e->NextSiblingElement()) { + if (std::strcmp(e->Name(), "Import") == 0) { + const char *Project = e->Attribute("Project"); + if (Project) + loadVisualStudioProperties(Project, &variables, &includePath, &additionalIncludeDirectories); + } + } + } } } @@ -425,7 +459,7 @@ void ImportProject::importVcxproj(const std::string &filename, std::mapadditionalIncludePaths), variables); + fs.setIncludePaths(Path::getPathFromFilename(filename), toStringList(includePath + ';' + i->additionalIncludePaths), variables); fileSettings.push_back(fs); } } diff --git a/lib/importproject.h b/lib/importproject.h index 93fe60d88..450e642df 100644 --- a/lib/importproject.h +++ b/lib/importproject.h @@ -60,7 +60,7 @@ public: private: void importCompileCommands(std::istream &istr); void importSln(std::istream &istr, const std::string &path); - void importVcxproj(const std::string &filename, std::map variables, const std::string &additionalIncludeDirectories); + void importVcxproj(const std::string &filename, std::map variables, std::string additionalIncludeDirectories); }; /// @}