aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/target.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-07-09 10:50:42 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-07-09 10:50:42 +0200
commit101987533ca35e4aa3515b25415f1abba46e796f (patch)
tree076fcafb99a6d6c4d10b9eb1ad965d2b6748e260 /libbuild2/target.cxx
parent932519463bca296054a3b5a8e07ad3505160a91b (diff)
Add support for ad hoc importation
Diffstat (limited to 'libbuild2/target.cxx')
-rw-r--r--libbuild2/target.cxx130
1 files changed, 63 insertions, 67 deletions
diff --git a/libbuild2/target.cxx b/libbuild2/target.cxx
index 232b0b1..0b67dc3 100644
--- a/libbuild2/target.cxx
+++ b/libbuild2/target.cxx
@@ -928,93 +928,89 @@ namespace build2
//
// ./: */
//
+ const scope& s (*pk.scope);
const dir_path& d (*pk.tk.dir);
- // We only do this for relative paths.
+ // Note: this code is a custom version of parser::parse_include().
+
+ // Calculate the new out_base. If the directory is absolute then we assume
+ // it is already normalized.
//
- if (d.relative ())
- {
- // Note: this code is a custom version of parser::parse_include().
+ dir_path out_base (d.relative ()
+ ? (s.out_path () / d).normalize ()
+ : d);
- const scope& s (*pk.scope);
+ // In our world modifications to the scope structure during search & match
+ // should be "pure append" in the sense that they should not affect any
+ // existing targets that have already been searched & matched.
+ //
+ // A straightforward way to enforce this is to not allow any existing
+ // targets to be inside any newly created scopes (except, perhaps for the
+ // directory target itself which we know hasn't been searched yet). This,
+ // however, is not that straightforward to implement: we would need to
+ // keep a directory prefix map for all the targets (e.g., in target_set).
+ // Also, a buildfile could load from a directory that is not a
+ // subdirectory of out_base. So for now we just assume that this is so.
+ // And so it is.
+ //
+ bool retest (false);
- // Calculate the new out_base.
+ assert (t.ctx.phase == run_phase::match);
+ {
+ // Switch the phase to load.
//
- dir_path out_base (s.out_path () / d);
- out_base.normalize ();
+ phase_switch ps (t.ctx, run_phase::load);
- // In our world modifications to the scope structure during search &
- // match should be "pure append" in the sense that they should not
- // affect any existing targets that have already been searched &
- // matched.
- //
- // A straightforward way to enforce this is to not allow any existing
- // targets to be inside any newly created scopes (except, perhaps for
- // the directory target itself which we know hasn't been searched yet).
- // This, however, is not that straightforward to implement: we would
- // need to keep a directory prefix map for all the targets (e.g., in
- // target_set). Also, a buildfile could load from a directory that is
- // not a subdirectory of out_base. So for now we just assume that this
- // is so. And so it is.
+ // This is subtle: while we were fussing around another thread may have
+ // loaded the buildfile. So re-test now that we are in an exclusive
+ // phase.
//
- bool retest (false);
+ if (e == nullptr)
+ e = search_existing_target (t.ctx, pk);
- assert (t.ctx.phase == run_phase::match);
+ if (e != nullptr && !e->implied)
+ retest = true;
+ else
{
- // Switch the phase to 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 an
- // exclusive phase.
+ // Ok, no luck, switch the scope.
//
- if (e == nullptr)
- e = search_existing_target (t.ctx, pk);
+ pair<scope&, scope*> sp (
+ switch_scope (*s.rw ().root_scope (), out_base));
- if (e != nullptr && !e->implied)
- retest = true;
- else
+ if (sp.second != nullptr) // Ignore scopes out of any project.
{
- // Ok, no luck, switch the scope.
- //
- pair<scope&, scope*> sp (
- switch_scope (*s.rw ().root_scope (), out_base));
+ scope& base (sp.first);
+ scope& root (*sp.second);
+
+ const dir_path& src_base (base.src_path ());
- if (sp.second != nullptr) // Ignore scopes out of any project.
+ path bf (src_base / root.root_extra->buildfile_file);
+
+ if (exists (bf))
+ {
+ l5 ([&]{trace << "loading buildfile " << bf << " for " << pk;});
+ retest = source_once (root, base, bf);
+ }
+ else if (exists (src_base))
{
- scope& base (sp.first);
- scope& root (*sp.second);
-
- const dir_path& src_base (base.src_path ());
-
- path bf (src_base / root.root_extra->buildfile_file);
-
- if (exists (bf))
- {
- l5 ([&]{trace << "loading buildfile " << bf << " for " << pk;});
- retest = source_once (root, base, bf, root);
- }
- else if (exists (src_base))
- {
- e = dir::search_implied (base, pk, trace);
- retest = (e != nullptr);
- }
+ e = dir::search_implied (base, pk, trace);
+ retest = (e != nullptr);
}
}
}
- assert (t.ctx.phase == run_phase::match);
+ }
- // If we loaded/implied the buildfile, examine the target again.
- //
- if (retest)
- {
- if (e == nullptr)
- e = search_existing_target (t.ctx, pk);
+ assert (t.ctx.phase == run_phase::match);
- if (e != nullptr && !e->implied)
- return e;
- }
+ // If we loaded/implied the buildfile, examine the target again.
+ //
+ if (retest)
+ {
+ if (e == nullptr)
+ e = search_existing_target (t.ctx, pk);
+
+ if (e != nullptr && !e->implied)
+ return e;
}
fail << "no explicit target for " << pk << endf;