aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/target.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2019-08-22 14:38:57 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2019-08-23 18:14:07 +0200
commit5035f4ef68922ac758b1e4734e67d73c9228010b (patch)
tree271fdd5b1d6e995a058d97aacb3ac90a538d9ff1 /libbuild2/target.cxx
parent8793941652d6aa1c3d02b2f87f691e6d06254b7d (diff)
Introduce notion of build context
All non-const global state is now in class context and we can now have multiple independent builds going on at the same time.
Diffstat (limited to 'libbuild2/target.cxx')
-rw-r--r--libbuild2/target.cxx108
1 files changed, 69 insertions, 39 deletions
diff --git a/libbuild2/target.cxx b/libbuild2/target.cxx
index c823e85..dbca6cd 100644
--- a/libbuild2/target.cxx
+++ b/libbuild2/target.cxx
@@ -67,7 +67,7 @@ namespace build2
const string& target::
ext (string v)
{
- ulock l (targets.mutex_);
+ ulock l (ctx.targets.mutex_);
// Once the extension is set, it is immutable. However, it is possible
// that someone has already "branded" this target with a different
@@ -102,7 +102,7 @@ namespace build2
// If this target is from the src tree, use its out directory to find
// the scope.
//
- return scopes.find (out_dir ());
+ return ctx.scopes.find (out_dir ());
}
const scope& target::
@@ -290,10 +290,36 @@ namespace build2
}
}
- // target_set
+ // include()
//
- target_set targets;
+ include_type
+ include_impl (action a,
+ const target& t,
+ const string& v,
+ const prerequisite& p,
+ const target* m)
+ {
+ context& ctx (t.ctx);
+
+ include_type r (false);
+
+ if (v == "false") r = include_type::excluded;
+ else if (v == "adhoc") r = include_type::adhoc;
+ else if (v == "true") r = include_type::normal;
+ else
+ fail << "invalid " << ctx.var_include->name << " variable value "
+ << "'" << v << "' specified for prerequisite " << p;
+
+ // Call the meta-operation override, if any (currently used by dist).
+ //
+ if (auto f = ctx.current_mif->include)
+ r = f (a, t, prerequisite_member {p, m}, r);
+ return r;
+ }
+
+ // target_set
+ //
const target* target_set::
find (const target_key& k, tracer& trace) const
{
@@ -367,14 +393,14 @@ namespace build2
// We sometimes call insert() even if we expect to find an existing
// target in order to keep the same code (see cc/search_library()).
//
- assert (phase != run_phase::execute);
+ assert (ctx.phase != run_phase::execute);
optional<string> e (
tt.fixed_extension != nullptr
? string (tt.fixed_extension (tk, nullptr /* root scope */))
: move (tk.ext));
- t = tt.factory (tt, move (dir), move (out), move (name));
+ t = tt.factory (ctx, tt, move (dir), move (out), move (name));
// Re-lock for exclusive access. In the meantime, someone could have
// inserted this target so emplace() below could return false, in which
@@ -392,8 +418,8 @@ namespace build2
{
t->ext_ = &i->first.ext;
t->implied = implied;
- t->state.data[0].target_ = t;
- t->state.data[1].target_ = t;
+ t->state.inner.target_ = t;
+ t->state.outer.target_ = t;
return pair<target&, ulock> (*t, move (ul));
}
@@ -432,7 +458,7 @@ namespace build2
{
// The implied flag can only be cleared during the load phase.
//
- assert (phase == run_phase::load);
+ assert (ctx.phase == run_phase::load);
// Clear the implied flag.
//
@@ -538,7 +564,7 @@ namespace build2
//
const mtime_target* t (this);
- switch (phase)
+ switch (ctx.phase)
{
case run_phase::load: break;
case run_phase::match:
@@ -546,10 +572,11 @@ namespace build2
// Similar logic to matched_state_impl().
//
const opstate& s (state[action () /* inner */]);
- size_t o (s.task_count.load (memory_order_relaxed) - // Synchronized.
- target::count_base ());
- if (o != target::offset_applied && o != target::offset_executed)
+ // Note: already synchronized.
+ size_t o (s.task_count.load (memory_order_relaxed) - ctx.count_base ());
+
+ if (o != offset_applied && o != offset_executed)
break;
}
// Fall through.
@@ -658,25 +685,25 @@ namespace build2
//
const target*
- target_search (const target&, const prerequisite_key& pk)
+ target_search (const target& t, const prerequisite_key& pk)
{
// The default behavior is to look for an existing target in the
// prerequisite's directory scope.
//
- return search_existing_target (pk);
+ return search_existing_target (t.ctx, pk);
}
const target*
- file_search (const target&, const prerequisite_key& pk)
+ file_search (const target& t, const prerequisite_key& pk)
{
// First see if there is an existing target.
//
- if (const target* t = search_existing_target (pk))
- return t;
+ if (const target* e = search_existing_target (t.ctx, pk))
+ return e;
// Then look for an existing file in the src tree.
//
- return search_existing_file (pk);
+ return search_existing_file (t.ctx, pk);
}
void
@@ -753,17 +780,17 @@ namespace build2
};
static const target*
- alias_search (const target&, const prerequisite_key& pk)
+ alias_search (const target& t, const prerequisite_key& pk)
{
// For an alias we don't want to silently create a target since it will do
// nothing and it most likely not what the user intended.
//
- const target* t (search_existing_target (pk));
+ const target* e (search_existing_target (t.ctx, pk));
- if (t == nullptr || t->implied)
+ if (e == nullptr || e->implied)
fail << "no explicit target for " << pk;
- return t;
+ return e;
}
const target_type alias::static_type
@@ -847,16 +874,16 @@ namespace build2
}
static const target*
- dir_search (const target&, const prerequisite_key& pk)
+ dir_search (const target& t, const prerequisite_key& pk)
{
tracer trace ("dir_search");
// The first step is like in search_alias(): looks for an existing target.
//
- const target* t (search_existing_target (pk));
+ const target* e (search_existing_target (t.ctx, pk));
- if (t != nullptr && !t->implied)
- return t;
+ if (e != nullptr && !e->implied)
+ return e;
// If not found (or is implied), then try to load the corresponding
// buildfile (which would normally define this target). Failed that, see
@@ -895,20 +922,20 @@ namespace build2
//
bool retest (false);
- assert (phase == run_phase::match);
+ assert (t.ctx.phase == run_phase::match);
{
// Switch the phase to load.
//
- phase_switch ps (run_phase::load);
+ phase_switch ps (t.ctx, run_phase::load);
// This is subtle: while we were fussing around another thread may
// have loaded the buildfile. So re-test now that we are in exclusive
// phase.
//
- if (t == nullptr)
- t = search_existing_target (pk);
+ if (e == nullptr)
+ e = search_existing_target (t.ctx, pk);
- if (t != nullptr && !t->implied)
+ if (e != nullptr && !e->implied)
retest = true;
else
{
@@ -933,23 +960,23 @@ namespace build2
}
else if (exists (src_base))
{
- t = dir::search_implied (base, pk, trace);
- retest = (t != nullptr);
+ e = dir::search_implied (base, pk, trace);
+ retest = (e != nullptr);
}
}
}
}
- assert (phase == run_phase::match);
+ assert (t.ctx.phase == run_phase::match);
// If we loaded/implied the buildfile, examine the target again.
//
if (retest)
{
- if (t == nullptr)
- t = search_existing_target (pk);
+ if (e == nullptr)
+ e = search_existing_target (t.ctx, pk);
- if (t != nullptr && !t->implied)
- return t;
+ if (e != nullptr && !e->implied)
+ return e;
}
}
@@ -1100,7 +1127,10 @@ namespace build2
// Note: we are guaranteed the scope is never NULL for prerequisites
// (where out/dir could be relative and none of this will work).
//
+ // @@ CTX TODO
+#if 0
root = scopes.find (tk.out->empty () ? *tk.dir : *tk.out).root_scope ();
+#endif
if (root == nullptr || root->root_extra == nullptr)
fail << "unable to determine extension for buildfile target " << tk;