diff options
Diffstat (limited to 'libbuild2/scope.cxx')
-rw-r--r-- | libbuild2/scope.cxx | 131 |
1 files changed, 102 insertions, 29 deletions
diff --git a/libbuild2/scope.cxx b/libbuild2/scope.cxx index 814d876..23781a8 100644 --- a/libbuild2/scope.cxx +++ b/libbuild2/scope.cxx @@ -32,8 +32,8 @@ namespace build2 // scope // scope:: - scope (context& c, bool global) - : ctx (c), vars (c, global), target_vars (c, global) + scope (context& c, bool shared) + : ctx (c), vars (*this, shared), target_vars (c, shared) { } @@ -685,6 +685,8 @@ namespace build2 pair<const target_type*, optional<string>> scope:: find_target_type (name& n, const location& loc, const target_type* tt) const { + // NOTE: see also functions-name.cxx:filter() if changing anything here. + optional<string> ext; string& v (n.value); @@ -790,9 +792,11 @@ namespace build2 } pair<const target_type&, optional<string>> scope:: - find_target_type (name& n, name& o, const location& loc) const + find_target_type (name& n, name& o, + const location& loc, + const target_type* tt) const { - auto r (find_target_type (n, loc)); + auto r (find_target_type (n, loc, tt)); if (r.first == nullptr) fail (loc) << "unknown target type " << n.type << " in " << n; @@ -806,26 +810,68 @@ namespace build2 fail (loc) << "expected directory after '@'"; } - dir_path& d (n.dir); + dir_path& dir (n.dir); const dir_path& sd (src_path ()); const dir_path& od (out_path ()); - if (d.empty ()) - d = src ? sd : od; // Already dormalized. + bool nabs (false); + + if (dir.empty ()) + dir = src ? sd : od; // Already normalized. else { - if (d.relative ()) - d = (src ? sd : od) / d; + if (dir.relative ()) + dir = (src ? sd : od) / dir; + else if (src) + nabs = true; - d.normalize (); + dir.normalize (); } dir_path out; - if (src && sd != od) // If in source build, then out must be empty. + if (src) { - out = o.dir.relative () ? od / o.dir : move (o.dir); + bool oabs (o.dir.absolute ()); + + out = oabs ? move (o.dir) : od / o.dir; out.normalize (); + + // Make sure out and src are parallel unless both were specified as + // absolute. We make an exception for this case because out may be used + // to "tag" imported targets (see cc::search_library()). So it's sort of + // the "I know what I am doing" escape hatch (it would have been even + // better to verify such a target is outside any project but that won't + // be cheap). + // + // See similar code for prerequisites in parser::parse_dependency(). + // + if (nabs && oabs) + ; + else if (root_->out_eq_src () + ? out == dir + // + // @@ PERF: could just compare leafs in place. + // + : (out.sub (root_->out_path ()) && + dir.sub (root_->src_path ()) && + out.leaf (root_->out_path ()) == dir.leaf (root_->src_path ()))) + ; + else + // @@ TMP change warn to fail after 0.16.0 release. + // + warn (loc) << "target output directory " << out + << " must be parallel to source directory " << dir; + + // If this target is in this project, then out must be empty if this is + // in source build. We assume that if either src or out are relative, + // then it belongs to this project. + // + if (root_->out_eq_src ()) + { + if (!nabs || !oabs || out.sub (root_->out_path ())) + out.clear (); + } } o.dir = move (out); // Result. @@ -834,14 +880,16 @@ namespace build2 } target_key scope:: - find_target_key (names& ns, const location& loc) const + find_target_key (names& ns, + const location& loc, + const target_type* tt) const { if (size_t n = ns.size ()) { if (n == (ns[0].pair ? 2 : 1)) { name dummy; - return find_target_key (ns[0], n == 1 ? dummy : ns[1], loc); + return find_target_key (ns[0], n == 1 ? dummy : ns[1], loc, tt); } } @@ -849,9 +897,11 @@ namespace build2 } pair<const target_type&, optional<string>> scope:: - find_prerequisite_type (name& n, name& o, const location& loc) const + find_prerequisite_type (name& n, name& o, + const location& loc, + const target_type* tt) const { - auto r (find_target_type (n, loc)); + auto r (find_target_type (n, loc, tt)); if (r.first == nullptr) fail (loc) << "unknown target type " << n.type << " in " << n; @@ -875,14 +925,16 @@ namespace build2 } prerequisite_key scope:: - find_prerequisite_key (names& ns, const location& loc) const + find_prerequisite_key (names& ns, + const location& loc, + const target_type* tt) const { if (size_t n = ns.size ()) { if (n == (ns[0].pair ? 2 : 1)) { name dummy; - return find_prerequisite_key (ns[0], n == 1 ? dummy : ns[1], loc); + return find_prerequisite_key (ns[0], n == 1 ? dummy : ns[1], loc, tt); } } @@ -910,7 +962,9 @@ namespace build2 } pair<reference_wrapper<const target_type>, bool> scope:: - derive_target_type (const string& name, const target_type& base) + derive_target_type (const string& name, + const target_type& base, + target_type::flag flags) { assert (root_scope () == this); @@ -928,10 +982,20 @@ namespace build2 // // Currently, if we define myfile{}: file{}, then myfile{foo} and // myfile{foo.x} are the same target. + + // Note: copies flags. // - unique_ptr<target_type> dt (new target_type (base)); - dt->base = &base; - dt->factory = &derived_tt_factory; + unique_ptr<target_type> dt ( + new target_type { + nullptr, // Will be patched in by insert() below. + &base, + &derived_tt_factory, + base.fixed_extension, + base.default_extension, + base.pattern, + base.print, + base.search, + base.flags | flags}); #if 0 // @@ We should probably inherit the fixed extension unless overriden with @@ -1010,8 +1074,17 @@ namespace build2 derive_target_type (const target_type& et) { assert (root_scope () == this); - unique_ptr<target_type> dt (new target_type (et)); - dt->factory = &derived_tt_factory; + unique_ptr<target_type> dt ( + new target_type { + nullptr, // Will be patched in by insert() below. + et.base, + &derived_tt_factory, + et.fixed_extension, + et.default_extension, + et.pattern, + et.print, + et.search, + et.flags}); return root_extra->target_types.insert (et.name, move (dt)).first; } @@ -1028,7 +1101,7 @@ namespace build2 if (er.first->second.front () == nullptr) { - er.first->second.front () = new scope (ctx, true /* global */); + er.first->second.front () = new scope (ctx, true /* shared */); er.second = true; } @@ -1132,8 +1205,8 @@ namespace build2 } auto scope_map:: - find (const dir_path& k) const -> pair<scopes::const_iterator, - scopes::const_iterator> + find (const dir_path& k, bool sno) const -> pair<scopes::const_iterator, + scopes::const_iterator> { assert (k.normalized (false)); auto i (map_.find_sup (k)); @@ -1142,9 +1215,9 @@ namespace build2 auto b (i->second.begin ()); auto e (i->second.end ()); - // Skip NULL first element. + // Skip NULL first element if requested. // - if (*b == nullptr) + if (sno && *b == nullptr) ++b; assert (b != e); |