summaryrefslogtreecommitdiff
path: root/task_cc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'task_cc.cc')
-rw-r--r--task_cc.cc267
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;
+}