#include "task.h" #include #include #include #include #include #include #include #include "libcppbuild.h" #include "settings.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 :: Task::Task(const BuildConfiguration& config, const Settings& settings, const std::string& source) : config(config) , settings(settings) { sourceFile = source; targetFile = settings.builddir / sourceFile.stem(); targetFile += ".o"; depsFile = settings.builddir / sourceFile.stem(); depsFile += ".d"; } bool Task::dirty() { if(!std::filesystem::exists(sourceFile)) { //std::cout << "Missing source file: " << std::string(sourceFile) << "\n"; return true; } if(!std::filesystem::exists(targetFile)) { //std::cout << "Missing targetFile\n"; return true; } if(!std::filesystem::exists(depsFile)) { //std::cout << "Missing depsFile\n"; return true; } if(std::filesystem::last_write_time(sourceFile) > std::filesystem::last_write_time(depsFile)) { //std::cout << "The sourceFile newer than depsFile\n"; return true; } auto depList = readDeps(depsFile); for(const auto& dep : depList) { if(!std::filesystem::exists(dep) || std::filesystem::last_write_time(targetFile) < std::filesystem::last_write_time(dep)) { //std::cout << "The targetFile older than " << std::string(dep) << "\n"; return true; } } if(std::filesystem::last_write_time(sourceFile) > std::filesystem::last_write_time(targetFile)) { //std::cout << "The targetFile older than sourceFile\n"; return true; } return false; } int parent_waitpid(pid_t pid) { int status; if(waitpid(pid, &status, 0) != pid) { return 1; } return status; } int Task::run() { if(!std::filesystem::exists(sourceFile)) { std::cout << "Missing source file: " << std::string(sourceFile) << "\n"; return 1; } std::string comp = "/usr/bin/g++"; auto flags = config.cxxflags; if(std::string(sourceFile.extension()) == ".c") { comp = "/usr/bin/gcc"; flags = config.cflags; } char source[256]; strcpy(source, std::string(sourceFile).data()); char target[256]; strcpy(target, std::string(targetFile).data()); char pwd[256]; strcpy(pwd, std::string(std::filesystem::current_path()).data()); std::vector argv; //args.push_back("/bin/echo"); if(comp == "/usr/bin/gcc") { argv.push_back("/usr/bin/gcc"); } else { argv.push_back("/usr/bin/g++"); } argv.push_back("-MMD"); argv.push_back("-c"); argv.push_back(source); argv.push_back("-o"); argv.push_back(target); for(const auto& flag : flags) { argv.push_back(flag.data()); } std::string cmd; for(const auto& arg : argv) { if(arg == nullptr) { break; } if(!cmd.empty()) { cmd += " "; } cmd += arg; } std::cout << cmd << "\n"; #if 0 auto pid = vfork(); if(pid == 0) { execv(comp.data(), (char**)argv.data()); } #else pid_t pid; if(posix_spawn(&pid, comp.data(), nullptr, nullptr, (char**)argv.data(), nullptr)) { return 1;//exit(1); } #endif return parent_waitpid(pid); } int Task::clean() { if(std::filesystem::exists(targetFile)) { std::cout << "Removing " << std::string(targetFile) << "\n"; std::filesystem::remove(targetFile); } if(std::filesystem::exists(depsFile)) { std::cout << "Removing " << std::string(depsFile) << "\n"; std::filesystem::remove(depsFile); } return 0; } std::vector Task::depends() const { return {}; } std::string Task::target() const { return targetFile; }