#include #include #include #include #include #include #include #include "libcppbuild.h" namespace { std::string readFile(const std::string &fileName) { std::ifstream ifs(fileName.c_str(), std::ios::in | std::ios::binary | std::ios::ate); std::ifstream::pos_type fileSize = ifs.tellg(); ifs.seekg(0, std::ios::beg); std::vector bytes(fileSize); ifs.read(bytes.data(), fileSize); return std::string(bytes.data(), fileSize); } std::vector readDeps(const std::string& depFile) { if(!std::filesystem::exists(depFile)) { return {}; } auto str = readFile(depFile); std::vector output; std::string tmp; bool start{false}; bool in_whitespace{false}; for(const auto& c : str) { if(c == '\\' || c == '\n') { continue; } if(c == ':') { start = true; continue; } if(!start) { continue; } if(c == ' ' || c == '\t') { if(in_whitespace) { continue; } if(!tmp.empty()) { output.push_back(tmp); } tmp.clear(); in_whitespace = true; } else { in_whitespace = false; tmp += c; } } if(!tmp.empty()) { output.push_back(tmp); } return output; } } // namespace :: int main(int argc, const char* argv[]) { if(argc == 2 && std::string(argv[1]) == "clean") { system("rm -Rf build"); return 0; } std::filesystem::path builddir("build/"); std::filesystem::create_directory(builddir); auto project = configs(); std::string output = "build/" + project.target; const auto& files = project.sources; std::vector objects; std::cout << "Building\n"; for(const auto& file : files) { auto path = std::filesystem::path(file); std::string object = builddir / path.stem(); object += ".o"; objects.push_back(object); std::string deps = builddir / path.stem(); deps += ".d"; if(!std::filesystem::exists(file)) { std::cout << "Missing source file: " << file << "\n"; return 1; } bool recompile{false}; if(!std::filesystem::exists(object) || !std::filesystem::exists(deps)) { recompile = true; } if(!recompile && std::filesystem::last_write_time(file) > std::filesystem::last_write_time(deps)) { recompile = true; } if(!recompile) { auto depList = readDeps(deps); for(const auto& dep : depList) { if(!std::filesystem::exists(dep) || std::filesystem::last_write_time(object) < std::filesystem::last_write_time(dep)) { recompile = true; break; } } } if(recompile || !std::filesystem::exists(object) || std::filesystem::last_write_time(file) > std::filesystem::last_write_time(object)) { std::string compiler = "g++ -MMD -c " + file + " -o " + object; std::cout << compiler << "\n"; if(system(compiler.data())) { return 1; } } } std::cout << "Linking\n"; bool dolink{false}; if(!std::filesystem::exists(output)) { dolink = true; } else { for(const auto& object : objects) { if(std::filesystem::last_write_time(output) <= std::filesystem::last_write_time(object)) { dolink = true; break; } } } if(!dolink) { std::cout << "No linking needed\n"; return 0; } std::string objectlist; for(const auto& object : objects) { objectlist += object + " "; } std::string compiler = "g++ " + objectlist + " -o " + output; std::cout << compiler << "\n"; if(system(compiler.data())) { return 1; } return 0; }