From 5da56616cccf4e595ec6a556cf1aef40b37746e3 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 28 Aug 2021 18:59:29 +0200 Subject: Move sources to ... well, src ;) --- src/build.cc | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 src/build.cc (limited to 'src/build.cc') diff --git a/src/build.cc b/src/build.cc new file mode 100644 index 0000000..445979e --- /dev/null +++ b/src/build.cc @@ -0,0 +1,173 @@ +#include "build.h" + +#include +#include +#include +#include +#include +#include + +#include "tasks.h" + +using namespace std::chrono_literals; + +int build(const Settings& settings, + const std::string& name, + const std::list>& tasks, + const std::list>& all_tasks) +{ + if(settings.verbose > 1) + { + std::cout << "Building '" << name << "'\n"; + } + + std::list> dirtyTasks; + for(auto task : tasks) + { + if(task->dirty()) + { + dirtyTasks.push_back(task); + } + } + + if(dirtyTasks.empty()) + { + std::cout << "Nothing to be done for '"<< name << "'\n"; + return 0; + } + + std::list> processes; + + // Start all tasks + bool done{false}; + while(!done) + { + bool started_one{false}; + while(processes.size() < settings.parallel_processes) + { + if(dirtyTasks.empty()) + { + done = true; + break; + } + + auto task = getNextTask(all_tasks, dirtyTasks); + if(task == nullptr) + { + if(processes.empty() && !dirtyTasks.empty()) + { + // No running processes, yet no process to run. This is a dead-lock... + std::cout << "Dead-lock detected.\n"; + return 1; + } + break; + } + + processes.emplace_back( + std::async(std::launch::async, + [task]() + { + return task->run(); + })); + started_one = true; + std::this_thread::sleep_for(2ms); + } + + for(auto process = processes.begin(); + process != processes.end(); + ++process) + { + if(process->valid()) + { + if(process->get() != 0) + { + // TODO: Wait for other processes to finish before returning + return 1; + } + processes.erase(process); + break; + } + } + + if(started_one) + { + std::this_thread::sleep_for(2ms); + } + else + { + std::this_thread::sleep_for(200ms); + } + } + + for(auto process = processes.begin(); + process != processes.end(); + ++process) + { + process->wait(); + auto ret = process->get(); + if(ret != 0) + { + return 1; + } + } + + return 0; +} + +namespace +{ +std::set> getDepTasks(std::shared_ptr task) +{ + std::set> tasks; + tasks.insert(task); + + auto deps = task->getDependsTasks(); + for(const auto& dep : deps) + { + auto depSet = getDepTasks(dep); + for(const auto& dep : depSet) + { + tasks.insert(dep); + } + } + + return tasks; +} +} + +int build(const Settings& settings, + const std::string& name, + const std::list>& all_tasks) +{ + bool task_found{false}; + for(auto task : all_tasks) + { + if(task->name() == name || task->target() == name) + { + std::cout << name << "\n"; + task_found = true; + + auto depSet = getDepTasks(task); + std::list> ts; + for(const auto& task : depSet) + { + ts.push_back(task); + } + auto ret = build(settings, name, ts, all_tasks); + if(ret != 0) + { + return ret; + } + + break; + } + } + + if(!task_found) + { + std::cerr << "*** No rule to make target '" << name << "'. Stop.\n"; + return 1; + } + + return 0; +} -- cgit v1.2.3