aboutsummaryrefslogtreecommitdiff
path: root/build
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-07-13 12:20:27 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-07-13 12:20:27 +0200
commit70613e9be046c9cddd2486505a44d3a0324d6d95 (patch)
tree48068dc88aca74f3587ea61cc47f8a4676107564 /build
parentbef7c36a3479b9b83eaf4be9ef090b21d6468f12 (diff)
Implement subproject import
Diffstat (limited to 'build')
-rw-r--r--build/config/operation.cxx6
-rw-r--r--build/file.cxx99
-rw-r--r--build/rule.cxx4
-rw-r--r--build/variable13
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;