diff options
Diffstat (limited to 'libbuild2/config')
-rw-r--r-- | libbuild2/config/functions.cxx | 2 | ||||
-rw-r--r-- | libbuild2/config/host-config.cxx.in | 3 | ||||
-rw-r--r-- | libbuild2/config/init.cxx | 53 | ||||
-rw-r--r-- | libbuild2/config/module.hxx | 2 | ||||
-rw-r--r-- | libbuild2/config/operation.cxx | 77 | ||||
-rw-r--r-- | libbuild2/config/operation.hxx | 6 |
6 files changed, 108 insertions, 35 deletions
diff --git a/libbuild2/config/functions.cxx b/libbuild2/config/functions.cxx index 84c1b03..b1a61a2 100644 --- a/libbuild2/config/functions.cxx +++ b/libbuild2/config/functions.cxx @@ -95,7 +95,7 @@ namespace build2 // See save_config() for details. // assert (s->ctx.phase == run_phase::load); - module* mod (s->rw ().find_module<module> (module::name)); + const module* mod (s->find_module<module> (module::name)); if (mod == nullptr) fail << "config.save() called without config module"; diff --git a/libbuild2/config/host-config.cxx.in b/libbuild2/config/host-config.cxx.in index 9e3e0c2..6b1ce77 100644 --- a/libbuild2/config/host-config.cxx.in +++ b/libbuild2/config/host-config.cxx.in @@ -9,5 +9,8 @@ namespace build2 // extern const char host_config[] = R"###($host_config$)###"; extern const char build2_config[] = R"###($build2_config$)###"; + + extern const char host_config_no_warnings[] = R"###($host_config_no_warnings$)###"; + extern const char build2_config_no_warnings[] = R"###($build2_config_no_warnings$)###"; } } diff --git a/libbuild2/config/init.cxx b/libbuild2/config/init.cxx index 7035ce5..2f134c4 100644 --- a/libbuild2/config/init.cxx +++ b/libbuild2/config/init.cxx @@ -26,6 +26,8 @@ namespace build2 { namespace config { + static const file_rule file_rule_ (true /* check_type */); + void functions (function_map&); // functions.cxx @@ -39,7 +41,7 @@ namespace build2 save_environment (const value& d, const value* b, names& storage) { if (b == nullptr) - return make_pair (reverse (d, storage), "="); + return make_pair (reverse (d, storage, true /* reduce */), "="); // The plan is to iterator over environment variables adding those that // are not in base to storage. There is, however, a complication: we may @@ -208,6 +210,9 @@ namespace build2 #ifndef BUILD2_BOOTSTRAP extern const char host_config[]; extern const char build2_config[]; + + extern const char host_config_no_warnings[]; + extern const char build2_config_no_warnings[]; #endif bool @@ -429,8 +434,15 @@ namespace build2 auto load_config_file = [&load_config] (const path& f, const location& l) { path_name fn (f); - ifdstream ifs; - load_config (open_file_or_stdin (fn, ifs), fn, l); + try + { + ifdstream ifs; + load_config (open_file_or_stdin (fn, ifs), fn, l); + } + catch (const io_error& e) + { + fail << "unable to read buildfile " << fn << ": " << e; + } }; // Load config.build unless requested not to. @@ -475,14 +487,23 @@ namespace build2 const string& s (f.string ()); - if (s[0] != '~') + if (s.empty ()) + fail << "empty path in config.config.load"; + else if (s[0] != '~') load_config_file (f, l); - else if (s == "~host" || s == "~build2") + else if (s == "~host" || s == "~host-no-warnings" || + s == "~build2" || s == "~build2-no-warnings") { #ifdef BUILD2_BOOTSTRAP assert (false); #else - istringstream is (s[1] == 'h' ? host_config : build2_config); + istringstream is (s[1] == 'h' + ? (s.size () == 5 + ? host_config + : host_config_no_warnings) + : (s.size () == 7 + ? build2_config + : build2_config_no_warnings)); load_config (is, path_name (s), l); #endif } @@ -705,21 +726,23 @@ namespace build2 // Register alias and fallback rule for the configure meta-operation. // + rs.insert_rule<alias> (configure_id, 0, "config.alias", alias_rule::instance); + + // This allows a custom configure rule while doing nothing by default. + // + rs.insert_rule<target> (configure_id, 0, "config.noop", noop_rule::instance); + // We need this rule for out-of-any-project dependencies (for example, // libraries imported from /usr/lib). We are registering it on the // global scope similar to builtin rules. // - // See a similar rule in the dist module. + // Note: use target instead of anything more specific (such as + // mtime_target) in order not to take precedence over the rules above. // - rs.global_scope ().insert_rule<mtime_target> ( - configure_id, 0, "config.file", file_rule::instance); - - rs.insert_rule<alias> (configure_id, 0, "config.alias", alias_rule::instance); - - // This allows a custom configure rule while doing nothing by default. + // See a similar rule in the dist module. // - rs.insert_rule<target> (configure_id, 0, "config.noop", noop_rule::instance); - rs.insert_rule<file> (configure_id, 0, "config.noop", noop_rule::instance); + rs.global_scope ().insert_rule<target> ( + configure_id, 0, "config.file", file_rule_); return true; } diff --git a/libbuild2/config/module.hxx b/libbuild2/config/module.hxx index 82b79be..8d3ff67 100644 --- a/libbuild2/config/module.hxx +++ b/libbuild2/config/module.hxx @@ -160,7 +160,7 @@ namespace build2 save_module (scope&, const char*, int); const saved_variable* - find_variable (const variable& var) + find_variable (const variable& var) const { auto i (saved_modules.find_sup (var.name)); if (i != saved_modules.end ()) diff --git a/libbuild2/config/operation.cxx b/libbuild2/config/operation.cxx index 34ed402..150bf1a 100644 --- a/libbuild2/config/operation.cxx +++ b/libbuild2/config/operation.cxx @@ -134,7 +134,8 @@ namespace build2 bool r; if (c.compare (p, 4 , "save") == 0) r = true; else if (c.compare (p, 4 , "drop") == 0) r = false; - else fail << "invalid config.config.persist action '" << c << "'"; + else fail << "invalid config.config.persist action '" << c << "'" + << endf; bool w (false); if ((p += 4) != c.size ()) @@ -163,11 +164,18 @@ namespace build2 // and this function can be called from a buildfile (probably only // during serial execution but still). // + // We could also be configuring multiple projects (including from + // pkg_configure() in bpkg) but feels like we should be ok since we + // only modify this project's root scope data which should not affect + // any other project. + // + // See also save_environment() for a similar issue. + // void save_config (const scope& rs, ostream& os, const path_name& on, bool inherit, - module& mod, + const module& mod, const project_set& projects) { context& ctx (rs.ctx); @@ -181,7 +189,7 @@ namespace build2 if (v) { storage.clear (); - dr << "'" << reverse (v, storage) << "'"; + dr << "'" << reverse (v, storage, true /* reduce */) << "'"; } else dr << "[null]"; @@ -251,6 +259,24 @@ namespace build2 continue; } + // A common reason behind an unused config.import.* value is an + // unused dependency. That is, there is depends in manifest but no + // import in buildfile (or import could be conditional in which case + // depends should also be conditional). So let's suggest this + // possibility. Note that the project name may have been sanitized + // to a variable name. Oh, well, better than nothing. + // + auto info_import = [] (diag_record& dr, const string& var) + { + if (var.compare (0, 14, "config.import.") == 0) + { + size_t p (var.find ('.', 14)); + + dr << info << "potentially unused dependency on " + << string (var, 14, p == string::npos ? p : p - 14); + } + }; + const value& v (p.first->second); pair<bool, bool> r (save_config_variable (*var, @@ -259,7 +285,7 @@ namespace build2 true /* unused */)); if (r.first) // save { - mod.save_variable (*var, 0); + const_cast<module&> (mod).save_variable (*var, 0); if (r.second) // warn { @@ -278,6 +304,7 @@ namespace build2 diag_record dr; dr << warn (on) << "saving no longer used variable " << *var; + info_import (dr, var->name); if (verb >= 2) info_value (dr, v); } @@ -288,6 +315,7 @@ namespace build2 { diag_record dr; dr << warn (on) << "dropping no longer used variable " << *var; + info_import (dr, var->name); info_value (dr, v); } } @@ -531,7 +559,7 @@ namespace build2 pair<names_view, const char*> p ( sv.save != nullptr ? sv.save (v, base, storage) - : make_pair (reverse (v, storage), "=")); + : make_pair (reverse (v, storage, true /* reduce */), "=")); // Might becomes empty after a custom save function had at it. // @@ -560,7 +588,7 @@ namespace build2 save_config (const scope& rs, const path& f, bool inherit, - module& mod, + const module& mod, const project_set& projects) { path_name fn (f); @@ -588,6 +616,9 @@ namespace build2 // Update config.config.environment value for a hermetic configuration. // + // @@ We are modifying the module. See also save_config() for a similar + // issue. + // static void save_environment (scope& rs, module& mod) { @@ -660,9 +691,9 @@ namespace build2 static void configure_project (action a, - scope& rs, + const scope& rs, const variable* c_s, // config.config.save - module& mod, + const module& mod, project_set& projects) { tracer trace ("configure_project"); @@ -696,7 +727,7 @@ namespace build2 // for the other half of this logic). // if (cast_false<bool> (rs["config.config.hermetic"])) - save_environment (rs, mod); + save_environment (const_cast<scope&> (rs), const_cast<module&> (mod)); // Save src-root.build unless out_root is the same as src. // @@ -728,6 +759,11 @@ namespace build2 lookup l (rs[*c_s]); if (l && (l.belongs (rs) || l.belongs (ctx.global_scope))) { + const path& f (cast<path> (l)); + + if (f.empty ()) + fail << "empty path in " << *c_s; + // While writing the complete configuration seems like a natural // default, there might be a desire to take inheritance into // account (if, say, we are exporting at multiple levels). One can @@ -735,8 +771,7 @@ namespace build2 // still want to support this mode somehow in the future (it seems // like an override of config.config.persist should do the trick). // - save_config ( - rs, cast<path> (l), false /* inherit */, mod, projects); + save_config (rs, f, false /* inherit */, mod, projects); } } } @@ -759,14 +794,14 @@ namespace build2 { const dir_path& pd (p.second); dir_path out_nroot (out_root / pd); - scope& nrs (ctx.scopes.find_out (out_nroot).rw ()); + const scope& nrs (ctx.scopes.find_out (out_nroot)); // Skip this subproject if it is not loaded or doesn't use the // config module. // if (nrs.out_path () == out_nroot) { - if (module* m = nrs.find_module<module> (module::name)) + if (const module* m = nrs.find_module<module> (module::name)) { configure_project (a, nrs, c_s, *m, projects); } @@ -819,6 +854,8 @@ namespace build2 // Don't translate default to update. In our case unspecified // means configure everything. // + // Note: see pkg_configure() in bpkg if changing anything here. + // return o; } @@ -855,6 +892,8 @@ namespace build2 static void configure_pre (context&, const values& params, const location& l) { + // Note: see pkg_configure() in bpkg if changing anything here. + // forward (params, "configure", l); // Validate. } @@ -976,20 +1015,28 @@ namespace build2 ctx.current_operation (*oif); + if (oif->operation_pre != nullptr) + oif->operation_pre (ctx, {}, true /* inner */, location ()); + phase_lock pl (ctx, run_phase::match); match_sync (action (configure_id, id), t); + + if (oif->operation_post != nullptr) + oif->operation_post (ctx, {}, true /* inner */); } } configure_project (a, - rs->rw (), + *rs, c_s, - *rs->rw ().find_module<module> (module::name), + *rs->find_module<module> (module::name), projects); } } } + // NOTE: see pkg_configure() in bpkg if changing anything here. + // const meta_operation_info mo_configure { configure_id, "configure", diff --git a/libbuild2/config/operation.hxx b/libbuild2/config/operation.hxx index 9e2a91e..1662941 100644 --- a/libbuild2/config/operation.hxx +++ b/libbuild2/config/operation.hxx @@ -15,8 +15,8 @@ namespace build2 { class module; - extern const meta_operation_info mo_configure; - extern const meta_operation_info mo_disfigure; + LIBBUILD2_SYMEXPORT extern const meta_operation_info mo_configure; + LIBBUILD2_SYMEXPORT extern const meta_operation_info mo_disfigure; const string& preprocess_create (context&, @@ -37,7 +37,7 @@ namespace build2 save_config (const scope& rs, ostream&, const path_name&, bool inherit, - module&, + const module&, const project_set&); // See config.config.hermetic.environment. |