aboutsummaryrefslogtreecommitdiff
path: root/build2/config
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-11-29 17:44:48 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-11-29 17:44:48 +0200
commit074a8c04a384a9752466bd2af69b695333b2955c (patch)
tree707454105647db7886268551ffc661a359e4637c /build2/config
parentf588f2e5a62d7621d20b2a567b8835bb87ff31f4 (diff)
Reimplement module sidebuilding using an ad hoc subproject
Diffstat (limited to 'build2/config')
-rw-r--r--build2/config/operation.cxx179
-rw-r--r--build2/config/utility.cxx150
-rw-r--r--build2/config/utility.hxx16
3 files changed, 197 insertions, 148 deletions
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> (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 <build2/config/utility.hxx>
+#include <build2/file.hxx>
#include <build2/context.hxx>
+#include <build2/filesystem.hxx>
+#include <build2/diagnostics.hxx>
#include <build2/config/module.hxx>
@@ -151,5 +154,152 @@ namespace build2
if (module* m = r.modules.lookup<module> (module::name))
m->save_module (name, prio);
}
+
+ void
+ create_project (const dir_path& d,
+ const build2::optional<dir_path>& 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<dir_path>& 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.
}
}