From 9b5acba21213c2bf87d92b0a12f4d41283a13ae3 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 21 Feb 2022 06:36:52 +0200 Subject: Complete build system command line parsing/processing --- bpkg/bpkg.cxx | 110 +++++++++++++++++++++++++++++----------------- bpkg/package-skeleton.cxx | 39 ++++++++++------ bpkg/package-skeleton.hxx | 1 + 3 files changed, 96 insertions(+), 54 deletions(-) diff --git a/bpkg/bpkg.cxx b/bpkg/bpkg.cxx index 137d823..c85372e 100644 --- a/bpkg/bpkg.cxx +++ b/bpkg/bpkg.cxx @@ -21,6 +21,9 @@ #include #include +#include +#include + #include #include #include @@ -100,6 +103,7 @@ namespace bpkg std::terminate (); } + strings build2_cmd_vars; build2::scheduler build2_sched; build2::global_mutexes build2_mutexes; build2::file_cache build2_fcache; @@ -426,30 +430,66 @@ init (const char* argv0, if (bsys) try { - // For now we use the same verbosity as us (equivalent to start_b() with - // verb_b::normal). + using namespace build2; + using build2::fail; + using build2::endf; + + build2::tracer trace ("init"); + + // Parse --build-option values as the build2 driver command line. // - build2::init_diag (verb, - false /* silent */, - (o.progress () ? optional (true) : - o.no_progress () ? optional (false) : - nullopt), - false /* no_lines */, - false /* no_columns */, - stderr_term); - - build2::init (&build2_terminate, - argv0, - // - // @@ Should we try to parse --build-option and extract - // these (having config_* is plausible)? Also - // --file-cache below. - // - nullopt /* mtime_check */, - nullopt /* config_sub */, - nullopt /* config_guess */); - - using build2::load_builtin_module; + // With things like verbosity, progress, etc., we use values from + // --build-option if specified, falling back to equivalent bpkg values + // otherwise. + // + build2::options bo; + cmdline bc; + { + small_vector argv {const_cast (argv0)}; + + if (size_t n = o.build_option ().size ()) + { + argv.reserve (n + 1); + + for (const string& a: o.build_option ()) + argv.push_back (const_cast (a.c_str ())); + } + + // Note that this function also parses the default options files and + // gets/sets the relevant environment variables. + // + // For now we use the same default verbosity as us (equivalent to + // start_b() with verb_b::normal). + // + bc = parse_cmdline (trace, + static_cast (argv.size ()), argv.data (), + bo, + bpkg::verb, + o.jobs_specified () ? o.jobs () : 0); + + if (!bc.buildspec.empty ()) + fail << "argument specified with --build-option"; + + if (bo.help () || bo.version ()) + fail << "--help or --version specified with --build-option"; + } + + build2_cmd_vars = move (bc.cmd_vars); + + init_diag (bc.verbosity, + bo.silent (), + (bc.progress ? bc.progress : + o.progress () ? optional (true) : + o.no_progress () ? optional (false) : nullopt), + bo.no_line (), + bo.no_column (), + bpkg::stderr_term); + + init (&build2_terminate, + argv0, + bc.mtime_check, + bc.config_sub, + bc.config_guess); load_builtin_module (&build2::config::build2_config_load); load_builtin_module (&build2::dist::build2_dist_load); @@ -472,25 +512,15 @@ init (const char* argv0, // relatively cheap. The module building logic will then re-tune it to // parallel if and when necessary. // - // @@ TODO: options (scheduler values). - // - size_t jobs (0); - - if (jobs == 0) - jobs = build2::scheduler::hardware_concurrency (); - - if (jobs == 0) - jobs = 1; - - build2_sched.startup (1 /* max_active */, - 1 /* init_active */, - 0 /* max_jobs */, - 0 /* queue_depth */, - nullopt /* max_stack */, - jobs /* orig_max_active */); + build2_sched.startup (1 /* max_active */, + 1 /* init_active */, + bc.max_jobs, + bc.jobs * bo.queue_depth (), + bc.max_stack, + bc.jobs); build2_mutexes.init (build2_sched.shard_size ()); - build2_fcache.init (true); + build2_fcache.init (bc.fcache_compress); } catch (const build2::failed&) { diff --git a/bpkg/package-skeleton.cxx b/bpkg/package-skeleton.cxx index 9cffef1..76bd816 100644 --- a/bpkg/package-skeleton.cxx +++ b/bpkg/package-skeleton.cxx @@ -31,6 +31,7 @@ namespace bpkg { // These are defined in bpkg.cxx and initialized in main(). // + extern strings build2_cmd_vars; extern build2::scheduler build2_sched; extern build2::global_mutexes build2_mutexes; extern build2::file_cache build2_fcache; @@ -59,6 +60,7 @@ namespace bpkg created_ = v.created_; ctx_ = move (v.ctx_); rs_ = v.rs_; + cmd_vars_ = move (v.cmd_vars_); reflect_names_ = move (v.reflect_names_); reflect_vars_ = move (v.reflect_vars_); reflect_frag_ = move (v.reflect_frag_); @@ -78,6 +80,7 @@ namespace bpkg src_root_ (v.src_root_), out_root_ (v.out_root_), created_ (v.created_), + cmd_vars_ (v.cmd_vars_), reflect_names_ (v.reflect_names_), reflect_vars_ (v.reflect_vars_), reflect_frag_ (v.reflect_frag_) @@ -720,22 +723,30 @@ namespace bpkg // Create build context. // - // @@ BUILD2_VAR_OVR, environment/default options files? E.g., !config - // to find module... Can't we make it reusable in build2? - // - // @@ What is our story about build system modules? It seems we will - // only support built-in and standard pre-installed modules here - // (otherwise we would need to build all the module dependencies - // before we can evaluate any of this). Which means they cannot be - // built except during development. Maybe start parallel scheduler - // if dev build? But is it not possible someone will use installed - // bpkg to develop a module? Why don't we just start a parallel - // scheduler always (though that would be wasted overhead most of - // the time)? Or maybe provide a command line option? - // We can reasonably assume reflect cannot have global or absolute scope // variable overrides so we don't need to pass them to context. + + // Merge variable overrides (note that the order is important). // + strings* cmd_vars; + { + strings& v1 (build2_cmd_vars); + strings& v2 (config_vars_); + + cmd_vars = (v2.empty () ? &v1 : v1.empty () ? &v2 : nullptr); + + if (cmd_vars == nullptr) + { + if (cmd_vars_.empty ()) // Cached. + { + cmd_vars_.reserve (v1.size () + v2.size ()); + cmd_vars_.assign (v1.begin (), v1.end ()); + cmd_vars_.insert (cmd_vars_.end (), v2.begin (), v2.end ()); + } + + cmd_vars = &cmd_vars_; + } + } ctx_.reset ( new context (build2_sched, @@ -745,7 +756,7 @@ namespace bpkg false /* no_external_modules */, false /* dry_run */, // Shouldn't matter. false /* keep_going */, // Shouldnt' matter. - config_vars_)); + *cmd_vars)); context& ctx (*ctx_); diff --git a/bpkg/package-skeleton.hxx b/bpkg/package-skeleton.hxx index c4c59cc..0b573e4 100644 --- a/bpkg/package-skeleton.hxx +++ b/bpkg/package-skeleton.hxx @@ -100,6 +100,7 @@ namespace bpkg bool created_ = false; unique_ptr ctx_; build2::scope* rs_ = nullptr; + strings cmd_vars_; // Storage for merged build2_cmd_vars and config_vars_. strings reflect_names_; // Reflect configuration variable names. strings reflect_vars_; // Reflect configuration variable overrides. -- cgit v1.1