diff options
Diffstat (limited to 'libbuild2/scope.cxx')
-rw-r--r-- | libbuild2/scope.cxx | 73 |
1 files changed, 60 insertions, 13 deletions
diff --git a/libbuild2/scope.cxx b/libbuild2/scope.cxx index 93f21db..be2669d 100644 --- a/libbuild2/scope.cxx +++ b/libbuild2/scope.cxx @@ -23,7 +23,7 @@ namespace build2 ? empty_project_name : i->first); - os << (i != b ? " " : "") << n << '@' << i->second; + os << (i != b ? " " : "") << n << '@' << i->second.string (); } return os; @@ -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) { } @@ -806,26 +806,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. @@ -910,7 +952,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 +972,13 @@ 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; + dt->flags |= flags; #if 0 // @@ We should probably inherit the fixed extension unless overriden with @@ -1028,7 +1075,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; } |