From 2d4b7eb982d2f7140d8093d9b1f0c3498d84f936 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 30 May 2023 09:36:35 +0200 Subject: Add support for fsdir{} dynamic prerequisites in the dyndep lines format This can be used to handle situations where the dynamic targets are placed into subdirectories. --- libbuild2/build/script/builtin.cli | 4 +++ libbuild2/build/script/parser.cxx | 59 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 2 deletions(-) (limited to 'libbuild2/build') 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 (t, + path_cast (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 (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 (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&) { -- cgit v1.1