// -*- c++ -*- // Distributed under the BSD 2-Clause License. // See accompanying file LICENSE for details. #include "tasks.h" #include #include #include #include #include "settings.h" #include "libctor.h" #include "task.h" #include "task_cc.h" #include "task_ld.h" #include "task_ar.h" #include "task_so.h" #include "rebuild.h" #include "configure.h" const std::deque& getTargets(const Settings& settings, bool resolve_externals) { static bool initialised{false}; static std::deque targets; if(!initialised) { const auto& externals = 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(); 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); config.flags.cflags.insert(config.flags.cflags.end(), flags.cflags.begin(), flags.cflags.end()); config.flags.cxxflags.insert(config.flags.cxxflags.end(), flags.cxxflags.begin(), flags.cxxflags.end()); config.flags.ldflags.insert(config.flags.ldflags.end(), flags.ldflags.begin(), flags.ldflags.end()); config.flags.asmflags.insert(config.flags.asmflags.end(), flags.asmflags.begin(), flags.asmflags.end()); //config.libs.insert(config.libs.end(), // libs.begin(), // libs.end()); } } targets.push_back({config, path}); } } initialised = true; } return targets; } std::list> taskFactory(const BuildConfiguration& config, const Settings& settings, const std::string& sourceDir) { std::filesystem::path targetFile(config.target); TargetType target_type{config.type}; if(target_type == TargetType::Auto) { if(targetFile.extension() == ".a") { target_type = TargetType::StaticLibrary; } else if(targetFile.extension() == ".so") { target_type = TargetType::DynamicLibrary; } else if(targetFile.extension() == "") { target_type = TargetType::Executable; } else { std::cerr << "Could not deduce target type from target " << targetFile.string() << " please specify.\n"; exit(1); } } std::vector objects; std::list> tasks; for(const auto& file : config.sources) { tasks.emplace_back(std::make_shared(config, settings, sourceDir, file)); objects.push_back(tasks.back()->target()); } switch(target_type) { case TargetType::Auto: // The target_type cannot be Auto break; case TargetType::StaticLibrary: tasks.emplace_back(std::make_shared(config, settings, config.target, objects, sourceDir)); break; #ifndef BOOTSTRAP case TargetType::DynamicLibrary: // 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.emplace_back(std::make_shared(config, settings, config.target, objects, sourceDir)); break; case TargetType::Executable: case TargetType::UnitTest: tasks.emplace_back(std::make_shared(config, settings, config.target, objects, sourceDir)); break; case TargetType::Object: break; #else default: break; #endif } return tasks; } std::shared_ptr getNextTask(const std::list>& allTasks, std::list>& 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::list> getTasks(const Settings& settings, const std::vector names, bool resolve_externals) { auto& targets = getTargets(settings, resolve_externals); std::list> 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; }