#include "vs_generate.h" #include #include #include #include VsParseSln::VsParseSln() = default; // 解析关联 void VsParseSln::parse_relate() { for (auto& proj : projs_) { for (auto& relate : proj.guid_relate_) { std::string opth = hashmap_[relate]; proj.relate_.push_back(opth); } } } bool VsParseSln::parse(const std::string& path) { std::ifstream sln_file(path, std::ios::in); if (!sln_file.is_open()) { std::cout << "没有找到 sln 文件或者打开文件失败,路径:" << path << "\n"; return false; } fs::path full_path(path); fs::path parent_path = full_path.parent_path(); projs_.clear(); std::string tmp{}; std::regex re(R"(\"(.*?)\")"); std::regex re2(R"((\{.*?\}))"); std::smatch match{}; ProjectInfo proj{}; bool related = false; bool add = false; while (std::getline(sln_file, tmp)) { if (tmp.find("Project") != std::string::npos && tmp.find(".vcxproj") != std::string::npos) { std::vector vec{}; while (std::regex_search(tmp, match, re)) { vec.push_back(match[1]); tmp = match.suffix().str(); } // 这里应该有4个结果 assert(vec.size() == 4); proj.guid_ = vec[3]; proj.path_ = parent_path.string() + "\\" + vec[2]; add = true; } if (tmp.find("ProjectDependencies") != std::string::npos) { related = true; continue; } if (tmp.find("EndProjectSection") != std::string::npos) { related = false; continue; } if (related) { // 这里要简单处理一下 if (std::regex_search(tmp, match, re2)) { std::string restr = match[1]; proj.guid_relate_.push_back(restr); } } if (tmp.find("EndProject") != std::string::npos && add) { projs_.push_back(proj); hashmap_[proj.guid_] = proj.path_; proj.guid_relate_.clear(); add = false; } } parse_relate(); sln_file.close(); return true; } std::vector VsParseSln::get_project() const { return projs_; } void VsParsePro::handle_include(tinyxml2::XMLElement* node, const std::string& key) const { if (!node) { return; } const char* data = node->Attribute("Condition"); if (!data) { return; } if (std::string(data).find(key) == std::string::npos) { return; } tinyxml2::XMLElement* purpose = node->FirstChildElement(); while (purpose) { const char* name = purpose->Name(); if (std::strcmp(name, "IncludePath") != 0) { purpose = purpose->NextSiblingElement(); continue; } const char* include_path = purpose->GetText(); current_proj_->addtion_.append(";"); current_proj_->addtion_.append(include_path); break; } } void VsParsePro::additon_include_and_predefine(tinyxml2::XMLElement* node, const std::string& key) const { if (!node) { return; } const char* data = node->Attribute("Condition"); if (!data) { return; } if (std::string(data).find(key) == std::string::npos) { return; } tinyxml2::XMLElement* cl = get_child_element(node, "ClCompile"); const tinyxml2::XMLElement* purpose = get_child_element(cl, "AdditionalIncludeDirectories"); if (purpose) { const char* addtion_dir = purpose->GetText(); current_proj_->addtion_.append(";"); current_proj_->addtion_.append(addtion_dir); } purpose = get_child_element(cl, "PreprocessorDefinitions"); if (purpose) { const char* predefinition = purpose->GetText(); current_proj_->predefinition_.append(";"); current_proj_->predefinition_.append(predefinition); } } tinyxml2::XMLElement* VsParsePro::get_child_element(tinyxml2::XMLElement* node, const std::string& key) { tinyxml2::XMLElement* result{}; if (!node) { return result; } tinyxml2::XMLElement* n = node->FirstChildElement(); while (n) { if (std::strcmp(n->Name(), key.c_str()) == 0) { result = n; break; } n = n->NextSiblingElement(); } return result; } bool VsParsePro::parse(ProjectInfo* proj, const std::string& key) { current_proj_ = proj; supplement(current_proj_); int ret = m_doc_.LoadFile(current_proj_->path_.c_str()); if (ret != 0) { std::cout << "解析失败:" << current_proj_->path_ << "\n"; return false; } tinyxml2::XMLElement* element = m_doc_.FirstChildElement(); if (std::strcmp(element->Name(), "Project") != 0) { std::cout << "不是合法的vcxproj文件。" << current_proj_->path_ << "\n"; return false; } addition_dir_.clear(); tinyxml2::XMLElement* node = element->FirstChildElement(); while (node) { if (std::strcmp(node->Name(), "PropertyGroup") == 0) { handle_include(node, key); } if (std::strcmp(node->Name(), "ItemDefinitionGroup") == 0) { additon_include_and_predefine(node, key); } node = node->NextSiblingElement(); } tidy(current_proj_); return true; } // 对初步解析出的工程进行整理 void VsParsePro::tidy(ProjectInfo* proj) {} // 补充其他信息 void VsParsePro::supplement(ProjectInfo* proj) { if (proj->path_.empty() || !fs::exists(proj->path_)) { return; } fs::path path(proj->path_); if (proj->proj_root_.empty()) { proj->proj_root_ = path.parent_path().string(); } if (proj->name_.empty()) { proj->name_ = path.filename().string(); } }