From 1adbf7b710d52958f6c0168ccb492252c1f19d4a Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 13 Mar 2020 08:48:43 +0200 Subject: Cleanup and make config/utility.?xx part of build system core --- libbuild2/config/init.cxx | 3 +- libbuild2/config/module.cxx | 16 ++++ libbuild2/config/module.hxx | 26 ++++-- libbuild2/config/operation.cxx | 4 +- libbuild2/config/utility.cxx | 180 ++--------------------------------------- libbuild2/config/utility.hxx | 106 +++++++++++++++--------- libbuild2/config/utility.txx | 3 - 7 files changed, 111 insertions(+), 227 deletions(-) (limited to 'libbuild2/config') diff --git a/libbuild2/config/init.cxx b/libbuild2/config/init.cxx index 8dd4d8b..ca34d52 100644 --- a/libbuild2/config/init.cxx +++ b/libbuild2/config/init.cxx @@ -300,7 +300,8 @@ namespace build2 { // Initialize the config entry points in the build system core. // - config_save_variable = &save_variable; + config_save_variable = &module::save_variable; + config_save_module = &module::save_module; config_preprocess_create = &preprocess_create; return mod_functions; diff --git a/libbuild2/config/module.cxx b/libbuild2/config/module.cxx index 176eef0..96107cc 100644 --- a/libbuild2/config/module.cxx +++ b/libbuild2/config/module.cxx @@ -3,6 +3,8 @@ #include +#include + using namespace std; namespace build2 @@ -45,12 +47,26 @@ namespace build2 return true; } + void module:: + save_variable (scope& rs, const variable& var, uint64_t flags) + { + if (module* m = rs.find_module (module::name)) + m->save_variable (var, flags); + } + bool module:: save_module (const char* name, int prio) { return saved_modules.insert (string ("config.") += name, prio).second; } + void module:: + save_module (scope& rs, const char* name, int prio) + { + if (module* m = rs.find_module (module::name)) + m->save_module (name, prio); + } + const string module::name ("config"); const uint64_t module::version (1); } diff --git a/libbuild2/config/module.hxx b/libbuild2/config/module.hxx index 28c73a3..ade75cd 100644 --- a/libbuild2/config/module.hxx +++ b/libbuild2/config/module.hxx @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -51,14 +52,6 @@ namespace build2 // Priority order with INT32_MIN being the highest. Modules with the // same priority are saved in the order inserted. // - // Generally, the idea is that we want higher-level modules at the top - // of the file since that's the configuration that we usualy want to - // change. So we have the following priority bands/defaults: - // - // 101-200/150 - code generators (e.g., yacc, bison) - // 201-300/250 - compilers (e.g., C, C++), - // 301-400/350 - binutils (ar, ld) - // std::multimap order; pair @@ -82,9 +75,15 @@ namespace build2 bool save_variable (const variable&, uint64_t flags = 0); + static void + save_variable (scope&, const variable&, uint64_t); + bool save_module (const char* name, int prio = 0); + static void + save_module (scope&, const char*, int); + // Return true if the variable is already saved. // bool @@ -102,6 +101,17 @@ namespace build2 static const string name; static const uint64_t version; }; + + // Implementation-specific utilities. + // + + inline path + config_file (const scope& rs) + { + return (rs.out_path () / + rs.root_extra->build_dir / + "config." + rs.root_extra->build_ext); + } } } diff --git a/libbuild2/config/operation.cxx b/libbuild2/config/operation.cxx index 2138986..07110e0 100644 --- a/libbuild2/config/operation.cxx +++ b/libbuild2/config/operation.cxx @@ -13,7 +13,7 @@ #include #include -#include +#include // save_* using namespace std; using namespace butl; @@ -1224,7 +1224,7 @@ namespace build2 "", /* root_pre */ rmod, "", /* root_post */ - true, /* config */ + "config", /* config */ true, /* buildfile */ "the create meta-operation"); diff --git a/libbuild2/config/utility.cxx b/libbuild2/config/utility.cxx index a39d3e0..b9fc513 100644 --- a/libbuild2/config/utility.cxx +++ b/libbuild2/config/utility.cxx @@ -3,17 +3,17 @@ #include -#include -#include -#include -#include - -#include - using namespace std; namespace build2 { + void (*config_save_variable) (scope&, const variable&, uint64_t); + void (*config_save_module) (scope&, const char*, int); + const string& (*config_preprocess_create) (context&, + values&, + vector_view&, + bool, + const location&); namespace config { pair @@ -126,171 +126,5 @@ namespace build2 else return false; } - - void - save_variable (scope& rs, const variable& var, uint64_t flags) - { - if (module* m = rs.find_module (module::name)) - m->save_variable (var, flags); - } - - void - save_module (scope& rs, const char* name, int prio) - { - if (module* m = rs.find_module (module::name)) - m->save_module (name, prio); - } - - void - create_project (const dir_path& d, - const build2::optional& amal, - const strings& bmod, - const string& rpre, - const strings& rmod, - const string& rpos, - bool config, - bool buildfile, - const char* who, - uint16_t verbosity) - { - string hdr ("# Generated by " + string (who) + ". Edit if you know" - " what you are doing.\n" - "#"); - - // If the directory exists, verify it's empty. Otherwise, create it. - // - if (exists (d)) - { - if (!empty (d)) - fail << "directory " << d << " exists and is not empty"; - } - else - mkdir_p (d, verbosity); - - // Create the build/ subdirectory. - // - // Note that for now we use the standard build file/directory scheme. - // - mkdir (d / std_build_dir, verbosity); - - // Write build/bootstrap.build. - // - { - path f (d / std_bootstrap_file); - - if (verb >= verbosity) - text << (verb >= 2 ? "cat >" : "save ") << f; - - try - { - ofdstream ofs (f); - - ofs << hdr << endl - << "project =" << endl; - - if (amal) - { - ofs << "amalgamation ="; - - if (!amal->empty ()) - { - ofs << ' '; - to_stream (ofs, *amal, true /* representation */); - } - - ofs << endl; - } - - ofs << endl; - - if (config) - ofs << "using config" << endl; - - for (const string& m: bmod) - { - if (!config || m != "config") - ofs << "using " << m << endl; - } - - ofs.close (); - } - catch (const io_error& e) - { - fail << "unable to write to " << f << ": " << e; - } - } - - // Write build/root.build. - // - { - path f (d / std_root_file); - - if (verb >= verbosity) - text << (verb >= 2 ? "cat >" : "save ") << f; - - try - { - ofdstream ofs (f); - - ofs << hdr << endl; - - if (!rpre.empty ()) - ofs << rpre << endl - << endl; - - for (const string& cm: rmod) - { - // If the module name start with '?', then use optional load. - // - bool opt (cm.front () == '?'); - string m (cm, opt ? 1 : 0); - - // Append .config unless the module name ends with '.', in which - // case strip it. - // - if (m.back () == '.') - m.pop_back (); - else - m += ".config"; - - ofs << "using" << (opt ? "?" : "") << " " << m << endl; - } - - if (!rpos.empty ()) - ofs << endl - << rpre << endl; - - ofs.close (); - } - catch (const io_error& e) - { - fail << "unable to write to " << f << ": " << e; - } - } - - // Write root buildfile. - // - if (buildfile) - { - path f (d / std_buildfile_file); - - if (verb >= verbosity) - text << (verb >= 2 ? "cat >" : "save ") << f; - - try - { - ofdstream ofs (f); - - ofs << hdr << endl - << "./: {*/ -build/}" << endl; - - ofs.close (); - } - catch (const io_error& e) - { - fail << "unable to write to " << f << ": " << e; - } - } - } } } diff --git a/libbuild2/config/utility.hxx b/libbuild2/config/utility.hxx index 3e01cd1..493d296 100644 --- a/libbuild2/config/utility.hxx +++ b/libbuild2/config/utility.hxx @@ -10,14 +10,73 @@ #include #include -#include #include namespace build2 { + // Note that the utility functions in this file are part of the build system + // core rather than the config module. They define the basic configuration + // semantics that should be applicable to both transient configurations as + // well as to other implementations of configuration persistence. + // + // The only persistence-specific aspects of this functionality are marking + // of the variables as to be persisted (saved, potentially with flags), + // establishing the module saving order (priority), and configuration + // creation (the create meta-operation implementation) These are accessed + // through the config module entry points (which are NULL for transient + // configurations). Note also that the exact interpretation of the save + // flags and module order depends on the config module implementation (which + // may ignore them as not applicable). An implementation may also define + // custom save flags (for example, accessible through the config.save + // attribute). Such flags should start from 0x100000000. + // + LIBBUILD2_SYMEXPORT extern void + (*config_save_variable) (scope&, const variable&, uint64_t); + + LIBBUILD2_SYMEXPORT extern void + (*config_save_module) (scope&, const char*, int); + + LIBBUILD2_SYMEXPORT extern const string& + (*config_preprocess_create) (context&, + values&, + vector_view&, + bool, + const location&); + namespace config { + // Mark the variable to be saved during configuration. + // + const uint64_t save_default_commented = 0x01; // Based on value::extra. + const uint64_t save_null_omitted = 0x02; // Treat NULL as undefined. + + inline void + save_variable (scope& rs, const variable& var, uint64_t flags = 0) + { + if (config_save_variable != nullptr) + config_save_variable (rs, var, flags); + } + + // Establish module save order/priority with INT32_MIN being the highest. + // Modules with the same priority are saved in the order inserted. + // + // Generally, for user-editable persisten configuration, we want higher- + // level modules at the top of the file since that's the configuration + // that the user usually wants to change. As a result, we define the + // following priority bands/defaults: + // + // 101-200/150 - code generators (e.g., yacc, bison) + // 201-300/250 - compilers (e.g., C, C++), + // 301-400/350 - binutils (ar, ld) + // + inline void + save_module (scope& rs, const char* module, int prio = 0) + { + if (config_save_module != nullptr) + config_save_module (rs, module, prio); + } + // Set, if necessary, a required config.* variable. // // If override is true and the variable doesn't come from this root scope @@ -33,9 +92,12 @@ namespace build2 // (always defined) to pass along its location (could be used to detect // inheritance, etc). // - // Note also that if save_flags has save_commented, then a default value - // is never considered "new" since for such variables absence of a value - // means the default value. + // Note also that if save_flags has save_default_commented, then a default + // value is never considered "new" since for such variables absence of a + // value means the default value. + // + // @@ Should save_null_omitted be interpreted to treat null as undefined? + // Sounds logical. // template pair @@ -139,42 +201,6 @@ namespace build2 // LIBBUILD2_SYMEXPORT bool unconfigured (scope& rs, const string& var, bool value); - - // Enter the variable so that it is saved during configuration. See - // config::module for details. - // - const uint64_t save_default_commented = 0x01; // Based on value::extra. - const uint64_t save_null_omitted = 0x02; // Treat NULL as undefined. - - LIBBUILD2_SYMEXPORT void - save_variable (scope& rs, const variable&, uint64_t flags = 0); - - // Establish module order/priority. See config::module for details. - // - LIBBUILD2_SYMEXPORT void - save_module (scope& rs, const char* module, int prio = 0); - - // Create a project in the specified directory. - // - LIBBUILD2_SYMEXPORT void - create_project (const dir_path& d, - const build2::optional& amalgamation, - const strings& boot_modules, // Bootstrap modules. - const string& root_pre, // Extra root.build text. - const strings& root_modules, // Root modules. - const string& root_post, // Extra root.build text. - bool config, // Load config module. - bool buildfile, // Create root buildfile. - const char* who, // Who is creating it. - uint16_t verbosity = 1); // Diagnostic verbosity. - - inline path - config_file (const scope& rs) - { - return (rs.out_path () / - rs.root_extra->build_dir / - "config." + rs.root_extra->build_ext); - } } } diff --git a/libbuild2/config/utility.txx b/libbuild2/config/utility.txx index 670a701..f52df8d 100644 --- a/libbuild2/config/utility.txx +++ b/libbuild2/config/utility.txx @@ -1,9 +1,6 @@ // file : libbuild2/config/utility.txx -*- C++ -*- // license : MIT; see accompanying LICENSE file -#include -#include // current_mif - namespace build2 { namespace config -- cgit v1.1