summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build.cc67
-rw-r--r--src/build.h5
2 files changed, 54 insertions, 18 deletions
diff --git a/src/build.cc b/src/build.cc
index 906c3ea..a31f6a5 100644
--- a/src/build.cc
+++ b/src/build.cc
@@ -131,17 +131,35 @@ int build(const ctor::settings& settings,
return 0;
}
-namespace
-{
-std::vector<std::shared_ptr<Task>> getDepTasks(std::shared_ptr<Task> task)
+std::vector<std::shared_ptr<Task>> getDepTasks(std::shared_ptr<Task> task,
+ std::vector<std::shared_ptr<Task>> trace)
{
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);
+ if(std::find(trace.begin(), trace.end(), dep) != trace.end())
+ {
+ 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())
@@ -153,7 +171,6 @@ std::vector<std::shared_ptr<Task>> getDepTasks(std::shared_ptr<Task> task)
return tasks;
}
-}
int build(const ctor::settings& settings,
const std::string& name,
@@ -167,20 +184,27 @@ int build(const ctor::settings& settings,
{
task_found = true;
- auto depSet = getDepTasks(task);
- std::vector<std::shared_ptr<Task>> ts;
- for(const auto& task_inner : depSet)
+ try
{
- if(std::find(ts.begin(), ts.end(), task_inner) == ts.end())
+ auto depSet = getDepTasks(task);
+ std::vector<std::shared_ptr<Task>> ts;
+ for(const auto& task_inner : depSet)
{
- ts.push_back(task_inner);
+ 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;
@@ -214,14 +238,21 @@ int build(const ctor::settings& settings,
{
task_found = true;
- auto depSet = getDepTasks(task);
- for(const auto& task_inner : depSet)
+ try
{
- if(std::find(ts.begin(), ts.end(), task_inner) == ts.end())
+ auto depSet = getDepTasks(task);
+ for(const auto& task_inner : depSet)
{
- ts.push_back(task_inner);
+ if(std::find(ts.begin(), ts.end(), task_inner) == ts.end())
+ {
+ ts.push_back(task_inner);
+ }
}
}
+ catch(...)
+ {
+ return 1; // cycle detected
+ }
}
}
}
diff --git a/src/build.h b/src/build.h
index 500fb7f..7296f76 100644
--- a/src/build.h
+++ b/src/build.h
@@ -33,3 +33,8 @@ int build(const ctor::settings& settings,
const std::vector<Target>& targets,
const std::vector<std::shared_ptr<Task>>& all_tasks,
bool dryrun = false);
+
+// Recursively build vector of dependency tasks from source task.
+// Throws if a cycle is detected.
+std::vector<std::shared_ptr<Task>> getDepTasks(std::shared_ptr<Task> task,
+ std::vector<std::shared_ptr<Task>> trace = {});