From 074a8c04a384a9752466bd2af69b695333b2955c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 29 Nov 2017 17:44:48 +0200 Subject: Reimplement module sidebuilding using an ad hoc subproject --- build2/config/operation.cxx | 179 ++++++++------------------------------------ build2/config/utility.cxx | 150 +++++++++++++++++++++++++++++++++++++ build2/config/utility.hxx | 16 ++++ 3 files changed, 197 insertions(+), 148 deletions(-) (limited to 'build2/config') diff --git a/build2/config/operation.cxx b/build2/config/operation.cxx index c7cfefd..2fad6b0 100644 --- a/build2/config/operation.cxx +++ b/build2/config/operation.cxx @@ -415,7 +415,7 @@ namespace build2 // disfigure // static void - load_project (scope& root) + bootstrap_project (scope& root) { if (auto l = root.vars[var_subprojects]) { @@ -432,7 +432,7 @@ namespace build2 // The same logic for src_root as in create_bootstrap_inner(). // - scope& nroot (create_root (root, out_nroot, dir_path ())); + scope& nroot (create_root (root, out_nroot, dir_path ())->second); if (!bootstrapped (nroot)) { @@ -447,7 +447,7 @@ namespace build2 bootstrap_src (nroot); } - load_project (nroot); + bootstrap_project (nroot); } } } @@ -476,7 +476,7 @@ namespace build2 // disfigure all the subprojects (see disfigure_project() below), we // bootstrap all known subprojects. // - load_project (root); + bootstrap_project (root); } static void @@ -644,151 +644,18 @@ namespace build2 // create // static void - create_project (const dir_path& d, - const strings& bmod, // Bootstrap modules. - const strings& rmod, // Root modules. - const variable_overrides& var_ovs) + save_config (const dir_path& d, const variable_overrides& var_ovs) { - // If the directory exists, verify it's empty. Otherwise, create it. + // Since there aren't any sub-projects yet, any config.import.* values + // that the user may want to specify won't be saved in config.build. So + // let's go ahead and mark them all to be saved. To do this, however, we + // need the config module (which is where this information is stored). + // And the module is created by init() during bootstrap. So what we are + // going to do is bootstrap the newly created project, similar to the + // way main() does it. // - if (exists (d)) - { - if (!empty (d)) - fail << "directory " << d << " exists and is not empty"; - } - else - mkdir_p (d); - - // Create the build/ subdirectory. - // - mkdir (d / build_dir); - - // Write build/bootstrap.build. - // - { - path f (d / bootstrap_file); - - if (verb) - text << (verb >= 2 ? "cat >" : "save ") << f; - - try - { - ofdstream ofs (f); - - // For now we disable amalgamating this project. Sooner or later - // someone will probably want to do this, though (i.e., nested - // configurations). - // - ofs << "# Generated by the create meta-operation. Edit if you " << - "know what you are doing." << endl - << "#" << endl - << "project =" << endl - << "amalgamation =" << endl - << endl - << "using config" << endl; - - for (const string& m: bmod) - { - if (m != "config") - ofs << "using " << m << endl; - } - - ofs.close (); - } - catch (const io_error& e) - { - fail << "unable to write " << f << ": " << e; - } - } - - // Write build/root.build. - // - { - path f (d / root_file); - - if (verb) - text << (verb >= 2 ? "cat >" : "save ") << f; - - try - { - ofdstream ofs (f); - - ofs << "# Generated by the create meta-operation. Edit if you " << - "know what you are doing." << 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; - } - - ofs.close (); - } - catch (const io_error& e) - { - fail << "unable to write " << f << ": " << e; - } - } - - // Write root buildfile. - // - { - path f (d / "buildfile"); - - if (verb) - text << (verb >= 2 ? "cat >" : "save ") << f; - - try - { - ofdstream ofs (f); - - ofs << "# Generated by the create meta-operation. Edit if you " << - "know what you are doing." << endl - << "#" << endl - << "./: {*/ -build/}" << endl; - - ofs.close (); - } - catch (const io_error& e) - { - fail << "unable to write " << f << ": " << e; - } - } - - // Well, this wasn't too bad. There is just one little snag: since there - // aren't any sub-projects yet, any config.import.* values that the user - // may want to specify won't be saved in config.build. So let's go ahead - // and mark them all to be saved. To do this, however, we need the - // config module (which is where this information is stored). And the - // module is created by init() during bootstrap. So what we are going to - // do is bootstrap the newly created project, similar to the way main() - // does it (except here we can omit all the guessing/sanity checks). - // - current_oname = &empty_string; // Make sure valid. - scope& gs (*scope::global_); - scope& rs (create_root (gs, d, d)); - - if (!bootstrapped (rs)) - { - bootstrap_out (rs); - setup_root (rs); - bootstrap_src (rs); - } - + scope& rs (load_project (gs, d, d, false /* load */)); module& m (*rs.modules.lookup (module::name)); // Save all the global config.import.* variables. @@ -834,7 +701,7 @@ namespace build2 bool lifted, const location& l) { - tracer trace ("create_project"); + tracer trace ("preprocess_create"); // The overall plan is to create the project(s), update the buildspec, // clear the parameters, and then continue as if we were the configure @@ -865,6 +732,8 @@ namespace build2 fail (l) << "invalid module name: " << e.what (); } + current_oname = &empty_string; // Make sure valid. + // Now handle each target in each operation spec. // for (const opspec& os: spec) @@ -919,7 +788,21 @@ namespace build2 l5 ([&]{trace << "creating project in " << d;}); - create_project (d, bmod, rmod, var_ovs); + // For now we disable amalgamating this project. Sooner or later + // someone will probably want to do this, though (i.e., nested + // configurations). + // + create_project (d, + dir_path (), /* amalgamation */ + bmod, + "", /* root_pre */ + rmod, + "", /* root_post */ + true, /* config */ + true, /* buildfile */ + "the create meta-operation"); + + save_config (d, var_ovs); } } diff --git a/build2/config/utility.cxx b/build2/config/utility.cxx index c195e0b..1c80d13 100644 --- a/build2/config/utility.cxx +++ b/build2/config/utility.cxx @@ -4,7 +4,10 @@ #include +#include #include +#include +#include #include @@ -151,5 +154,152 @@ namespace build2 if (module* m = r.modules.lookup (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. + // + mkdir (d / build_dir, verbosity); + + // Write build/bootstrap.build. + // + { + path f (d / 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 << ' ' << amal->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 " << f << ": " << e; + } + } + + // Write build/root.build. + // + { + path f (d / 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 " << f << ": " << e; + } + } + + // Write root buildfile. + // + if (buildfile) + { + path f (d / "buildfile"); + + 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 " << f << ": " << e; + } + } + } } } diff --git a/build2/config/utility.hxx b/build2/config/utility.hxx index 33a3985..c09dc07 100644 --- a/build2/config/utility.hxx +++ b/build2/config/utility.hxx @@ -92,6 +92,8 @@ namespace build2 // // Return the value (as always defined lookup), which can be NULL. // + // @@ Rename since clashes with the optional class template. + // lookup optional (scope& root, const variable&); @@ -144,6 +146,20 @@ namespace build2 // void save_module (scope& root, const char* name, int prio = 0); + + // Create a project in the specified directory. + // + 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. } } -- cgit v1.1