diff options
Diffstat (limited to 'task_cc.cc')
-rw-r--r-- | task_cc.cc | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/task_cc.cc b/task_cc.cc new file mode 100644 index 0000000..2a65698 --- /dev/null +++ b/task_cc.cc @@ -0,0 +1,267 @@ +#include "task_cc.h" + +#include <iostream> +#include <fstream> +#include <unistd.h> +#include <cstring> +#include <sys/types.h> +#include <sys/wait.h> +#include <spawn.h> + +#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<char> bytes(fileSize); + ifs.read(bytes.data(), fileSize); + + return std::string(bytes.data(), fileSize); +} + +std::vector<std::string> readDeps(const std::string& depFile) +{ + if(!std::filesystem::exists(depFile)) + { + return {}; + } + + auto str = readFile(depFile); + + std::vector<std::string> 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 :: + +TaskCC::TaskCC(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 TaskCC::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 TaskCC::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<const char*> 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()); + } + auto ret = parent_waitpid(pid); +#elif 0 + pid_t pid; + if(posix_spawn(&pid, comp.data(), nullptr, nullptr, (char**)argv.data(), nullptr)) + { + return 1;//exit(1); + } + auto ret = parent_waitpid(pid); +#else + auto ret = system(cmd.data()); +#endif + + return ret; +} + +int TaskCC::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<std::string> TaskCC::depends() const +{ + return {}; +} + +std::string TaskCC::target() const +{ + return targetFile; +} |