diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-07-13 12:20:27 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-07-13 12:20:27 +0200 |
commit | 70613e9be046c9cddd2486505a44d3a0324d6d95 (patch) | |
tree | 48068dc88aca74f3587ea61cc47f8a4676107564 /build | |
parent | bef7c36a3479b9b83eaf4be9ef090b21d6468f12 (diff) |
Implement subproject import
Diffstat (limited to 'build')
-rw-r--r-- | build/config/operation.cxx | 6 | ||||
-rw-r--r-- | build/file.cxx | 99 | ||||
-rw-r--r-- | build/rule.cxx | 4 | ||||
-rw-r--r-- | build/variable | 13 |
4 files changed, 87 insertions, 35 deletions
diff --git a/build/config/operation.cxx b/build/config/operation.cxx index 43a5718..57bb60d 100644 --- a/build/config/operation.cxx +++ b/build/config/operation.cxx @@ -245,10 +245,10 @@ namespace build } static void - disfigure_match (action a, + disfigure_match (action, scope& root, - const target_key& tk, - const location& l, + const target_key&, + const location&, action_targets& ts) { tracer trace ("disfigure_match"); diff --git a/build/file.cxx b/build/file.cxx index b58d8e8..0dff025 100644 --- a/build/file.cxx +++ b/build/file.cxx @@ -647,6 +647,8 @@ namespace build string project; name target; + // @@ This is probably all wrong. + // if (n.dir.empty ()) { if (!n.simple ()) @@ -656,7 +658,7 @@ namespace build // means sub-projects? Or only to a certain point, then // (untyped) target? Looks like I will need to scan anything // that looks like a directory checking if this is a subproject. - // If not, then that's part of the target. + // If not, then that's part of the target. No, no, nooooo! // project = n.value; } @@ -680,48 +682,77 @@ namespace build // Figure out this project's out_root. // dir_path out_root; - string var ("config.import." + project); + dir_path fallback_src_root; // We have seen this already, havent' we ? - if (auto v = iroot[var]) + // First search subprojects, starting with our root and then trying + // outer roots for as long as we are inside an amalgamation. + // + for (scope* r (&iroot);; r = r->parent_scope ()->root_scope ()) { - if (!v.belongs (*global_scope)) // A value from (some) config.build. - out_root = v.as<const dir_path&> (); - else + if (auto v = r->vars["subprojects"]) { - // Process the path by making it absolute and normalized. Also, - // for usability's sake, treat a simple name that doesn't end - // with '/' as a directory. + // @@ Map sure would have been handy. // - list_value& lv (v.as<list_value&> ()); + if (const name* n = v.as<const list_value&> ().find_pair (project)) + { + out_root = r->path () / n->dir; + fallback_src_root = r->src_path () / n->dir; + break; + } + } - if (lv.size () != 1 || lv[0].empty () || !lv[0].type.empty ()) - fail (l) << "invalid " << var << " value " << lv; + if (!r->vars["amalgamation"]) + break; + } - name& n (lv[0]); - if (n.directory ()) - out_root = n.dir; + // Then try the config.import.* mechanism. + // + if (out_root.empty ()) + { + string var ("config.import." + project); + + if (auto v = iroot[var]) + { + if (!v.belongs (*global_scope)) // A value from (some) config.build. + out_root = v.as<const dir_path&> (); else - out_root = dir_path (n.value); + { + // Process the path by making it absolute and normalized. Also, + // for usability's sake, treat a simple name that doesn't end + // with '/' as a directory. + // + list_value& lv (v.as<list_value&> ()); - if (out_root.relative ()) - out_root = work / out_root; + if (lv.size () != 1 || lv[0].empty () || !lv[0].type.empty ()) + fail (l) << "invalid " << var << " value " << lv; - out_root.normalize (); - iroot.assign (var) = out_root; + name& n (lv[0]); - // Also update the command-line value. This is necessary to avoid - // a warning issued by the config module about global/root scope - // value mismatch. - // - if (n.dir != out_root) - n = name (out_root); + if (n.directory ()) + out_root = n.dir; + else + out_root = dir_path (n.value); + + if (out_root.relative ()) + out_root = work / out_root; + + out_root.normalize (); + iroot.assign (var) = out_root; + + // Also update the command-line value. This is necessary to avoid + // a warning issued by the config module about global/root scope + // value mismatch. + // + if (n.dir != out_root) + n = name (out_root); + } } + else + fail (l) << "unable to find out_root for imported " << project << + info << "consider explicitly configuring its out_root via the " + << var << " command line variable"; } - else - fail (l) << "unable to find out_root for imported " << project << - info << "consider explicitly configuring its out_root via the " - << var << " command line variable"; // Bootstrap the imported root scope. This is pretty similar to // what we do in main() except that here we don't try to guess @@ -744,6 +775,14 @@ namespace build root.src_path_ = &p; } + // Otherwise, use fallback if available. + // + else if (!fallback_src_root.empty ()) + { + auto v (root.assign ("src_root")); + v = move (fallback_src_root); + root.src_path_ = &v.as<const dir_path&> (); + } else fail (l) << "unable to determine src_root for imported " << project << info << "consider configuring " << out_root; diff --git a/build/rule.cxx b/build/rule.cxx index eadbecb..8f3a7a9 100644 --- a/build/rule.cxx +++ b/build/rule.cxx @@ -136,7 +136,7 @@ namespace build // dir_rule // match_result dir_rule:: - match (action a, target& t, const string&) const + match (action, target& t, const string&) const { return t; } @@ -151,7 +151,7 @@ namespace build // fsdir_rule // match_result fsdir_rule:: - match (action a, target& t, const string&) const + match (action, target& t, const string&) const { return t; } diff --git a/build/variable b/build/variable index 2bb3393..835fde1 100644 --- a/build/variable +++ b/build/variable @@ -84,6 +84,19 @@ namespace build const list_value* lv (dynamic_cast<const list_value*> (&v)); return lv != nullptr && static_cast<const names&> (*this) == *lv; } + + // Pair (i.e., key-value) search. Note that this funtion assumes + // the list contains only pairs and keys are simple names. Returns + // NULL if not found. + // + const name* + find_pair (const std::string& key) const + { + for (auto i (begin ()); i != end (); i += 2) + if (i->value == key) + return &*++i; + return nullptr; + } }; typedef std::unique_ptr<list_value> list_value_ptr; |