diff options
-rw-r--r-- | libbuild2/parser.cxx | 22 | ||||
-rw-r--r-- | libbuild2/scope.cxx | 41 |
2 files changed, 43 insertions, 20 deletions
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx index d5514b7..f0eafb3 100644 --- a/libbuild2/parser.cxx +++ b/libbuild2/parser.cxx @@ -2515,25 +2515,25 @@ namespace build2 o.dir.normalize (); // Note: don't collapse current to empty. - // Make sure out and src are parallel. - // - // See similar code for targets in scope::find_target_type(). + // 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). // // For now we require that both are either relative or absolute. // - if (n.dir.empty () && o.dir.current ()) + // See similar code for targets in scope::find_target_type(). + // + if (n.dir.absolute () && o.dir.absolute ()) + ; + else if (n.dir.empty () && o.dir.current ()) ; else if (o.dir.relative () && n.dir.relative () && o.dir == n.dir) ; - else if (o.dir.absolute () && - n.dir.absolute () && - o.dir.sub (root_->out_path ()) && - n.dir.sub (root_->src_path ()) && - o.dir.leaf (root_->out_path ()) == - n.dir.leaf (root_->src_path ())) - ; else fail (ploc) << "prerequisite output directory " << o.dir << " must be parallel to source directory " << n.dir; diff --git a/libbuild2/scope.cxx b/libbuild2/scope.cxx index 0d952f0..51a1c25 100644 --- a/libbuild2/scope.cxx +++ b/libbuild2/scope.cxx @@ -811,12 +811,16 @@ namespace build2 const dir_path& sd (src_path ()); const dir_path& od (out_path ()); + bool nabs (false); + if (dir.empty ()) - dir = src ? sd : od; // Already dormalized. + dir = src ? sd : od; // Already normalized. else { if (dir.relative ()) dir = (src ? sd : od) / dir; + else if (src) + nabs = true; dir.normalize (); } @@ -824,16 +828,30 @@ namespace build2 dir_path out; 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. + // 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 (out.sub (root_->out_path ()) && - dir.sub (root_->src_path ()) && - out.leaf (root_->out_path ()) == dir.leaf (root_->src_path ())) + 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. @@ -841,10 +859,15 @@ namespace build2 warn (loc) << "target output directory " << out << " must be parallel to source directory " << dir; - // If in source build, then out must be empty. + // 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 (sd == od) - out.clear (); + if (root_->out_eq_src ()) + { + if (!nabs || !oabs || out.sub (root_->out_path ())) + out.clear (); + } } o.dir = move (out); // Result. |