// -*- c++ -*- // Distributed under the BSD 2-Clause License. // See accompanying file LICENSE for details. #include "tasks.h" #include #include #include #include #include #include "ctor.h" #include "task.h" #include "task_cc.h" #include "task_ld.h" #include "task_ar.h" #include "task_so.h" #include "task_fn.h" #include "rebuild.h" #include "configure.h" #include "util.h" #include "tools.h" const std::deque& getTargets(const ctor::settings& settings, bool resolve_externals) { static bool initialised{false}; static std::deque targets; if(!initialised) { const auto& externals = ctor::get_configuration().externals; for(std::size_t i = 0; i < numConfigFiles; ++i) { std::string path = std::filesystem::path(configFiles[i].file).parent_path().string(); if(settings.verbose > 1) { std::cout << configFiles[i].file << " in path " << path << "\n"; } auto configs = configFiles[i].cb(settings); for(auto& config : configs) { if(resolve_externals) { // Resolv config externals for(const auto& external : config.externals) { if(externals.find(external) == externals.end()) { std::cout << "External '" << external << "' not found in cache - run configure.\n"; exit(1); } const auto& flags = externals.at(external); append(config.flags.cflags, flags.cflags); append(config.flags.cxxflags, flags.cxxflags); append(config.flags.ldflags, flags.ldflags); append(config.flags.arflags, flags.arflags); append(config.flags.asmflags, flags.asmflags); //append(config.libs.insert(config.libs libs); } } targets.push_back({config, path}); } } initialised = true; } return targets; } std::vector> taskFactory(const ctor::build_configuration& config, const ctor::settings& settings, const std::string& sourceDir) { std::vector> tasks; std::filesystem::path targetFile(config.target); ctor::target_type target_type{config.type}; if(target_type == ctor::target_type::automatic) { if(config.function != nullptr) { target_type = ctor::target_type::function; } else { target_type = target_type_from_extension(ctor::toolchain::any, targetFile); } } std::vector objects; if(target_type != ctor::target_type::function) { for(const auto& file : config.sources) { auto task = std::make_shared(config, settings, sourceDir, file); tasks.push_back(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.push_back(task); objects.push_back(task->target()); } } #endif switch(target_type) { case ctor::target_type::automatic: // The target_type cannot be Auto break; case ctor::target_type::unknown: std::cerr << "Could not deduce target type from target " << targetFile.string() << " please specify.\n"; exit(1); break; case ctor::target_type::static_library: case ctor::target_type::unit_test_library: tasks.push_back(std::make_shared(config, settings, config.target, objects, sourceDir)); break; #ifndef BOOTSTRAP case ctor::target_type::dynamic_library: // TODO: Use C++20 starts_with if(targetFile.stem().string().substr(0, 3) != "lib") { std::cerr << "Dynamic library target must have 'lib' prefix\n"; exit(1); } tasks.push_back(std::make_shared(config, settings, config.target, objects, sourceDir)); break; case ctor::target_type::executable: case ctor::target_type::unit_test: tasks.push_back(std::make_shared(config, settings, config.target, objects, sourceDir)); break; case ctor::target_type::object: case ctor::target_type::function: break; #else default: break; #endif } return tasks; } std::shared_ptr getNextTask(const std::vector>& allTasks, std::vector>& dirtyTasks) { for(auto dirtyTask = dirtyTasks.begin(); dirtyTask != dirtyTasks.end(); ++dirtyTask) { //std::cout << "Examining target " << (*dirtyTask)->target() << "\n"; if((*dirtyTask)->ready()) { dirtyTasks.erase(dirtyTask); return *dirtyTask; } } //std::cout << "No task ready ... \n"; return nullptr; } std::vector> getTasks(const ctor::settings& settings, const std::vector names, bool resolve_externals) { auto& targets = getTargets(settings, resolve_externals); std::vector> tasks; for(const auto& target : targets) { if(names.empty() || std::find(std::begin(names), std::end(names), target.config.target) != std::end(names)) { std::vector objects; auto t = taskFactory(target.config, settings, target.path); tasks.insert(tasks.end(), t.begin(), t.end()); } } return tasks; }