From: Mikko Rasa Date: Thu, 22 Aug 2013 12:03:03 +0000 (+0300) Subject: Add transitive dependencies for source files X-Git-Url: http://git.tdb.fi/?p=builder.git;a=commitdiff_plain;h=55269a63b0875be0b172453714f9190d30fb1dff Add transitive dependencies for source files This eliminates a problem where includes in C source files would cause generates sources to be rebuilt if any of the included files changed. Includes should only affect the object file built from the source file, not the source file itself. --- diff --git a/source/analyzer.cpp b/source/analyzer.cpp index d15a747..2c9cf05 100644 --- a/source/analyzer.cpp +++ b/source/analyzer.cpp @@ -30,6 +30,9 @@ void Analyzer::analyze() 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); } } @@ -109,7 +112,11 @@ void Analyzer::build_depend_table(Target &tgt, unsigned depth) 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); diff --git a/source/csourcefile.cpp b/source/csourcefile.cpp index e34ff27..d4f6d79 100644 --- a/source/csourcefile.cpp +++ b/source/csourcefile.cpp @@ -62,13 +62,13 @@ void CSourceFile::find_dependencies() { 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(); } diff --git a/source/objectfile.cpp b/source/objectfile.cpp index cee8c87..97b5c75 100644 --- a/source/objectfile.cpp +++ b/source/objectfile.cpp @@ -44,7 +44,7 @@ void ObjectFile::find_dependencies() void ObjectFile::find_dependencies(FileTarget *tgt) { FileTarget *rtgt = dynamic_cast(tgt->get_real_target()); - const Dependencies &tdeps = rtgt->get_dependencies(); + const Dependencies &tdeps = rtgt->get_transitive_dependencies(); Dependencies deps_to_add; if(rtgt==tgt) { diff --git a/source/target.cpp b/source/target.cpp index 72a369a..55f73a0 100644 --- a/source/target.cpp +++ b/source/target.cpp @@ -33,6 +33,13 @@ void Target::add_dependency(Target &dep) 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); diff --git a/source/target.h b/source/target.h index 6b9cc90..64a132c 100644 --- a/source/target.h +++ b/source/target.h @@ -17,6 +17,11 @@ class Tool; /** 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 { @@ -49,6 +54,7 @@ protected: std::list problems; Dependencies depends; + Dependencies trans_depends; Dependencies side_effects; Target *primary_target; @@ -66,6 +72,8 @@ public: 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 &); @@ -80,6 +88,8 @@ public: /// 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; }