From 82e9227262a41bfa740952659b3b91d2d99e984e Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 3 Dec 2021 09:47:05 +0200 Subject: Add depdb-dyndep --drop-cycles option --- libbuild2/build/script/parser.cxx | 72 +++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 26 deletions(-) (limited to 'libbuild2/build/script/parser.cxx') diff --git a/libbuild2/build/script/parser.cxx b/libbuild2/build/script/parser.cxx index 15545cf..2210cc8 100644 --- a/libbuild2/build/script/parser.cxx +++ b/libbuild2/build/script/parser.cxx @@ -1442,7 +1442,8 @@ namespace build2 move (cwd), move (*file), ops.what_specified () ? move (ops.what ()) : string (what), - def_pt}; + def_pt, + ops.drop_cycles ()}; return; } @@ -1600,13 +1601,15 @@ namespace build2 auto add = [this, &trace, what, a, &bs, &t, &pts, pts_n = pts.size (), - &map_ext, def_pt, &pfx_map, &so_map, + &ops, &map_ext, def_pt, &pfx_map, &so_map, &dd, &skip_count] (path fp, - bool cache, + size_t* skip, timestamp mt) -> optional { context& ctx (t.ctx); + bool cache (skip == nullptr); + // We can only defer the failure if we will be running the recipe // body. // @@ -1636,26 +1639,51 @@ namespace build2 fp, cache, cache /* normalized */, map_ext, *def_pt, pfx_map, so_map).first) { - // Skip if this is one of the static prerequisites. + // We don't need to do these tests for the cached case since such + // prerequisites would have been skipped (and we won't get here if + // the target/prerequisite set changes since we hash them). // - for (size_t i (0); i != pts_n; ++i) + if (!cache) { - const prerequisite_target& p (pts[i]); + // Skip if this is one of the static prerequisites. + // + 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.data != 0 ? reinterpret_cast (p.data) : - nullptr)) + if (const target* pt = + (p.target != nullptr ? p.target : + p.data != 0 ? reinterpret_cast (p.data) : + nullptr)) + { + if (ft == pt) + return false; + } + } + + // Skip if this is one of the targets. + // + if (ops.drop_cycles ()) { - if (pt == ft) + for (const target* m (&t); m != nullptr; m = m->adhoc_member) { - // Note that we have to increment the skip count since we - // skip before performing this test. - // - skip_count++; - return false; + if (ft == m) + return false; } } + + // Skip until where we left off. + // + // Note that we used to do this outside of this lambda and + // before calling enter_file() but due to the above skips we can + // only do it here if we want to have a consistent view of the + // prerequisite lists between the cached and non-cached cases. + // + if (*skip != 0) + { + --(*skip); + return false; + } } if (optional u = dyndep::inject_file ( @@ -1724,7 +1752,7 @@ namespace build2 if (l->empty ()) // Done, nothing changed. return; - if (optional r = add (path (move (*l)), true /*cache*/, mt)) + if (optional r = add (path (move (*l)), nullptr, mt)) { restart = *r; @@ -1880,16 +1908,8 @@ namespace build2 if (r.first == make_type::target) continue; - // Skip until where we left off. - // - if (skip != 0) - { - skip--; - continue; - } - if (optional u = add (path (move (r.second)), - false /* cache */, + &skip, rmt)) { restart = *u; -- cgit v1.1