From 7a16146600384272baf7fb2fc0fc64f59b17ffe9 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 8 Jun 2022 17:38:01 +0200 Subject: Function target type including support for generated sources. --- src/libctor.h | 9 +++++ src/task.cc | 2 +- src/task.h | 1 + src/task_cc.cc | 14 +++++++ src/task_cc.h | 3 ++ src/task_fn.cc | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/task_fn.h | 47 ++++++++++++++++++++++ src/tasks.cc | 33 +++++++++++++--- 8 files changed, 223 insertions(+), 7 deletions(-) create mode 100644 src/task_fn.cc create mode 100644 src/task_fn.h (limited to 'src') diff --git a/src/libctor.h b/src/libctor.h index b539910..14fdf1d 100644 --- a/src/libctor.h +++ b/src/libctor.h @@ -9,6 +9,7 @@ #include #include #include +#include enum class TargetType { @@ -20,6 +21,7 @@ enum class TargetType Object, UnitTest, UnitTestLib, + Function, }; enum class Language @@ -69,6 +71,12 @@ struct Settings int verbose{0}; // -1: completely silent, 0: normal, 1: verbose, ... }; +struct BuildConfiguration; +using GeneratorCb = std::function; + struct BuildConfiguration { std::string name; // Name - used for referring in other configurations. @@ -79,6 +87,7 @@ struct BuildConfiguration std::vector depends; // internal target dependencies Flags flags; std::vector externals; // externals used by this configuration + GeneratorCb function; }; using BuildConfigurations = std::vector; diff --git a/src/task.cc b/src/task.cc index 37e1879..fb50765 100644 --- a/src/task.cc +++ b/src/task.cc @@ -36,7 +36,7 @@ int Task::registerDepTasks(const std::set>& tasks) } } - return 0; + return registerDepTasksInner(tasks); } bool Task::operator==(const std::string& depStr) diff --git a/src/task.h b/src/task.h index a43e08f..be3995f 100644 --- a/src/task.h +++ b/src/task.h @@ -30,6 +30,7 @@ public: const std::string& sourceDir); int registerDepTasks(const std::set>& tasks); + virtual int registerDepTasksInner(const std::set>& tasks) { return 0; } bool operator==(const std::string& dep); diff --git a/src/task_cc.cc b/src/task_cc.cc index ee25abf..a55a619 100644 --- a/src/task_cc.cc +++ b/src/task_cc.cc @@ -17,6 +17,7 @@ TaskCC::TaskCC(const BuildConfiguration& config, const Settings& settings, , config(config) , settings(settings) , sourceDir(sourceDir) + , _source(source) { sourceFile = sourceDir; sourceFile /= source.file; @@ -66,6 +67,19 @@ TaskCC::TaskCC(const BuildConfiguration& config, const Settings& settings, flagsFile += ".flags"; } +int TaskCC::registerDepTasksInner(const std::set>& tasks) +{ + for(const auto& task : tasks) + { + if(*task == _source.file) + { + dependsTasks.insert(task); + } + } + + return 0; +} + std::string TaskCC::name() const { return {}; diff --git a/src/task_cc.h b/src/task_cc.h index 26c81a4..0a0d96a 100644 --- a/src/task_cc.h +++ b/src/task_cc.h @@ -22,6 +22,8 @@ public: const std::string& sourceDir, const Source& source); virtual ~TaskCC() = default; + int registerDepTasksInner(const std::set>& tasks) override; + std::string name() const override; bool dirtyInner() override; @@ -52,4 +54,5 @@ protected: const BuildConfiguration& config; const Settings& settings; std::filesystem::path sourceDir; + const Source& _source; }; diff --git a/src/task_fn.cc b/src/task_fn.cc new file mode 100644 index 0000000..ab00fae --- /dev/null +++ b/src/task_fn.cc @@ -0,0 +1,121 @@ +// -*- c++ -*- +// Distributed under the BSD 2-Clause License. +// See accompanying file LICENSE for details. +#include "task_fn.h" + +#include +#include +#include + +#include "libctor.h" +#include "execute.h" +#include "util.h" + +TaskFn::TaskFn(const BuildConfiguration& config, const Settings& settings, + const std::string& sourceDir, const Source& source) + : Task(config, settings, sourceDir) + , config(config) + , settings(settings) +{ + sourceFile = sourceDir; + sourceFile /= source.file; + + std::filesystem::create_directories(std::filesystem::path(settings.builddir) / sourceFile.parent_path()); + + target_type = config.type; + source_language = source.language; + + if(source.output.empty()) + { + std::cerr << "Missing output file for functional target\n"; + exit(1); + } + + _targetFile = source.output; +} + +bool TaskFn::dirtyInner() +{ + 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::last_write_time(sourceFile) > + std::filesystem::last_write_time(targetFile())) + { + //std::cout << "The targetFile older than sourceFile\n"; + return true; + } + + return false; +} + +int TaskFn::runInner() +{ + if(!std::filesystem::exists(sourceFile)) + { + std::cout << "Missing source file: " << sourceFile.string() << "\n"; + return 1; + } + + if(settings.verbose >= 0) + { + std::cout << "Fn" << " " << + sourceFile.lexically_normal().string() << " => " << + targetFile().lexically_normal().string() << "\n"; + } + + return config.function(sourceFile.string(), + targetFile().string(), + config, + settings); +} + +int TaskFn::clean() +{ + if(std::filesystem::exists(targetFile())) + { + std::cout << "Removing " << targetFile().string() << "\n"; + std::filesystem::remove(targetFile()); + } + + return 0; +} + +std::vector TaskFn::depends() const +{ + return {}; +} + +std::string TaskFn::target() const +{ + return _targetFile; +} + +std::filesystem::path TaskFn::targetFile() const +{ + return std::filesystem::path(settings.builddir) / sourceDir / _targetFile; +} + +bool TaskFn::derived() const +{ + return false; +} + +std::string TaskFn::toJSON() const +{ + return {}; // TODO: Not sure how to express this... +} + +std::string TaskFn::source() const +{ + return sourceFile.string(); +} diff --git a/src/task_fn.h b/src/task_fn.h new file mode 100644 index 0000000..e350395 --- /dev/null +++ b/src/task_fn.h @@ -0,0 +1,47 @@ +// -*- c++ -*- +// Distributed under the BSD 2-Clause License. +// See accompanying file LICENSE for details. +#pragma once + +#include "task.h" + +#include +#include +#include +#include + +struct BuildConfiguration; +struct Settings; + +class TaskFn + : public Task +{ +public: + TaskFn(const BuildConfiguration& config, + const Settings& settings, + const std::string& sourceDir, const Source& source); + virtual ~TaskFn() = default; + + bool dirtyInner() override; + + int runInner() override; + int clean() override; + + std::vector depends() const override; + + std::string target() const override; + std::filesystem::path targetFile() const override; + bool derived() const override; + + std::string toJSON() const override; + + std::string source() const override; + +protected: + std::filesystem::path sourceFile; + std::filesystem::path _targetFile; + + const BuildConfiguration& config; + const Settings& settings; + std::filesystem::path sourceDir; +}; diff --git a/src/tasks.cc b/src/tasks.cc index 646292a..68b2476 100644 --- a/src/tasks.cc +++ b/src/tasks.cc @@ -15,6 +15,7 @@ #include "task_ld.h" #include "task_ar.h" #include "task_so.h" +#include "task_fn.h" #include "rebuild.h" #include "configure.h" @@ -80,12 +81,18 @@ std::set> taskFactory(const BuildConfiguration& config, const Settings& settings, const std::string& sourceDir) { + std::set> tasks; + std::filesystem::path targetFile(config.target); TargetType target_type{config.type}; if(target_type == TargetType::Auto) { - if(targetFile.extension() == ".a") + if(config.function != nullptr) + { + target_type = TargetType::Function; + } + else if(targetFile.extension() == ".a") { target_type = TargetType::StaticLibrary; } @@ -106,13 +113,26 @@ std::set> taskFactory(const BuildConfiguration& config, } std::vector objects; - std::set> tasks; - for(const auto& file : config.sources) + if(target_type != TargetType::Function) { - auto task = std::make_shared(config, settings, sourceDir, file); - tasks.insert(task); - objects.push_back(task->targetFile().string()); + for(const auto& file : config.sources) + { + auto task = std::make_shared(config, settings, sourceDir, file); + tasks.insert(task); + objects.push_back(task->targetFile().string()); + } } +#ifndef BOOTSTRAP + else + { + for(const auto& file : config.sources) + { + auto task = std::make_shared(config, settings, sourceDir, file); + tasks.insert(task); + objects.push_back(task->target()); + } + } +#endif switch(target_type) { @@ -144,6 +164,7 @@ std::set> taskFactory(const BuildConfiguration& config, break; case TargetType::Object: + case TargetType::Function: break; #else default: -- cgit v1.2.3