diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | libcppbuild.cc | 176 | ||||
-rw-r--r-- | libcppbuild.h | 3 | ||||
-rw-r--r-- | settings.h | 7 | ||||
-rw-r--r-- | src/bar.o | bin | 2848 -> 0 bytes | |||
-rw-r--r-- | task.cc | 199 | ||||
-rw-r--r-- | task.h | 32 |
8 files changed, 276 insertions, 153 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e518938 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +cppbuild +*.a +*.o
\ No newline at end of file @@ -1,11 +1,12 @@ all: libcppbuild.a cppbuild -libcppbuild.a: libcppbuild.cc +libcppbuild.a: libcppbuild.cc task.cc libcppbuild.h g++ -g -std=c++17 libcppbuild.cc -c -o libcppbuild.o - ar rcs libcppbuild.a libcppbuild.o + g++ -g -std=c++17 task.cc -c -o task.o + ar rcs libcppbuild.a libcppbuild.o task.o -cppbuild: cppbuild.cc libcppbuild.a +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 libcppbuild.a + rm -f cppbuild libcppbuild.o task.o libcppbuild.a diff --git a/libcppbuild.cc b/libcppbuild.cc index ddc0b66..46f1bfc 100644 --- a/libcppbuild.cc +++ b/libcppbuild.cc @@ -2,182 +2,60 @@ #include <string> #include <filesystem> #include <iostream> -#include <fstream> -#include <regex> #include <utility> -//#include <thread> -#include <future> #include "libcppbuild.h" +#include "task.h" +#include "settings.h" -namespace -{ -std::string readFile(const std::string &fileName) +int main(int argc, const char* argv[]) { - 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); + Settings settings; + settings.builddir = "build/foo"; + std::filesystem::path builddir(settings.builddir); + std::filesystem::create_directories(builddir); - std::vector<char> bytes(fileSize); - ifs.read(bytes.data(), fileSize); + auto project = configs(); + std::string output = builddir / project.target; + const auto& files = project.sources; + std::vector<std::string> objects; - return std::string(bytes.data(), fileSize); -} + std::vector<Task> tasks; -std::vector<std::string> readDeps(const std::string& depFile) -{ - if(!std::filesystem::exists(depFile)) + for(const auto& file : files) { - return {}; + tasks.emplace_back(project, settings, file); + objects.push_back(tasks.back().targetFile); } - 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(argc == 2 && std::string(argv[1]) == "clean") { - if(c == '\\' || c == '\n') - { - continue; - } - - if(c == ':') - { - start = true; - continue; - } - - if(!start) + std::cout << "Cleaning\n"; + //std::filesystem::remove_all(builddir); + for(auto& task : tasks) { - continue; - } - - if(c == ' ' || c == '\t') - { - if(in_whitespace) - { - continue; - } - - if(!tmp.empty()) + if(task.clean() != 0) { - output.push_back(tmp); + return 1; } - tmp.clear(); - in_whitespace = true; - } - else - { - in_whitespace = false; - tmp += c; } - } - - if(!tmp.empty()) - { - output.push_back(tmp); - } - - return output; -} -} // namespace :: + std::filesystem::remove(output); - -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<std::string> objects; - - std::vector<std::future<int>> tasks; - std::cout << "Building\n"; - for(const auto& file : files) + // Start all tasks + for(auto& task : tasks) { - 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)) - { - - tasks.emplace_back( - std::async(std::launch::async, - [file, object]() - { - std::string compiler = "g++ -MMD -c " + file + " -o " + object; - std::cout << compiler << "\n"; - if(system(compiler.data())) - { - return 1; - } - return 0; - })); - } + task.start(); } + // Wait for all tasks for(auto& task : tasks) { - task.wait(); - if(task.get() != 0) + if(task.wait() != 0) { return 1; } diff --git a/libcppbuild.h b/libcppbuild.h index 11a8eb7..e9599fc 100644 --- a/libcppbuild.h +++ b/libcppbuild.h @@ -7,6 +7,9 @@ struct BuildConfiguration { std::string target; std::vector<std::string> sources; + std::string cxxflags; + std::string cflags; + std::string ldflags; }; BuildConfiguration configs(); diff --git a/settings.h b/settings.h new file mode 100644 index 0000000..302c6d7 --- /dev/null +++ b/settings.h @@ -0,0 +1,7 @@ +// -*- c++ -*- +#pragma once + +struct Settings +{ + std::string builddir; +}; diff --git a/src/bar.o b/src/bar.o Binary files differdeleted file mode 100644 index 37903db..0000000 --- a/src/bar.o +++ /dev/null @@ -0,0 +1,199 @@ +#include "task.h" + +#include <iostream> +#include <fstream> + +#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) +{ + sourceFile = source; + targetFile = settings.builddir / sourceFile.stem(); + targetFile += ".o"; + depsFile = settings.builddir / sourceFile.stem(); + depsFile += ".d"; +} + +void Task::start() +{ + future = + std::async(std::launch::async, + [&]() + { + if(!std::filesystem::exists(sourceFile)) + { + std::cout << "Missing source file: " << std::string(sourceFile) << "\n"; + return 1; + } + + bool recompile{false}; + + if(!recompile && + !std::filesystem::exists(targetFile)) + { + recompile = true; + std::cout << "Missing targetFile\n"; + } + + if(!recompile && + !std::filesystem::exists(depsFile)) + { + recompile = true; + std::cout << "Missing depsFile\n"; + } + + if(!recompile && + std::filesystem::last_write_time(sourceFile) > + std::filesystem::last_write_time(depsFile)) + { + recompile = true; + std::cout << "The sourceFile newer than depsFile\n"; + } + + if(!recompile) + { + 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)) + { + recompile = true; + std::cout << "The targetFile older than dep\n"; + break; + } + } + } + + if(!recompile && + std::filesystem::last_write_time(sourceFile) > + std::filesystem::last_write_time(targetFile)) + { + recompile = true; + std::cout << "The targetFile older than sourceFile\n"; + } + + if(recompile) + { + std::string cmd = + "g++ -MMD -c " + std::string(sourceFile) + + " -o " + std::string(targetFile); + std::cout << cmd << "\n"; + + if(system(cmd.data())) + { + return 1; + } + return 0; + } + + return 0; + }); +} + +int Task::wait() +{ + future.wait(); + return future.get(); +} + +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() +{ + return {}; +} @@ -0,0 +1,32 @@ +// -*- c++ -*- +#pragma once + +#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); + + void start(); + + int wait(); + + int clean(); + + std::vector<std::string> depends(); + + std::filesystem::path sourceFile; + std::filesystem::path targetFile; + std::filesystem::path depsFile; + + std::future<int> future; +}; |