aboutsummaryrefslogtreecommitdiff
path: root/build
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-07-14 09:47:40 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-07-14 09:47:40 +0200
commit8276259438592439236341b74300cb5538303c83 (patch)
tree0e072ee31bd13ff55f2c3e0d4a0b50725f8dd73f /build
parent70613e9be046c9cddd2486505a44d3a0324d6d95 (diff)
Add notion of strong/weak amalgamation, make strong new clean boundary
Diffstat (limited to 'build')
-rw-r--r--build/algorithm.ixx10
-rw-r--r--build/bin/module.cxx2
-rw-r--r--build/config/operation.cxx5
-rw-r--r--build/cxx/rule.cxx35
-rw-r--r--build/file.cxx10
-rw-r--r--build/rule.cxx32
-rw-r--r--build/scope29
-rw-r--r--build/target7
-rw-r--r--build/target.ixx2
9 files changed, 88 insertions, 44 deletions
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<module>&,
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&> ());
+ const dir_path& d (v.as<const dir_path&> ());
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<lib> () || pt.is_a<liba> () || pt.is_a<libso> ())
+ {
+ // @@ 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 <build/file> 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<scope>;
diff --git a/build/target b/build/target
index ba51f5e..1015b0c 100644
--- a/build/target
+++ b/build/target
@@ -21,6 +21,7 @@
#include <butl/multi-index> // map_iterator_adapter
#include <build/types>
+#include <build/scope>
#include <build/variable>
#include <build/operation>
#include <build/target-type>
@@ -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 <build/scope>
-
namespace build
{
// prerequisite_ref