From f6bcdf67b1b981592825d6a6a1c4d3ff122de553 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 20 Dec 2025 15:43:47 +0100 Subject: WIP --- src/ctor.h | 9 +++- src/task_fn.cc | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++------- src/task_fn.h | 4 ++ src/tasks.cc | 16 +++++-- src/util.h | 4 ++ 5 files changed, 152 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/ctor.h b/src/ctor.h index 27b30af..0dcf56b 100644 --- a/src/ctor.h +++ b/src/ctor.h @@ -218,6 +218,11 @@ using GeneratorCb = std::function; +using GeneratorCb2 = std::function& input, + const std::string& output, + const ctor::build_configuration& config, + const ctor::settings& settings)>; + struct build_configuration { std::string name; // Name - used for referring in other configurations. @@ -228,7 +233,9 @@ struct build_configuration std::vector depends; // internal target dependencies ctor::flags flags; std::vector externals; // externals used by this configuration - GeneratorCb function; + std::variant function; }; using build_configurations = std::vector; diff --git a/src/task_fn.cc b/src/task_fn.cc index b6b50ea..a984ef8 100644 --- a/src/task_fn.cc +++ b/src/task_fn.cc @@ -20,6 +20,12 @@ TaskFn::TaskFn(const ctor::build_configuration& config_, const ctor::settings& s { sourceFile /= source.file; + for(const auto& src : config.sources) + { + auto _src = sourceFile / src.file; + sources.push_back(_src.string()); + } + std::filesystem::create_directories(std::filesystem::path(settings.builddir) / sourceFile.parent_path()); target_type = config.type; @@ -27,29 +33,90 @@ TaskFn::TaskFn(const ctor::build_configuration& config_, const ctor::settings& s if(source.output.empty()) { - std::cerr << "Missing output file for functional target\n"; - exit(1); + std::filesystem::path base = sourceFile.parent_path(); + _targetFile = + //std::filesystem::path(settings.builddir) / + base / config.target; + } + else + { + _targetFile = source.output; } - _targetFile = source.output; + sourceListFile = targetFile().parent_path() / targetFile().filename(); + sourceListFile += ".sources"; } bool TaskFn::dirtyInner() { - if(!std::filesystem::exists(sourceFile)) + if(!std::filesystem::exists(targetFile())) { - //std::cout << "Missing source file: " << std::string(sourceFile) << "\n"; + //std::cout << "Missing targetFile\n"; return true; } - if(!std::filesystem::exists(targetFile())) + if(!std::filesystem::exists(sourceListFile)) { - //std::cout << "Missing targetFile\n"; + //std::cout << "Missing sourceListFile\n"; return true; } - if(std::filesystem::last_write_time(sourceFile) > - std::filesystem::last_write_time(targetFile())) + { + auto lastSourceList = readFile(sourceListFile.string()); + if(sourceListString() != lastSourceList) + { + //std::cout << "The compiler sourceList changed\n"; + return true; + } + } + + std::filesystem::file_time_type last_changed{}; + bool missing{false}; + const auto visitor = overloaded + { + [](std::monostate) {}, + [&](ctor::GeneratorCb) + { + if(!std::filesystem::exists(sourceFile)) + { + missing = true; + } + last_changed = std::filesystem::last_write_time(sourceFile); + }, + [&](ctor::GeneratorCb2) + { + bool first{true}; + for(const auto& source : sources) + { + if(!std::filesystem::exists(source)) + { + missing |= true; + } + else + { + if(first) + { + last_changed = std::filesystem::last_write_time(source); + } + else + { + last_changed = + std::max(last_changed, + std::filesystem::last_write_time(source)); + } + } + first = false; + } + }, + }; + std::visit(visitor, config.function); + + if(missing) + { + return true; + } + + if(last_changed > std::filesystem::last_write_time(targetFile())) { //std::cout << "The targetFile older than sourceFile\n"; return true; @@ -60,10 +127,17 @@ bool TaskFn::dirtyInner() int TaskFn::runInner() { - if(!std::filesystem::exists(sourceFile)) - { - std::cout << "Missing source file: " << sourceFile.string() << "\n"; - return 1; +// if(!std::filesystem::exists(sourceFile)) +// { +// std::cout << "Missing source file: " << sourceFile.string() << "\n"; +// return 1; +// } + + { // Write sourceList to file. + std::ofstream sourceListStream(sourceListFile.string()); + std::cout << "Write to sources file: " << sourceListFile.string() << '\n'; + sourceListStream << sourceListString(); + std::cout << "Content: " << sourceListString() << '\n'; } if(settings.verbose >= 0) @@ -74,10 +148,26 @@ int TaskFn::runInner() std::cout << output << std::flush; } - auto res = config.function(sourceFile.string(), - targetFile().string(), - config, - settings); + int res{}; + const auto visitor = overloaded + { + [](std::monostate) {}, + [&](ctor::GeneratorCb cb) + { + res = cb(sourceFile.string(), + targetFile().string(), + config, + settings); + }, + [&](ctor::GeneratorCb2 cb) + { + res = cb(sources, + targetFile().string(), + config, + settings); + }, + }; + std::visit(visitor, config.function); if(res != 0) { std::filesystem::remove(targetFile()); @@ -94,6 +184,12 @@ int TaskFn::clean() std::filesystem::remove(targetFile()); } + if(std::filesystem::exists(sourceListFile)) + { + std::cout << "Removing " << sourceListFile.string() << "\n"; + std::filesystem::remove(sourceListFile); + } + return 0; } @@ -112,6 +208,16 @@ std::filesystem::path TaskFn::targetFile() const return std::filesystem::path(settings.builddir) / sourceDir / _targetFile; } +std::string TaskFn::sourceListString() const +{ + std::string sourceListStr; + for(const auto& source : config.sources) + { + sourceListStr += " " + source.file; + } + return sourceListStr; +} + bool TaskFn::derived() const { return false; diff --git a/src/task_fn.h b/src/task_fn.h index 1bad32c..7740f9e 100644 --- a/src/task_fn.h +++ b/src/task_fn.h @@ -28,6 +28,7 @@ public: std::string target() const override; std::filesystem::path targetFile() const override; + std::string sourceListString() const; bool derived() const override; std::string toJSON() const override; @@ -37,8 +38,11 @@ public: protected: std::filesystem::path sourceFile; std::filesystem::path _targetFile; + std::filesystem::path sourceListFile; const ctor::build_configuration& config; const ctor::settings& settings; std::filesystem::path sourceDir; + + std::vector sources; }; diff --git a/src/tasks.cc b/src/tasks.cc index 94fe269..82d044e 100644 --- a/src/tasks.cc +++ b/src/tasks.cc @@ -85,7 +85,7 @@ std::vector> taskFactory(const ctor::build_configuration& ctor::target_type target_type{config.type}; if(target_type == ctor::target_type::automatic) { - if(config.function != nullptr) + if(!std::holds_alternative(config.function)) { target_type = ctor::target_type::function; } @@ -114,12 +114,22 @@ std::vector> taskFactory(const ctor::build_configuration& #ifndef BOOTSTRAP else { - for(const auto& file : config.sources) + bool multi{std::holds_alternative(config.function)}; + if(multi) { - auto task = std::make_shared(config, settings, sourceDir, file); + auto task = std::make_shared(config, settings, sourceDir, ""); tasks.push_back(task); objects.push_back(task->target()); } + else + { + for(const auto& file : config.sources) + { + auto task = std::make_shared(config, settings, sourceDir, file); + tasks.push_back(task); + objects.push_back(task->target()); + } + } } #endif diff --git a/src/util.h b/src/util.h index 38d89f2..3e689eb 100644 --- a/src/util.h +++ b/src/util.h @@ -39,3 +39,7 @@ std::vector argsplit(const std::string& str); //! Calls the system getenv and sets the string if the env name it exists. //! \returns true if the env name existed, false otherwise. bool get_env(std::string_view name, std::string& value); + +// helper type for the visitor +template +struct overloaded : Ts... { using Ts::operator()...; }; -- cgit v1.2.3