const Target::Dependencies &depends = i->second->get_dependencies();
for(Target::Dependencies::const_iterator j=depends.begin(); j!=depends.end(); ++j)
rdepends[*j].insert(i->second);
+ const Target::Dependencies &tdepends = i->second->get_transitive_dependencies();
+ for(Target::Dependencies::const_iterator j=tdepends.begin(); j!=tdepends.end(); ++j)
+ rdepends[*j].insert(i->second);
}
}
depends.assign(rdeps.begin(), rdeps.end());
}
else
+ {
depends = tgt.get_dependencies();
+ const Target::Dependencies &tdeps = tgt.get_transitive_dependencies();
+ depends.insert(depends.end(), tdeps.begin(), tdeps.end());
+ }
depends.sort(full_paths ? target_order_full : target_order);
{
Target *hdr = builder.get_vfs().find_header(i->substr(1), ((*i)[0]=='"' ? local_incpath : incpath));
if(hdr)
- add_dependency(*hdr);
+ add_transitive_dependency(*hdr);
}
}
void CSourceFile::modified()
{
includes.clear();
- depends.clear();
+ trans_depends.clear();
find_dependencies();
}
void ObjectFile::find_dependencies(FileTarget *tgt)
{
FileTarget *rtgt = dynamic_cast<FileTarget *>(tgt->get_real_target());
- const Dependencies &tdeps = rtgt->get_dependencies();
+ const Dependencies &tdeps = rtgt->get_transitive_dependencies();
Dependencies deps_to_add;
if(rtgt==tgt)
{
dep.signal_bubble_rebuild.connect(sigc::mem_fun(this, &Target::check_rebuild));
}
+void Target::add_transitive_dependency(Target &dep)
+{
+ if(&dep==this)
+ throw invalid_argument("Target::add_transitive_dependency");
+ trans_depends.push_back(&dep);
+}
+
void Target::add_side_effect(Target &se)
{
side_effects.push_back(&se);
/**
Targets make up the build graph. This class is a base for all target types and
handles many common tasks. See also FileTarget and VirtualTarget.
+
+Targets can depend on other targets. There are two kinds of dependencies:
+normal and transitive. Normal dependencies will need to be built before the
+target itself, and will cause the target to be rebuilt if modified. Transitive
+dependencies can be used by other targets further down the chain.
*/
class Target
{
std::list<std::string> problems;
Dependencies depends;
+ Dependencies trans_depends;
Dependencies side_effects;
Target *primary_target;
this won't be detected until the targets are prepared. */
void add_dependency(Target &);
+ void add_transitive_dependency(Target &);
+
/** Adds a side effect for the target. Side effects are not built on their
own, but together with their primary target. */
void add_side_effect(Target &);
/// Returns the dependencies of the target, in the order they were added.
const Dependencies &get_dependencies() const { return depends; }
+ const Dependencies &get_transitive_dependencies() const { return trans_depends; }
+
/// Returns the side effects of the target.
const Dependencies &get_side_effects() const { return side_effects; }