aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/build
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/build')
-rw-r--r--libbuild2/build/script/builtin.cli4
-rw-r--r--libbuild2/build/script/parser.cxx59
2 files changed, 61 insertions, 2 deletions
diff --git a/libbuild2/build/script/builtin.cli b/libbuild2/build/script/builtin.cli
index 6d6369b..5aea034 100644
--- a/libbuild2/build/script/builtin.cli
+++ b/libbuild2/build/script/builtin.cli
@@ -56,6 +56,10 @@ namespace build2
// lines. In the non-byproduct mode a prerequisite line that starts
// with a leading space is considered a non-existent prerequisite.
// Currently only relative non-existent prerequisites are supported.
+ // Finally, in this mode, if the prerequisite is syntactically a
+ // directory (that is, it ends with a trailing directory separator),
+ // then it is added as fsdir{}. This can be used to handle situations
+ // where the dynamic targets are placed into subdirectories.
//
// Note on naming: whenever we (may) have two options, one for target
// and the other for prerequisite, we omit "prerequisite" as that's
diff --git a/libbuild2/build/script/parser.cxx b/libbuild2/build/script/parser.cxx
index 9965799..7e2feb9 100644
--- a/libbuild2/build/script/parser.cxx
+++ b/libbuild2/build/script/parser.cxx
@@ -2434,6 +2434,61 @@ namespace build2
bool cache (skip == nullptr);
+ // Handle fsdir{} prerequisite separately.
+ //
+ // Note: inspired by inject_fsdir().
+ //
+ if (fp.to_directory ())
+ {
+ if (!cache)
+ {
+ // Note: already absolute since cannot be non-existent.
+ //
+ fp.normalize ();
+ }
+
+ const fsdir* dt (&search<fsdir> (t,
+ path_cast<dir_path> (fp),
+ dir_path (),
+ string (), nullptr, nullptr));
+
+ // Subset of code for file below.
+ //
+ if (!cache)
+ {
+ for (size_t i (0); i != pts_n; ++i)
+ {
+ const prerequisite_target& p (pts[i]);
+
+ if (const target* pt =
+ (p.target != nullptr ? p.target :
+ p.adhoc () ? reinterpret_cast<target*> (p.data) :
+ nullptr))
+ {
+ if (dt == pt)
+ return false;
+ }
+ }
+
+ if (*skip != 0)
+ {
+ --(*skip);
+ return false;
+ }
+ }
+
+ match_sync (a, *dt);
+ pts.push_back (
+ prerequisite_target (
+ nullptr, true /* adhoc */, reinterpret_cast<uintptr_t> (dt)));
+
+ if (!cache)
+ dd.expect (fp.representation ());
+
+ skip_count++;
+ return false;
+ }
+
// We can only defer the failure if we will be running the recipe
// body.
//
@@ -3013,7 +3068,8 @@ namespace build2
{
f = path (l.c_str () + n, l.size () - n);
- if (f.empty ())
+ if (f.empty () ||
+ (n && f.to_directory ())) // Non-existent fsdir{}.
throw invalid_path ("");
if (f.relative ())
@@ -3036,7 +3092,6 @@ namespace build2
//
throw invalid_path ("");
}
-
}
catch (const invalid_path&)
{