#include <msp/core/algorithm.h>
#include <msp/fs/stat.h>
#include <msp/fs/utils.h>
+#include <msp/strings/utils.h>
#include "builder.h"
#include "filetarget.h"
#include "sourcepackage.h"
using namespace std;
using namespace Msp;
+vector<Target *> Target::prepare_stack;
+
Target::Target(Builder &b, const string &n):
builder(b),
name(n)
return;
if(state==PREPARING)
{
- builder.get_logger().log("problems", "Dependency cycle detected at %s", name);
- problems.push_back("Dependency cycle detected");
+ auto i = find(prepare_stack, this);
+ if(i!=prepare_stack.end())
+ {
+ string cycle;
+ for(; i!=prepare_stack.end(); ++i)
+ append(cycle, " -> ", (*i)->name);
+ append(cycle, " -> ", name);
+ builder.get_logger().log("problems", "Dependency cycle detected: %s", cycle);
+ problems.push_back(format("Dependency cycle detected: %s", cycle));
+ }
+ else
+ {
+ builder.get_logger().log("problems", "Dependency cycle detected at %s", name);
+ problems.push_back("Dependency cycle detected");
+ }
state = BROKEN;
return;
}
+ PushPrepare _push(this);
state = PREPARING;
/* Prepare existing dependencies early, because their information may be
needed to find other dependencies. */
#include <string>
#include <vector>
#include <sigc++/signal.h>
+#include <msp/core/noncopyable.h>
#include <msp/time/timestamp.h>
#include "libbuilder_api.h"
BROKEN
};
+ struct PushPrepare: Msp::NonCopyable
+ {
+ PushPrepare(Target *t) { prepare_stack.push_back(t); }
+ ~PushPrepare() { prepare_stack.pop_back(); }
+ };
+
public:
sigc::signal<void> signal_bubble_rebuild;
sigc::signal<void> signal_modified;
Dependencies side_effects;
Target *primary_target = 0;
+ static std::vector<Target *> prepare_stack;
+
Target(Builder &, const std::string &);
public:
virtual ~Target() { }