summaryrefslogtreecommitdiff
path: root/build.cc
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2021-07-10 21:17:49 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2021-07-10 23:43:37 +0200
commit23b150fd0dedc012e85b405ec92bc3adacfe9959 (patch)
tree2f919e89b74906eb15c14ff89e2936dab2936b74 /build.cc
parentbfbb506ff1a5e87401d4aa633f0707d1238082d0 (diff)
Individual target builds.
Diffstat (limited to 'build.cc')
-rw-r--r--build.cc166
1 files changed, 166 insertions, 0 deletions
diff --git a/build.cc b/build.cc
new file mode 100644
index 0000000..6302a18
--- /dev/null
+++ b/build.cc
@@ -0,0 +1,166 @@
+#include "build.h"
+
+#include <future>
+#include <vector>
+#include <iostream>
+#include <chrono>
+#include <set>
+
+#include "tasks.h"
+
+using namespace std::chrono_literals;
+
+int build(const Settings& settings,
+ const std::string& name,
+ const std::list<std::shared_ptr<Task>>& tasks,
+ const std::list<std::shared_ptr<Task>>& all_tasks)
+{
+ if(settings.verbose > 1)
+ {
+ std::cout << "Building '" << name << "'\n";
+ }
+
+ std::list<std::shared_ptr<Task>> 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<std::future<int>> 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)
+ {
+ 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<std::shared_ptr<Task>> getDepTasks(std::shared_ptr<Task> task)
+{
+ std::set<std::shared_ptr<Task>> 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<std::shared_ptr<Task>>& 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<std::shared_ptr<Task>> 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;
+}