From 8276259438592439236341b74300cb5538303c83 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 14 Jul 2015 09:47:40 +0200 Subject: Add notion of strong/weak amalgamation, make strong new clean boundary --- build/algorithm.ixx | 10 +++++++--- build/bin/module.cxx | 2 +- build/config/operation.cxx | 5 ++--- build/cxx/rule.cxx | 35 ++++++++++++++++++++++++++++------- build/file.cxx | 10 ++++++++++ build/rule.cxx | 32 +++++--------------------------- build/scope | 29 ++++++++++++++++++++++++++++- build/target | 7 +++++++ build/target.ixx | 2 -- 9 files changed, 88 insertions(+), 44 deletions(-) (limited to 'build') diff --git a/build/algorithm.ixx b/build/algorithm.ixx index d4d0ec8..c4f5815 100644 --- a/build/algorithm.ixx +++ b/build/algorithm.ixx @@ -71,7 +71,11 @@ namespace build search_and_match_prerequisites (action a, target& t) { search_and_match_prerequisites ( - a, t, a.operation () != clean_id ? dir_path () : t.dir); + a, + t, + a.operation () != clean_id + ? dir_path () + : t.strong_scope ().path ()); } inline void @@ -80,11 +84,11 @@ namespace build if (a.operation () != clean_id) search_and_match_prerequisite_members (a, t, dir_path ()); else - // Note that here we don't iterate over members even for see + // Note that here we don't iterate over members even for see- // through groups since the group target should clean eveything // up. A bit of an optimization. // - search_and_match_prerequisites (a, t, t.dir); + search_and_match_prerequisites (a, t, t.strong_scope ().path ()); } target_state diff --git a/build/bin/module.cxx b/build/bin/module.cxx index ab1c1f5..5e7888b 100644 --- a/build/bin/module.cxx +++ b/build/bin/module.cxx @@ -31,7 +31,7 @@ namespace build extern "C" void bin_init (scope& root, scope& base, - const location& l, + const location&, std::unique_ptr&, bool) { diff --git a/build/config/operation.cxx b/build/config/operation.cxx index 57bb60d..48d4d19 100644 --- a/build/config/operation.cxx +++ b/build/config/operation.cxx @@ -81,10 +81,9 @@ namespace build << "# feel free to edit." << endl << "#" << endl; - auto av = root.vars["amalgamation"]; - if (av && !av.empty ()) + if (auto v = root.vars["amalgamation"]) { - const dir_path& d (av.as ()); + const dir_path& d (v.as ()); ofs << "# Base configuration inherited from " << d << endl << "#" << endl; diff --git a/build/cxx/rule.cxx b/build/cxx/rule.cxx index e0e5c0f..9228994 100644 --- a/build/cxx/rule.cxx +++ b/build/cxx/rule.cxx @@ -126,17 +126,20 @@ namespace build // code (below) takes care of the ones it is adding. // // When cleaning, ignore prerequisites that are not in the same - // or a subdirectory of ours. + // or a subdirectory of our strong amalgamation. // + const dir_path* amlg ( + a.operation () != clean_id + ? nullptr + : &t.strong_scope ().path ()); + for (prerequisite_member p: group_prerequisite_members (a, t)) { target& pt (p.search ()); - if (a.operation () == clean_id && !pt.dir.sub (t.dir)) + if (a.operation () == clean_id && !pt.dir.sub (*amlg)) continue; - build::match (a, pt); - // A dependency on a library is there so that we can get its // cxx.export.poptions. In particular, making sure it is // executed before us will only restrict parallelism. But we @@ -144,8 +147,18 @@ namespace build // populated; see append_lib_options() above. // if (pt.is_a () || pt.is_a () || pt.is_a ()) + { + // @@ The fact that we match but never execute messes up + // the dependents count. This is a workaround, not a + // solution. + // + if (a.operation () == update_id) + build::match (a, pt); + continue; + } + build::match (a, pt); t.prerequisite_targets.push_back (&pt); } @@ -932,6 +945,14 @@ namespace build // Process prerequisites: do rule chaining for C and C++ source // files as well as search and match. // + // When cleaning, ignore prerequisites that are not in the same + // or a subdirectory of our strong amalgamation. + // + const dir_path* amlg ( + a.operation () != clean_id + ? nullptr + : &t.strong_scope ().path ()); + for (prerequisite_member p: group_prerequisite_members (a, t)) { bool group (!p.prerequisite.belongs (t)); // Group's prerequisite. @@ -943,7 +964,7 @@ namespace build // pt = &p.search (); - if (a.operation () == clean_id && !pt->dir.sub (t.dir)) + if (a.operation () == clean_id && !pt->dir.sub (*amlg)) continue; // Skip. // If this is the obj{} or lib{} target group, then pick the @@ -1042,9 +1063,9 @@ namespace build target& ot (search (o_type, d, *cp.tk.name, nullptr, cp.scope)); // If we are cleaning, check that this target is in the same or - // a subdirectory of ours. + // a subdirectory of our strong amalgamation. // - if (a.operation () == clean_id && !ot.dir.sub (t.dir)) + if (a.operation () == clean_id && !ot.dir.sub (*amlg)) { // If we shouldn't clean obj{}, then it is fair to assume // we shouldn't clean cxx{} either (generated source will diff --git a/build/file.cxx b/build/file.cxx index 0dff025..b137c32 100644 --- a/build/file.cxx +++ b/build/file.cxx @@ -579,6 +579,11 @@ namespace build bootstrap_src (rs); create_bootstrap_outer (rs); + + // Check if we are strongly amalgamated by this outer root scope. + // + if (root.src_path ().sub (rs.src_path ())) + root.strong_ = rs.strong_scope (); // Itself or some outer scope. } scope& @@ -612,6 +617,11 @@ namespace build bootstrap_src (rs); + // Check if we strongly amalgamated this inner root scope. + // + if (rs.src_path ().sub (root.src_path ())) + rs.strong_ = root.strong_scope (); // Itself or some outer scope. + // See if there are more inner roots. // return create_bootstrap_inner (rs, out_base); diff --git a/build/rule.cxx b/build/rule.cxx index 8f3a7a9..6db0f4f 100644 --- a/build/rule.cxx +++ b/build/rule.cxx @@ -159,35 +159,13 @@ namespace build recipe fsdir_rule:: apply (action a, target& t, const match_result&) const { - switch (a.operation ()) - { - case default_id: - case update_id: - // For default, we don't do anything other than letting our - // prerequisites do their thing. - // - - // Inject dependency on the parent directory. Note that we - // don't do it for clean since we shouldn't be removing it. - // + // Inject dependency on the parent directory. Note that we + // don't do it for clean since we shouldn't be removing it. + // + if (a.operation () != clean_id) inject_parent_fsdir (a, t); - search_and_match_prerequisites (a, t, dir_path ()); - break; - - case clean_id: - // For clean, ignore prerequisites that are not in the same or a - // subdirectory of ours (if t.dir is foo/bar/, then "we" are bar - // and our directory is foo/). Just meditate on it a bit and you - // will see the light. - // - search_and_match_prerequisites ( - a, t, t.dir.root () ? t.dir : t.dir.directory ()); - break; - - default: - assert (false); - } + search_and_match_prerequisites (a, t); switch (a) { diff --git a/build/scope b/build/scope index 817ee95..eb2dafc 100644 --- a/build/scope +++ b/build/scope @@ -43,6 +43,20 @@ namespace build scope* root_scope () const {return root_;} + // Root scope of a strong amalgamation of this scope or NULL if + // this scope is not (yet) in any (known) project. If there is + // no strong amalgamation, then this function returns the root + // scope of the project (in other words, in this case a project + // is treated as its own strong amalgamation). + // + scope* + strong_scope () const + { + return root_ != nullptr + ? root_->strong_ != nullptr ? root_->strong_ : root_ + : nullptr; + } + bool root () const {return root_ == this;} @@ -140,11 +154,18 @@ namespace build friend class scope_map; friend class temp_scope; + // These two from set strong_. + // + friend void create_bootstrap_outer (scope&); + friend scope& create_bootstrap_inner (scope&, const dir_path&); + scope () = default; const dir_path* path_; // Pointer to the key in scope_map. scope* parent_; scope* root_; + scope* strong_ = nullptr; // Only set on root sopes. + // NULL means no strong amalgamtion. }; // Temporary scope. The idea is to be able to create a temporary @@ -158,7 +179,13 @@ namespace build class temp_scope: public scope { public: - temp_scope (scope& p) {path_ = p.path_; parent_ = &p; root_ = p.root_;} + temp_scope (scope& p) + { + path_ = p.path_; + parent_ = &p; + root_ = p.root_; + // No need to copy strong_ since we are never root scope. + } }; using scope_map_base = butl::dir_path_map; diff --git a/build/target b/build/target index ba51f5e..1015b0c 100644 --- a/build/target +++ b/build/target @@ -21,6 +21,7 @@ #include // map_iterator_adapter #include +#include #include #include #include @@ -203,6 +204,12 @@ namespace build scope& root_scope () const; + // Root scope of a strong amalgamation that contains this target. + // The same notes as to root_scope() apply. + // + scope& + strong_scope () const {return *root_scope ().strong_scope ();} + // Prerequisites. // public: diff --git a/build/target.ixx b/build/target.ixx index 16616b5..8cf9e77 100644 --- a/build/target.ixx +++ b/build/target.ixx @@ -2,8 +2,6 @@ // copyright : Copyright (c) 2014-2015 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -#include - namespace build { // prerequisite_ref -- cgit v1.1