aboutsummaryrefslogtreecommitdiff
path: root/build/file.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-04-13 10:29:25 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-04-13 10:29:25 +0200
commit534f9d8db025d58c9ce23f3b81a37e8c34386a27 (patch)
treee7d0c7871a7caf3b3e41c8d00548212f1ca7aa83 /build/file.cxx
parentb4ceb7b6aecb7492b28d7a0f6c53fa657a2cd2e5 (diff)
Add initial import support
Diffstat (limited to 'build/file.cxx')
-rw-r--r--build/file.cxx169
1 files changed, 167 insertions, 2 deletions
diff --git a/build/file.cxx b/build/file.cxx
index 0b0220d..70a5ed8 100644
--- a/build/file.cxx
+++ b/build/file.cxx
@@ -15,6 +15,19 @@ using namespace std;
namespace build
{
+ bool
+ is_src_root (const path& d)
+ {
+ return file_exists (d / path ("build/bootstrap.build")) ||
+ file_exists (d / path ("build/root.build"));
+ }
+
+ bool
+ is_out_root (const path& d)
+ {
+ return file_exists (d / path ("build/bootstrap/src-root.build"));
+ }
+
void
source (const path& bf, scope& root, scope& base)
{
@@ -146,18 +159,170 @@ namespace build
}
void
- root_pre (scope& root)
+ create_bootstrap_outer (scope& root)
+ {
+ auto v (root.ro_variables ()["amalgamation"]);
+
+ if (!v)
+ return;
+
+ const path& d (v.as<const path&> ());
+ path out_root (root.path () / d);
+ path src_root (root.src_path () / d);
+ out_root.normalize ();
+ src_root.normalize ();
+
+ scope& rs (create_root (out_root, src_root));
+
+ bootstrap_out (rs);
+
+ // Check if the bootstrap process changed src_root.
+ //
+ const path& p (rs.variables["src_root"].as<const path&> ());
+
+ if (src_root != p)
+ fail << "bootstrapped src_root " << p << " does not match "
+ << "amalgamated " << src_root;
+
+ rs.src_path_ = &p;
+
+ bootstrap_src (rs);
+ create_bootstrap_outer (rs);
+ }
+
+ scope&
+ create_bootstrap_inner (scope& root, const path& out_base)
+ {
+ if (auto v = root.ro_variables ()["subprojects"])
+ {
+ for (const name& n: v.as<const list_value&> ())
+ {
+ // Should be a list of directories.
+ //
+ if (!n.type.empty () || !n.value.empty () || n.dir.empty ())
+ fail << "expected directory in subprojects variable "
+ << "instead of " << n;
+
+ path out_root (root.path () / n.dir);
+
+ if (!out_base.sub (out_root))
+ continue;
+
+ path src_root (root.src_path () / n.dir);
+ scope& rs (create_root (out_root, src_root));
+
+ bootstrap_out (rs);
+
+ // Check if the bootstrap process changed src_root.
+ //
+ const path& p (rs.variables["src_root"].as<const path&> ());
+
+ if (src_root != p)
+ fail << "bootstrapped src_root " << p << " does not match "
+ << "subproject " << src_root;
+
+ rs.src_path_ = &p;
+
+ bootstrap_src (rs);
+
+ // See if there are more inner roots.
+ //
+ return create_bootstrap_inner (rs, out_base);
+ }
+ }
+
+ return root;
+ }
+
+ void
+ load_root_pre (scope& root)
{
tracer trace ("root_pre");
// First load outer roots, if any.
//
if (scope* rs = root.parent_scope ()->root_scope ())
- root_pre (*rs);
+ load_root_pre (*rs);
path bf (root.src_path () / path ("build/root.build"));
if (file_exists (bf))
source_once (bf, root, root);
}
+
+ void
+ import (scope& ibase, const name& n, const location& l)
+ {
+ scope& iroot (*ibase.root_scope ());
+
+ // Figure out this project's out_root.
+ //
+ const variable& var (variable_pool.find ("config." + n.value));
+ auto val (iroot[var]);
+
+ if (val)
+ {
+ if (val.scope == global_scope)
+ iroot.variables[var] = val; // Copy into root scope.
+ }
+ else
+ fail (l) << "unable to find out_root for imported " << n <<
+ info << "consider explicitly configuring its out_root via the "
+ << var.name << " command line variable";
+
+ const path& out_root (val.as<const path&> ());
+
+ // Bootstrap the imported root scope. This is pretty similar to
+ // what we do in main() except that here we don't try to guess
+ // src_root.
+ //
+ path src_root (is_src_root (out_root) ? out_root : path ());
+ scope& root (create_root (out_root, src_root));
+
+ bootstrap_out (root);
+
+ // Check that the bootstrap process set src_root.
+ //
+ if (auto v = root.ro_variables ()["src_root"])
+ {
+ const path& p (v.as<const path&> ());
+
+ if (!src_root.empty () && p != src_root)
+ fail << "bootstrapped src_root " << p << " does not match "
+ << "discovered " << src_root;
+
+ root.src_path_ = &p;
+ }
+ else
+ fail (l) << "unable to determine src_root for imported " << n <<
+ info << "consider configuring " << out_root;
+
+ bootstrap_src (root);
+
+ // Bootstrap outer roots if any. Loading will be done by
+ // load_root_pre() below.
+ //
+ create_bootstrap_outer (root);
+
+ // Load the imported root scope.
+ //
+ load_root_pre (root);
+
+ // Create a temporary scope so that the export stub does not mess
+ // up any of our variables.
+ //
+ temp_scope ts (ibase);
+
+ // "Pass" the imported project's roots to the stub.
+ //
+ ts.variables["out_root"] = out_root;
+ ts.variables["src_root"] = src_root;
+
+ // Load the export stub. Note that it is loaded in the context
+ // of the importing project, not the imported one. The export
+ // stub will normally switch to the imported root scope at some
+ // point.
+ //
+ source (root.src_path () / path ("build/export.build"), iroot, ts);
+ }
}