// -*- c++ -*- // Distributed under the BSD 2-Clause License. // See accompanying file LICENSE for details. #include "task_fn.h" #include #include #include #include "ctor.h" #include "execute.h" #include "util.h" TaskFn::TaskFn(const ctor::build_configuration& config_, const ctor::settings& settings_, const std::string& sourceDir_, const ctor::source& source) : Task(config_, settings_, sourceDir_) , config(config_) , settings(settings_) { std::filesystem::create_directories(std::filesystem::path(settings.builddir) / sourceDir.parent_path()); target_type = config.type; source_language = source.language; if(std::holds_alternative(config.function)) { if(source.source_type == ctor::source_type::generated) { sourceFile = std::filesystem::path(settings.builddir); } sourceFile /= sourceDir / source.file; std::filesystem::path base = sourceFile.parent_path(); if(source.output.empty()) { std::cerr << "Missing target/output file for functional target.\n"; exit(1); } _targetFile = base / source.output; } else if(std::holds_alternative(config.function)) { for(const auto& src : config.sources) { std::filesystem::path _src; if(src.source_type == ctor::source_type::generated) { _src = std::filesystem::path(settings.builddir); } _src /= sourceDir / src.file; sources.push_back(_src.string()); } std::filesystem::path base = sourceDir; if(config.target.empty()) { std::cerr << "Missing target file for functional target\n"; exit(1); } _targetFile = base / config.target; sourceListFile = targetFile().parent_path() / targetFile().filename(); sourceListFile += ".sources"; } } bool TaskFn::dirtyInner() { if(!std::filesystem::exists(targetFile())) { //std::cout << "Missing targetFile\n"; return true; } if(std::holds_alternative(config.function)) { if(!std::filesystem::exists(sourceListFile)) { //std::cout << "Missing sourceListFile\n"; return true; } { 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}; if(std::holds_alternative(config.function)) { if(!std::filesystem::exists(sourceFile)) { missing = true; } last_changed = std::filesystem::last_write_time(sourceFile); } else if(std::holds_alternative(config.function)) { 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; } } if(missing) { return true; } if(last_changed > std::filesystem::last_write_time(targetFile())) { //std::cout << "The targetFile older than sourceFile\n"; return true; } return false; } int TaskFn::runInner() { if(std::holds_alternative(config.function)) { // Write sourceList to file. std::ofstream sourceListStream(sourceListFile.string()); sourceListStream << sourceListString(); } if(settings.verbose >= 0) { std::string output = "Fn " + sourceFile.lexically_normal().string() + " => " + targetFile().lexically_normal().string() + '\n'; std::cout << output << std::flush; } int res{}; if(std::holds_alternative(config.function)) { } else if(std::holds_alternative(config.function)) { auto func = std::get(config.function); res = func(sourceFile.string(), targetFile().string(), config, settings); } else if(std::holds_alternative(config.function)) { auto func = std::get(config.function); res = func(sources, targetFile().string(), config, settings); } if(res != 0) { std::filesystem::remove(targetFile()); } return res; } int TaskFn::clean() { if(std::filesystem::exists(targetFile())) { std::cout << "Removing " << targetFile().string() << "\n"; std::filesystem::remove(targetFile()); } if(std::holds_alternative(config.function)) { if(std::filesystem::exists(sourceListFile)) { std::cout << "Removing " << sourceListFile.string() << "\n"; std::filesystem::remove(sourceListFile); } } return 0; } std::vector TaskFn::depends() const { std::vector deps; if(std::holds_alternative(config.function)) { for(const auto& src : config.sources) { if(src.source_type == ctor::source_type::generated) { std::filesystem::path _src = std::filesystem::path(settings.builddir); _src /= src.file; deps.push_back(_src.string()); } } } return deps; } std::string TaskFn::target() const { return _targetFile.string(); } std::filesystem::path TaskFn::targetFile() const { return std::filesystem::path(settings.builddir) / _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; } std::string TaskFn::toJSON() const { return {}; // TODO: Not sure how to express this... } std::string TaskFn::source() const { return sourceFile.string(); }