diff options
-rw-r--r-- | build2/b-options.cxx | 3 | ||||
-rw-r--r-- | build2/b.cli | 3 | ||||
-rw-r--r-- | build2/b.cxx | 47 |
3 files changed, 47 insertions, 6 deletions
diff --git a/build2/b-options.cxx b/build2/b-options.cxx index 60eeec6..2bc65b3 100644 --- a/build2/b-options.cxx +++ b/build2/b-options.cxx @@ -1529,7 +1529,8 @@ namespace build2 << ::std::endl << "The default options files for the build system driver are called \033[1mb.options\033[0m and" << ::std::endl << "are searched for in the \033[1m.build2/\033[0m subdirectory of the home directory and in the" << ::std::endl - << "system directory (for example, \033[1m/etc/build2/\033[0m) if configured." << ::std::endl + << "system directory (for example, \033[1m/etc/build2/\033[0m) if configured. Note that besides" << ::std::endl + << "options these files can also contain global variable overrides." << ::std::endl << ::std::endl << "Once the search is complete, the files are loaded in the reverse order, that" << ::std::endl << "is, beginning from the system directory (if any), followed by the home" << ::std::endl diff --git a/build2/b.cli b/build2/b.cli index 7566418..31247f9 100644 --- a/build2/b.cli +++ b/build2/b.cli @@ -659,7 +659,8 @@ namespace build2 The default options files for the build system driver are called \cb{b.options} and are searched for in the \cb{.build2/} subdirectory of the home directory and in the system directory (for example, \cb{/etc/build2/}) - if configured. + if configured. Note that besides options these files can also contain global + variable overrides. Once the search is complete, the files are loaded in the reverse order, that is, beginning from the system directory (if any), followed by the home diff --git a/build2/b.cxx b/build2/b.cxx index 4e9ebf7..66b217d 100644 --- a/build2/b.cxx +++ b/build2/b.cxx @@ -342,7 +342,7 @@ main (int argc, char* argv[]) } // Merge all the individual buildspec arguments into a single string. - // We wse newlines to separate arguments so that line numbers in + // We use newlines to separate arguments so that line numbers in // diagnostics signify argument numbers. Clever, huh? // if (argn != 0) @@ -381,7 +381,9 @@ main (int argc, char* argv[]) if (ops.default_options_specified ()) extra = ops.default_options (); - ops = merge_default_options ( + // Load default options files. + // + default_options<options> def_ops ( load_default_options<options, cl::argv_file_scanner, cl::unknown_mode> ( @@ -400,8 +402,45 @@ main (int argc, char* argv[]) else trace << "loading " << (r ? "remote " : "local ") << f; } - }), - ops); + }, + true /* args */)); + + // Merge the default and command line options. + // + ops = merge_default_options (def_ops, ops); + + // Merge the default and command line global overrides. + // + // Note that the "broken down" variable assignments occupying a single + // line are naturally supported. + // + cmd_vars = + merge_default_arguments ( + def_ops, + cmd_vars, + [] (const default_options_entry<options>& e, const strings&) + { + path_name fn (e.file); + + // Verify that all arguments are global overrides. + // + for (const string& a: e.arguments) + { + size_t p (a.find ('=', 1)); + if (p == string::npos || a[0] != '!') + { + diag_record dr (fail (fn)); + dr << "expected option or global variable override instead " + << "of '" << a << "'"; + + if (p != string::npos) + dr << info << "prefix variable assignment with '!'"; + } + + if (p == 1 || (p == 2 && a[1] == '+')) // '!=' or '!+=' ? + fail (fn) << "missing variable name in '" << a << "'"; + } + }); } catch (const pair<path, system_error>& e) { |