diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2020-04-08 13:44:33 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2020-04-08 13:44:33 +0200 |
commit | cea5dd6f96f2c06467264644f800619e9d24564d (patch) | |
tree | 1cbc193b5c2d4e18c6ef91952cdf4fe36f8f6264 | |
parent | 7ef1fb36f19adc7e31939fcfd874b6ad4b6d25c1 (diff) |
Allow configuration variables in unnamed projects
While generally a bad idea, there are valid situations where this may happen,
such as a standalone build of the tests subproject in test-installed.
-rw-r--r-- | libbuild2/file.cxx | 17 | ||||
-rw-r--r-- | libbuild2/parser.cxx | 36 |
2 files changed, 40 insertions, 13 deletions
diff --git a/libbuild2/file.cxx b/libbuild2/file.cxx index 3e6282c..cbad9ec 100644 --- a/libbuild2/file.cxx +++ b/libbuild2/file.cxx @@ -1305,7 +1305,7 @@ namespace build2 // if (!p.config_report.empty () && verb >= (p.config_report_new ? 2 : 3)) { - const project_name& proj (named_project (root)); // Must be there. + const project_name& proj (named_project (root)); // Can be empty. // @@ TODO/MAYBE: // @@ -1323,7 +1323,14 @@ namespace build2 // the repetitive config.<project>. So we are only going to print the // part after <project> (see parser::parse_config() for details). // - string stem ('.' + proj.variable () + '.'); + // But if there is no named project, then we print everything after + // config. This feels right since there could be zero identifiable + // information about the project in the header line. For example: + // + // config @/tmp/tests + // libhello.tests.remote true + // + string stem (!proj.empty () ? '.' + proj.variable () + '.' : string ()); names storage; for (const pair<lookup, string>& lf: p.config_report) @@ -1342,8 +1349,10 @@ namespace build2 } else { - size_t p (l.var->name.find (stem)); // Must be there. - n = string (l.var->name, p + stem.size ()); + size_t p (!stem.empty () + ? l.var->name.find (stem) + stem.size () + : 7); // "config." + n = string (l.var->name, p); } dr << "\n "; diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx index 797a484..e86212c 100644 --- a/libbuild2/parser.cxx +++ b/libbuild2/parser.cxx @@ -1690,14 +1690,29 @@ namespace build2 // the config[.**].<project>.** pattern where <project> is the innermost // named project. // + // Note that we currently don't allow just the config.<project> name even + // though this is used quite liberally in build system modules. Allowing + // this will complicate the logic (and documentation) a bit and there are + // no obvious use-cases. On the other hand, for tools that could be used + // during the build (say yacc), such a variable would most likely be used + // to specify its location (say config.yacc) . So let's "reserve" it for + // now. + // + // What should we do if there is no named project? We used to fail but + // there are valid cases where this can happen, for example, a standalone + // build of an unnamed tests subproject in order to test an installed + // library. Doing anything fuzzy like requiring at least a four-component + // name in this case is probably not worth the trouble: it's possible the + // subproject needs some configuration values from it amalgamation (in + // which case it will be duplicating them in its root.build file). So + // for now we allow this trusting the user knows what they are doing. + // string proj; { const project_name& n (named_project (*root_)); - if (n.empty ()) - fail (t) << "configuration variable in unnamed project"; - - proj = n.variable (); + if (!n.empty ()) + proj = n.variable (); } // We are now in the normal lexing mode. Since we always have <var> we @@ -1806,13 +1821,16 @@ namespace build2 dr << fail (t) << "configuration variable '" << name << "' does not start with 'config.'"; - if (name.find ('.' + proj + '.') == string::npos) - dr << fail (t) << "configuration variable '" << name - << "' does not include project name"; + if (!proj.empty ()) + { + if (name.find ('.' + proj + '.') == string::npos) + dr << fail (t) << "configuration variable '" << name + << "' does not include project name"; + } if (!dr.empty ()) - dr << info << "expected variable name in the 'config[.**]." << proj - << ".**' form"; + dr << info << "expected variable name in the 'config[.**]." + << (proj.empty () ? "<project>" : proj.c_str ()) << ".**' form"; } const variable& var ( |