aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/config/init.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/config/init.cxx')
-rw-r--r--libbuild2/config/init.cxx159
1 files changed, 159 insertions, 0 deletions
diff --git a/libbuild2/config/init.cxx b/libbuild2/config/init.cxx
new file mode 100644
index 0000000..73275c6
--- /dev/null
+++ b/libbuild2/config/init.cxx
@@ -0,0 +1,159 @@
+// file : libbuild2/config/init.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <libbuild2/config/init.hxx>
+
+#include <libbuild2/file.hxx>
+#include <libbuild2/rule.hxx>
+#include <libbuild2/scope.hxx>
+#include <libbuild2/context.hxx>
+#include <libbuild2/filesystem.hxx> // exists()
+#include <libbuild2/diagnostics.hxx>
+
+#include <libbuild2/config/module.hxx>
+#include <libbuild2/config/utility.hxx>
+#include <libbuild2/config/operation.hxx>
+
+using namespace std;
+using namespace butl;
+
+namespace build2
+{
+ namespace config
+ {
+ bool
+ boot (scope& rs, const location&, unique_ptr<module_base>& mod)
+ {
+ tracer trace ("config::boot");
+
+ l5 ([&]{trace << "for " << rs;});
+
+ const string& mname (current_mname);
+ const string& oname (current_oname);
+
+ // Only create the module if we are configuring or creating. This is a
+ // bit tricky since the build2 core may not yet know if this is the
+ // case. But we know.
+ //
+ if (( mname == "configure" || mname == "create") ||
+ (mname.empty () && (oname == "configure" || oname == "create")))
+ {
+ unique_ptr<module> m (new module);
+
+ // Adjust priority for the import pseudo-module so that
+ // config.import.* values come first in config.build.
+ //
+ m->save_module ("import", INT32_MIN);
+
+ mod = move (m);
+ }
+
+ // Register meta-operations. Note that we don't register create_id
+ // since it will be pre-processed into configure.
+ //
+ rs.insert_meta_operation (configure_id, mo_configure);
+ rs.insert_meta_operation (disfigure_id, mo_disfigure);
+
+ return true; // Initialize first (load config.build).
+ }
+
+ bool
+ init (scope& rs,
+ scope&,
+ const location& l,
+ unique_ptr<module_base>&,
+ bool first,
+ bool,
+ const variable_map& config_hints)
+ {
+ tracer trace ("config::init");
+
+ if (!first)
+ {
+ warn (l) << "multiple config module initializations";
+ return true;
+ }
+
+ const dir_path& out_root (rs.out_path ());
+ l5 ([&]{trace << "for " << out_root;});
+
+ assert (config_hints.empty ()); // We don't known any hints.
+
+ auto& vp (var_pool.rw (rs));
+
+ // Load config.build if one exists (we don't need to worry about
+ // disfigure since we will never be init'ed).
+ //
+ const variable& c_v (vp.insert<uint64_t> ("config.version", false));
+
+ {
+ path f (config_file (rs));
+
+ if (exists (f))
+ {
+ // Check the config version. We assume that old versions cannot
+ // understand new configs and new versions are incompatible with old
+ // configs.
+ //
+ // We extract the value manually instead of loading and then
+ // checking in order to be able to fixup/migrate the file which we
+ // may want to do in the future.
+ //
+ {
+ // Assume missing version is 0.
+ //
+ auto p (extract_variable (f, c_v));
+ uint64_t v (p.second ? cast<uint64_t> (p.first) : 0);
+
+ if (v != module::version)
+ fail (l) << "incompatible config file " << f <<
+ info << "config file version " << v
+ << (p.second ? "" : " (missing)") <<
+ info << "config module version " << module::version <<
+ info << "consider reconfiguring " << project (rs) << '@'
+ << out_root;
+ }
+
+ source (rs, rs, f);
+ }
+ }
+
+ // Register alias and fallback rule for the configure meta-operation.
+ //
+ // We need this rule for out-of-any-project dependencies (e.g.,
+ // libraries imported from /usr/lib). We are registring it on the
+ // global scope similar to builtin rules.
+ //
+ {
+ auto& r (rs.global ().rules);
+ r.insert<mtime_target> (
+ configure_id, 0, "config.file", file_rule::instance);
+ }
+ {
+ auto& r (rs.rules);
+
+ //@@ outer
+ r.insert<alias> (configure_id, 0, "config.alias", alias_rule::instance);
+
+ // This allows a custom configure rule while doing nothing by default.
+ //
+ r.insert<target> (configure_id, 0, "config", noop_rule::instance);
+ r.insert<file> (configure_id, 0, "config.file", noop_rule::instance);
+ }
+
+ return true;
+ }
+
+ module_functions
+ build2_config_load ()
+ {
+ // Initialize the config entry points in the build system core.
+ //
+ config_save_variable = &config::save_variable;
+ config_preprocess_create = &config::preprocess_create;
+
+ return module_functions {&boot, &init};
+ }
+ }
+}