diff options
Diffstat (limited to 'src/build.cc')
-rw-r--r-- | src/build.cc | 136 |
1 files changed, 86 insertions, 50 deletions
diff --git a/src/build.cc b/src/build.cc index 081c156..5995fb7 100644 --- a/src/build.cc +++ b/src/build.cc @@ -4,21 +4,20 @@ #include "build.h" #include <future> -#include <vector> #include <iostream> #include <chrono> -#include <set> #include <thread> #include <list> +#include <algorithm> -#include "libctor.h" +#include "ctor.h" using namespace std::chrono_literals; -int build(const Settings& settings, +int build(const ctor::settings& settings, const std::string& name, - const std::set<std::shared_ptr<Task>>& tasks, - const std::set<std::shared_ptr<Task>>& all_tasks, + const std::vector<std::shared_ptr<Task>>& tasks, + const std::vector<std::shared_ptr<Task>>& all_tasks, bool dryrun) { if(settings.verbose > 1) @@ -26,19 +25,20 @@ int build(const Settings& settings, std::cout << "Building '" << name << "'\n"; } - std::set<std::shared_ptr<Task>> dirtyTasks; + std::vector<std::shared_ptr<Task>> dirtyTasks; for(auto task : tasks) { - if(task->dirty()) + if(task->dirty() && + std::find(dirtyTasks.begin(), dirtyTasks.end(), task) == dirtyTasks.end()) { - dirtyTasks.insert(task); + dirtyTasks.push_back(task); } } // Dry-run returns number of dirty tasks but otherwise does nothing. if(dryrun) { - return dirtyTasks.size(); + return static_cast<int>(dirtyTasks.size()); } if(dirtyTasks.empty()) @@ -65,7 +65,7 @@ int build(const Settings& settings, break; } - auto task = getNextTask(all_tasks, dirtyTasks); + auto task = getNextTask(settings, all_tasks, dirtyTasks); if(task == nullptr) { if(processes.empty() && !dirtyTasks.empty()) @@ -84,7 +84,9 @@ int build(const Settings& settings, return task->run(); })); started_one = true; - std::this_thread::sleep_for(2ms); + // Make sure we don't start tasks on top of each other to prevent + // straining the disk. + std::this_thread::sleep_for(50ms); } for(auto process = processes.begin(); @@ -106,27 +108,21 @@ int build(const Settings& settings, break; } - if(started_one) + if(!started_one) // prevent polling too fast if no task is yet ready { - std::this_thread::sleep_for(2ms); - } - else - { - std::this_thread::sleep_for(200ms); + std::this_thread::sleep_for(10ms); } } - for(auto process = processes.begin(); - process != processes.end(); - ++process) + for(auto& process : processes) { - if(process->valid() == false) + if(process.valid() == false) { continue; } - process->wait(); - auto ret = process->get(); - if(ret != 0) + process.wait(); + auto ret = process.get(); + if (ret != 0) { return ret; } @@ -135,30 +131,50 @@ int build(const Settings& settings, return 0; } -namespace +std::vector<std::shared_ptr<Task>> getDepTasks(std::shared_ptr<Task> task, + std::vector<std::shared_ptr<Task>> trace) { -std::set<std::shared_ptr<Task>> getDepTasks(std::shared_ptr<Task> task) -{ - std::set<std::shared_ptr<Task>> tasks; - tasks.insert(task); + std::vector<std::shared_ptr<Task>> tasks; + tasks.push_back(task); + trace.push_back(task); auto deps = task->getDependsTasks(); for(const auto& dep : deps) { - auto depSet = getDepTasks(dep); - for(const auto& dep : depSet) + if(std::find(trace.begin(), trace.end(), dep) != trace.end()) { - tasks.insert(dep); + trace.push_back(dep); + std::cerr << "Error: Cyclic dependency detected: "; + bool first{true}; + for(auto t : trace) + { + if(!first) + { + std::cerr << " -> "; + } + + first = false; + std::cerr << t->target(); + } + std::cerr << '\n'; + throw 1; + } + auto depSet = getDepTasks(dep, trace); + for(const auto& dep_inner : depSet) + { + if(std::find(tasks.begin(), tasks.end(), dep_inner) == tasks.end()) + { + tasks.push_back(dep_inner); + } } } return tasks; } -} -int build(const Settings& settings, +int build(const ctor::settings& settings, const std::string& name, - const std::set<std::shared_ptr<Task>>& all_tasks, + const std::vector<std::shared_ptr<Task>>& all_tasks, bool dryrun) { bool task_found{false}; @@ -168,17 +184,27 @@ int build(const Settings& settings, { task_found = true; - auto depSet = getDepTasks(task); - std::set<std::shared_ptr<Task>> ts; - for(const auto& task : depSet) + try { - ts.insert(task); - } + auto depSet = getDepTasks(task); + std::vector<std::shared_ptr<Task>> ts; + for(const auto& task_inner : depSet) + { + if(std::find(ts.begin(), ts.end(), task_inner) == ts.end()) + { + ts.push_back(task_inner); + } + } - auto ret = build(settings, name, ts, all_tasks, dryrun); - if(ret != 0) + auto ret = build(settings, name, ts, all_tasks, dryrun); + if(ret != 0) + { + return ret; + } + } + catch(...) { - return ret; + return 1; // cycle detected } break; @@ -194,14 +220,14 @@ int build(const Settings& settings, return 0; } -int build(const Settings& settings, +int build(const ctor::settings& settings, const std::string& name, const std::vector<Target>& targets, - const std::set<std::shared_ptr<Task>>& all_tasks, + const std::vector<std::shared_ptr<Task>>& all_tasks, bool dryrun) { bool task_found{false}; - std::set<std::shared_ptr<Task>> ts; + std::vector<std::shared_ptr<Task>> ts; for(const auto& target : targets) { @@ -212,10 +238,20 @@ int build(const Settings& settings, { task_found = true; - auto depSet = getDepTasks(task); - for(const auto& task : depSet) + try + { + auto depSet = getDepTasks(task); + for(const auto& task_inner : depSet) + { + if(std::find(ts.begin(), ts.end(), task_inner) == ts.end()) + { + ts.push_back(task_inner); + } + } + } + catch(...) { - ts.insert(task); + return 1; // cycle detected } } } |