vsgene/vs_generate.cpp

201 lines
6.0 KiB
C++
Raw Permalink Normal View History

2024-03-08 12:00:42 +08:00
#include "vs_generate.h"
#include <cassert>
#include <fstream>
#include <regex>
#include <string>
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<std::string> 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<ProjectInfo> 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();
}
}