diff options
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | libcppbuild.cc | 72 | ||||
-rw-r--r-- | task.cc | 263 | ||||
-rw-r--r-- | task.h | 30 | ||||
-rw-r--r-- | task_cc.cc | 267 | ||||
-rw-r--r-- | task_cc.h | 38 | ||||
-rw-r--r-- | task_ld.cc | 89 | ||||
-rw-r--r-- | task_ld.h | 38 |
8 files changed, 464 insertions, 342 deletions
@@ -1,12 +1,13 @@ all: libcppbuild.a cppbuild -libcppbuild.a: libcppbuild.cc task.cc libcppbuild.h +libcppbuild.a: libcppbuild.cc libcppbuild.h task_cc.cc task_cc.h task_ld.cc task_ld.h task.h g++ -g -std=c++17 libcppbuild.cc -c -o libcppbuild.o - g++ -g -std=c++17 task.cc -c -o task.o - ar rcs libcppbuild.a libcppbuild.o task.o + g++ -g -std=c++17 task_cc.cc -c -o task_cc.o + g++ -g -std=c++17 task_ld.cc -c -o task_ld.o + ar rcs libcppbuild.a libcppbuild.o task_cc.o task_ld.o cppbuild: cppbuild.cc libcppbuild.h libcppbuild.a g++ -g -std=c++17 cppbuild.cc libcppbuild.a -pthread -o cppbuild clean: - rm -f cppbuild libcppbuild.o task.o libcppbuild.a + rm -f cppbuild libcppbuild.o task_cc.o task_ld.o libcppbuild.a diff --git a/libcppbuild.cc b/libcppbuild.cc index 2167173..c75f43e 100644 --- a/libcppbuild.cc +++ b/libcppbuild.cc @@ -6,9 +6,11 @@ #include <list> #include <chrono> #include <thread> +#include <memory> #include "libcppbuild.h" -#include "task.h" +#include "task_cc.h" +#include "task_ld.h" #include "settings.h" #include <unistd.h> @@ -29,31 +31,33 @@ int main(int argc, const char* argv[]) std::filesystem::create_directories(builddir); auto config = configs(); - std::string output = builddir / config.target; - const auto& files = config.sources; - std::vector<std::string> objects; - - std::vector<Task> tasks; - for(const auto& file : files) + std::vector<std::string> objects; + std::vector<std::unique_ptr<Task>> tasks; + for(const auto& file : config.sources) { - tasks.emplace_back(config, settings, file); - objects.push_back(tasks.back().target()); + tasks.emplace_back(std::make_unique<TaskCC>(config, settings, file)); + objects.push_back(tasks.back()->target()); } + TaskLD task_ld(config, settings, config.target, objects); + if(argc == 2 && std::string(argv[1]) == "clean") { std::cout << "Cleaning\n"; //std::filesystem::remove_all(builddir); for(auto& task : tasks) { - if(task.clean() != 0) + if(task->clean() != 0) { return 1; } } - std::filesystem::remove(output); + if(task_ld.clean() != 0) + { + return 1; + } return 0; } @@ -69,7 +73,7 @@ int main(int argc, const char* argv[]) while(processes.size() < settings.parallel_processes && task != tasks.end()) { - if(!task->dirty()) + if(!(*task)->dirty()) { ++task; continue; @@ -77,9 +81,9 @@ int main(int argc, const char* argv[]) processes.emplace_back( std::async(std::launch::async, - [task]() + [&t = *task]() { - return task->run(); + return t->run(); })); ++task; std::this_thread::sleep_for(2ms); @@ -108,49 +112,17 @@ int main(int argc, const char* argv[]) ++process) { process->wait(); - if(process->get() != 0) + auto ret = process->get(); + if(ret != 0) { 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 + " " + - config.ldflags + " " + - "-o " + output; - std::cout << compiler << "\n"; - if(system(compiler.data())) + if(task_ld.dirty()) { - return 1; + return task_ld.run(); } return 0; @@ -1,263 +0,0 @@ -#include "task.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 :: - -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<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()); - } -#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<std::string> Task::depends() const -{ - return {}; -} - -std::string Task::target() const -{ - return targetFile; -} @@ -3,33 +3,13 @@ #include <vector> #include <string> -#include <future> -#include <filesystem> - -struct BuildConfiguration; -struct Settings; class Task { public: - Task(const BuildConfiguration& config, - const Settings& settings, - const std::string& source); - - bool dirty(); - - int run(); - int clean(); - - std::vector<std::string> depends() const; - - std::string target() const; - -private: - std::filesystem::path sourceFile; - std::filesystem::path targetFile; - std::filesystem::path depsFile; - - const BuildConfiguration& config; - const Settings& settings; + virtual bool dirty() = 0; + virtual int run() = 0; + virtual int clean() = 0 ; + virtual std::vector<std::string> depends() const = 0; + virtual std::string target() const = 0; }; 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; +} diff --git a/task_cc.h b/task_cc.h new file mode 100644 index 0000000..c73a1e5 --- /dev/null +++ b/task_cc.h @@ -0,0 +1,38 @@ +// -*- c++ -*- +#pragma once + +#include "task.h" + +#include <vector> +#include <string> +#include <future> +#include <filesystem> + +struct BuildConfiguration; +struct Settings; + +class TaskCC + : public Task +{ +public: + TaskCC(const BuildConfiguration& config, + const Settings& settings, + const std::string& source); + + bool dirty() override; + + int run() override; + int clean() override; + + std::vector<std::string> depends() const override; + + std::string target() const override; + +private: + std::filesystem::path sourceFile; + std::filesystem::path targetFile; + std::filesystem::path depsFile; + + const BuildConfiguration& config; + const Settings& settings; +}; diff --git a/task_ld.cc b/task_ld.cc new file mode 100644 index 0000000..235523f --- /dev/null +++ b/task_ld.cc @@ -0,0 +1,89 @@ +#include "task_ld.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" + +TaskLD::TaskLD(const BuildConfiguration& config, + const Settings& settings, + const std::string& target, + const std::vector<std::string>& objects) + : config(config) + , settings(settings) +{ + targetFile = settings.builddir; + targetFile /= target; + for(const auto& object : objects) + { + //std::filesystem::path objectFile = settings.builddir; + //objectFile /= object; + std::filesystem::path objectFile = object; + objectFiles.push_back(objectFile); + } +} + +bool TaskLD::dirty() +{ + if(!std::filesystem::exists(targetFile)) + { + return true; + } + + for(const auto& objectFile : objectFiles) + { + if(std::filesystem::last_write_time(targetFile) <= + std::filesystem::last_write_time(objectFile)) + { + return true; + } + } + + return false; +} + +int TaskLD::run() +{ + std::string objectlist; + for(const auto& objectFile : objectFiles) + { + if(!objectlist.empty()) + { + objectlist += " "; + } + objectlist += std::string(objectFile); + } + + std::string compiler = "g++ " + objectlist + " " + + config.ldflags + " " + + "-o " + std::string(targetFile); + std::cout << compiler << "\n"; + if(system(compiler.data())) + { + return 1; + } + return 0; +} + +int TaskLD::clean() +{ + std::filesystem::remove(targetFile); + return 0; +} + +std::vector<std::string> TaskLD::depends() const +{ + return {}; +} + +std::string TaskLD::target() const +{ + std::cout << "Removing " << std::string(targetFile) << "\n"; + return std::string(targetFile); +} diff --git a/task_ld.h b/task_ld.h new file mode 100644 index 0000000..709f238 --- /dev/null +++ b/task_ld.h @@ -0,0 +1,38 @@ +// -*- c++ -*- +#pragma once + +#include "task.h" + +#include <vector> +#include <string> +#include <future> +#include <filesystem> + +struct BuildConfiguration; +struct Settings; + +class TaskLD + : public Task +{ +public: + TaskLD(const BuildConfiguration& config, + const Settings& settings, + const std::string& target, + const std::vector<std::string>& objects); + + bool dirty() override; + + int run() override; + int clean() override; + + std::vector<std::string> depends() const override; + + std::string target() const override; + +private: + std::vector<std::filesystem::path> objectFiles; + std::filesystem::path targetFile; + + const BuildConfiguration& config; + const Settings& settings; +}; |