From 534f9d8db025d58c9ce23f3b81a37e8c34386a27 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 13 Apr 2015 10:29:25 +0200 Subject: Add initial import support --- build/file.cxx | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 167 insertions(+), 2 deletions(-) (limited to 'build/file.cxx') 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 ()); + 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 ()); + + 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 ()) + { + // 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 ()); + + 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 ()); + + // 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 ()); + + 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); + } } -- cgit v1.1