From b5d143f529e4ebbeb7a1746312e38da815e2e321 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 8 May 2023 13:21:55 +0200 Subject: Add --load-only option in addition to --match-only This option has the effect of loading all the subdirectory buildfiles that are not explicitly included. --- build2/b.cxx | 21 +++++++++++++++++++-- libbuild2/b-cmdline.cxx | 3 +++ libbuild2/b-options.cxx | 24 ++++++++++++++++++++++-- libbuild2/b-options.hxx | 4 ++++ libbuild2/b-options.ixx | 6 ++++++ libbuild2/b.cli | 17 ++++++++++++++--- libbuild2/context.cxx | 4 ++-- libbuild2/context.hxx | 16 +++++++++++++--- libbuild2/dist/operation.cxx | 4 ++-- libbuild2/module.cxx | 2 +- libbuild2/rule.cxx | 18 +++++++++++++++++- 11 files changed, 103 insertions(+), 16 deletions(-) diff --git a/build2/b.cxx b/build2/b.cxx index 163a89e..72c49e9 100644 --- a/build2/b.cxx +++ b/build2/b.cxx @@ -416,10 +416,14 @@ main (int argc, char* argv[]) pctx = nullptr; // Free first to reuse memory. } + optional mo; + if (ops.load_only ()) mo = match_only_level::alias; + else if (ops.match_only ()) mo = match_only_level::all; + pctx.reset (new context (sched, mutexes, fcache, - ops.match_only (), + mo, ops.no_external_modules (), ops.dry_run (), ops.no_diag_buffer (), @@ -479,6 +483,8 @@ main (int argc, char* argv[]) 1100 /* variables */}); } + bool load_only (ops.load_only ()); + const path& buildfile (ops.buildfile_specified () ? ops.buildfile () : empty_path); @@ -1409,6 +1415,9 @@ main (int argc, char* argv[]) break; } + if (load_only && (mid != perform_id || oid != update_id)) + fail << "--load-only requires perform(update) action"; + // Now load the buildfiles and search the targets. // action_targets tgs; @@ -1440,6 +1449,9 @@ main (int argc, char* argv[]) if (tt == nullptr) fail (l) << "unknown target type " << tn.type; + if (load_only && !tt->is_a ()) + fail << "--load-only requires alias target"; + if (mif->search != nullptr) { // If the directory is relative, assume it is relative to work @@ -1470,7 +1482,9 @@ main (int argc, char* argv[]) } } // target - if (dump_load) + // Delay until after match in the --load-only mode (see below). + // + if (dump_load && !load_only) dump (ctx, nullopt /* action */); // Finally, match the rules and perform the operation. @@ -1610,6 +1624,9 @@ main (int argc, char* argv[]) << ", id " << static_cast (post_oid);}); } + if (dump_load && load_only) + dump (ctx, nullopt /* action */); + if (mif->operation_post != nullptr) mif->operation_post (ctx, mparams, oid); diff --git a/libbuild2/b-cmdline.cxx b/libbuild2/b-cmdline.cxx index b7d0726..77ad087 100644 --- a/libbuild2/b-cmdline.cxx +++ b/libbuild2/b-cmdline.cxx @@ -418,6 +418,9 @@ namespace build2 if (ops.mtime_check () && ops.no_mtime_check ()) fail << "both --mtime-check and --no-mtime-check specified"; + + if (ops.match_only () && ops.load_only ()) + fail << "both --match-only and --load-only specified"; } catch (const cli::exception& e) { diff --git a/libbuild2/b-options.cxx b/libbuild2/b-options.cxx index 0ff788e..251c709 100644 --- a/libbuild2/b-options.cxx +++ b/libbuild2/b-options.cxx @@ -354,6 +354,7 @@ namespace build2 dry_run_ (), no_diag_buffer_ (), match_only_ (), + load_only_ (), no_external_modules_ (), structured_result_ (), structured_result_specified_ (false), @@ -588,6 +589,12 @@ namespace build2 this->match_only_, a.match_only_); } + if (a.load_only_) + { + ::build2::build::cli::parser< bool>::merge ( + this->load_only_, a.load_only_); + } + if (a.no_external_modules_) { ::build2::build::cli::parser< bool>::merge ( @@ -883,8 +890,18 @@ namespace build2 << " lines and thus could be tolerable." << ::std::endl; os << std::endl - << "\033[1m--match-only\033[0m Match the rules but do not execute the operation. This" << ::std::endl - << " mode is primarily useful for profiling." << ::std::endl; + << "\033[1m--match-only\033[0m Match the rules without executing the operation. This" << ::std::endl + << " mode is primarily useful for profiling and dumping the" << ::std::endl + << " build system state." << ::std::endl; + + os << std::endl + << "\033[1m--load-only\033[0m Match the rules only to \033[1malias{}\033[0m targets ignoring other" << ::std::endl + << " targets and without executing the operation. In" << ::std::endl + << " particular, this has the effect of loading all the" << ::std::endl + << " subdirectory \033[1mbuildfiles\033[0m that are not explicitly" << ::std::endl + << " included. Note that this option can only be used with" << ::std::endl + << " the \033[1mperform(update)\033[0m action on an \033[1malias{}\033[0m target," << ::std::endl + << " usually \033[1mdir{}\033[0m." << ::std::endl; os << std::endl << "\033[1m--no-external-modules\033[0m Don't load external modules during project bootstrap." << ::std::endl @@ -991,6 +1008,7 @@ namespace build2 << " the state after multiple phases/variants. By default" << ::std::endl << " the entire build state is dumped but this behavior can" << ::std::endl << " be altered with the \033[1m--dump-scope\033[0m and \033[1m--dump-target\033[0m" << ::std::endl + << " options. See also the \033[1m--match-only\033[0m and \033[1m--load-only\033[0m" << ::std::endl << " options." << ::std::endl; os << std::endl @@ -1191,6 +1209,8 @@ namespace build2 &::build2::build::cli::thunk< b_options, &b_options::no_diag_buffer_ >; _cli_b_options_map_["--match-only"] = &::build2::build::cli::thunk< b_options, &b_options::match_only_ >; + _cli_b_options_map_["--load-only"] = + &::build2::build::cli::thunk< b_options, &b_options::load_only_ >; _cli_b_options_map_["--no-external-modules"] = &::build2::build::cli::thunk< b_options, &b_options::no_external_modules_ >; _cli_b_options_map_["--structured-result"] = diff --git a/libbuild2/b-options.hxx b/libbuild2/b-options.hxx index 37239ce..48dd35f 100644 --- a/libbuild2/b-options.hxx +++ b/libbuild2/b-options.hxx @@ -151,6 +151,9 @@ namespace build2 match_only () const; const bool& + load_only () const; + + const bool& no_external_modules () const; const structured_result_format& @@ -304,6 +307,7 @@ namespace build2 bool dry_run_; bool no_diag_buffer_; bool match_only_; + bool load_only_; bool no_external_modules_; structured_result_format structured_result_; bool structured_result_specified_; diff --git a/libbuild2/b-options.ixx b/libbuild2/b-options.ixx index 99e73d0..34b0d39 100644 --- a/libbuild2/b-options.ixx +++ b/libbuild2/b-options.ixx @@ -177,6 +177,12 @@ namespace build2 } inline const bool& b_options:: + load_only () const + { + return this->load_only_; + } + + inline const bool& b_options:: no_external_modules () const { return this->no_external_modules_; diff --git a/libbuild2/b.cli b/libbuild2/b.cli index deb6a26..c9dfddd 100644 --- a/libbuild2/b.cli +++ b/libbuild2/b.cli @@ -663,8 +663,18 @@ namespace build2 bool --match-only { - "Match the rules but do not execute the operation. This mode is primarily - useful for profiling." + "Match the rules without executing the operation. This mode is primarily + useful for profiling and dumping the build system state." + } + + bool --load-only + { + "Match the rules only to \cb{alias{\}} targets ignoring other targets + and without executing the operation. In particular, this has the + effect of loading all the subdirectory \cb{buildfiles} that are not + explicitly included. Note that this option can only be used with the + \cb{perform(update)} action on an \cb{alias{\}} target, usually + \cb{dir{\}}." } bool --no-external-modules @@ -782,7 +792,8 @@ namespace build2 pre/post-operations (\cb{match} dumps the main operation only). Repeat this option to dump the state after multiple phases/variants. By default the entire build state is dumped but this behavior can be - altered with the \cb{--dump-scope} and \cb{--dump-target} options." + altered with the \cb{--dump-scope} and \cb{--dump-target} options. + See also the \cb{--match-only} and \cb{--load-only} options." } string --dump-format diff --git a/libbuild2/context.cxx b/libbuild2/context.cxx index afbb59a..3c101eb 100644 --- a/libbuild2/context.cxx +++ b/libbuild2/context.cxx @@ -290,7 +290,7 @@ namespace build2 context (scheduler& s, global_mutexes& ms, file_cache& fc, - bool mo, + optional mo, bool nem, bool dr, bool ndb, @@ -716,7 +716,7 @@ namespace build2 sched (nullptr), mutexes (nullptr), fcache (nullptr), - match_only (false), + match_only (nullopt), no_external_modules (true), dry_run_option (false), no_diag_buffer (false), diff --git a/libbuild2/context.hxx b/libbuild2/context.hxx index b0fac02..7574787 100644 --- a/libbuild2/context.hxx +++ b/libbuild2/context.hxx @@ -120,6 +120,16 @@ namespace build2 } }; + // Match-only level. + // + // See the --match-only and --load-only options for background. + // + enum class match_only_level + { + alias, // Match only alias{} targets. + all // Match all targets. + }; + // A build context encapsulates the state of a build. It is possible to have // multiple build contexts provided they are non-overlapping, that is, they // don't try to build the same projects (note that this is currently not @@ -217,9 +227,9 @@ namespace build2 global_mutexes* mutexes; file_cache* fcache; - // Match only flag (see --match-only but also dist). + // Match only flag/level (see --{load,match}-only but also dist). // - bool match_only; + optional match_only; // Skip booting external modules flag (see --no-external-modules). // @@ -689,7 +699,7 @@ namespace build2 context (scheduler&, global_mutexes&, file_cache&, - bool match_only = false, + optional match_only = nullopt, bool no_external_modules = false, bool dry_run = false, bool no_diag_buffer = false, diff --git a/libbuild2/dist/operation.cxx b/libbuild2/dist/operation.cxx index 45b1688..6dcc88a 100644 --- a/libbuild2/dist/operation.cxx +++ b/libbuild2/dist/operation.cxx @@ -302,8 +302,8 @@ namespace build2 } }; - auto mog = make_guard ([&ctx] () {ctx.match_only = false;}); - ctx.match_only = true; + auto mog = make_guard ([&ctx] () {ctx.match_only = nullopt;}); + ctx.match_only = match_only_level::all; const operations& ops (rs.root_extra->operations); for (operations::size_type id (default_id + 1); // Skip default_id. diff --git a/libbuild2/module.cxx b/libbuild2/module.cxx index dd83225..1aaa38d 100644 --- a/libbuild2/module.cxx +++ b/libbuild2/module.cxx @@ -83,7 +83,7 @@ namespace build2 new context (*ctx.sched, *ctx.mutexes, *ctx.fcache, - false, /* match_only */ + nullopt, /* match_only */ false, /* no_external_modules */ false, /* dry_run */ ctx.no_diag_buffer, diff --git a/libbuild2/rule.cxx b/libbuild2/rule.cxx index 5d456d5..0b401c2 100644 --- a/libbuild2/rule.cxx +++ b/libbuild2/rule.cxx @@ -219,7 +219,23 @@ namespace build2 // inject_fsdir (a, t, true, false); - match_prerequisites (a, t); + // Handle the alias match-only level. + // + match_search ms; + if (t.ctx.match_only && *t.ctx.match_only == match_only_level::alias) + { + ms = [] (action, + const target& t, + const prerequisite& p, + include_type i) + { + return prerequisite_target ( + p.is_a () ? &search (t, p) : nullptr, + i); + }; + } + + match_prerequisites (a, t, ms); return default_recipe; } -- cgit v1.1