#include "vs_json.h" #include #include #include JsonCommand::JsonCommand() = default; JsonCommand::~JsonCommand() = default; void JsonCommand::set_expect(const std::string& exp) { expect_ = exp; } void JsonCommand::set_out(const std::string& out) { out_ = out; } bool JsonCommand::generate(const std::vector& projs) { Json::Value json_root{}; for (const auto& item : projs) { const auto& cpps = get_cpp_paths(item.proj_root_); std::string command = get_command(&item, projs); for (const auto& cpp : cpps) { Json::Value jsn{}; jsn["directory"] = item.proj_root_; jsn["command"] = command + " -c " + cpp; // NOLINT jsn["file"] = cpp; json_root.append(jsn); } } std::ofstream jsf(out_, std::ios::out); if (!jsf.is_open()) { std::cout << "不能打开文件:" << std::endl; return false; } jsf << json_root.toStyledString(); jsf.close(); return true; } std::string JsonCommand::get_command(const ProjectInfo* proj, const std::vector& projs) { std::string result{}; result.append( R"("C:\PROGRA~2\Microsoft Visual Studio 14.0\VC\bin\amd64\cl.exe")"); std::string co_include = proj->addtion_; std::string co_predefinitions = proj->predefinition_; std::string speciaA("$(IncludePath)"); std::string speciaB("%(PreprocessorDefinitions)"); std::string speciaC("%(AdditionalIncludeDirectories)"); std::string speciaD("$(WindowsSDK_IncludePath)"); std::string speciaE("$(VC_IncludePath)"); replaceAll(co_include, speciaA, ""); replaceAll(co_include, speciaC, ""); replaceAll(co_include, speciaD, ""); replaceAll(co_include, speciaE, ""); replaceAll(co_predefinitions, speciaB, ""); auto include_vec = split(co_include, ";"); auto prede_vec = split(co_predefinitions, ";"); for (const auto& str : prede_vec) { if (str.empty()) { continue; } result.append(" -D" + str); } for (const auto& str : include_vec) { if (str.empty()) { continue; } if (expect_.find(str) != std::string::npos) { continue; } result.append(" -I" + fs::path(proj->proj_root_).append(str).string()); } std::list proj_list{}; std::vector re_relate{}; auto handle = [&](const std::vector& lrelate) { for (const auto& str : lrelate) { proj_list.push_back(str); } }; for (const auto& str : proj->guid_relate_) { // 这里的relate 子项目有别的依赖的话都需要加上 // 这里假定不会出现循环引用的情况 (理论也不应该出现) for (const auto& pj : projs) { if (pj.guid_ == str) { handle(pj.guid_relate_); re_relate.push_back(pj.path_); break; } } //std::string dir = fs::path(str).parent_path().string(); //result.append(" -I" + dir); } while (!proj_list.empty()) { std::string& data = proj_list.front(); for (const auto& pj : projs) { if (data == pj.guid_) { handle(pj.guid_relate_); re_relate.push_back(pj.path_); break; } } proj_list.pop_front(); } // 去重 std::set no_reply{}; for (const auto& str : re_relate) { no_reply.insert(str); } for (const auto& str : no_reply) { std::string dir = fs::path(str).parent_path().string(); result.append(" -I" + dir); } // std::cout << result << std::endl; return result; } std::vector JsonCommand::split(const std::string& source, const std::string& sep) { std::vector tokens; std::size_t start = 0; std::size_t end = 0; while ((end = source.find(sep, start)) != std::string::npos) { tokens.push_back(source.substr(start, end - start)); start = end + sep.length(); } tokens.push_back(source.substr(start)); return tokens; } std::vector JsonCommand::get_cpp_paths( const std::string& parent_path) { std::vector vec{}; try { for (const auto& entry : fs::directory_iterator(parent_path)) { if (!fs::is_regular_file(entry.path())) { continue; } const fs::path& file_path(entry.path()); if (file_path.extension().string() == ".cpp") { vec.push_back(file_path.string()); } } } catch (fs::filesystem_error& e) { std::cout << "Error: " << e.what() << std::endl; } return vec; } void JsonCommand::replaceAll(std::string& str, const std::string& from, const std::string& to) { size_t start_pos = 0; while ((start_pos = str.find(from, start_pos)) != std::string::npos) { str.replace(start_pos, from.length(), to); start_pos += to.length(); } }