aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/config/operation.cxx119
1 files changed, 80 insertions, 39 deletions
diff --git a/build/config/operation.cxx b/build/config/operation.cxx
index f223028..b85a5c7 100644
--- a/build/config/operation.cxx
+++ b/build/config/operation.cxx
@@ -7,6 +7,7 @@
#include <fstream>
#include <build/scope>
+#include <build/file>
#include <build/context>
#include <build/filesystem>
#include <build/diagnostics>
@@ -246,66 +247,106 @@ namespace build
ts.push_back (&root);
}
- static void
- disfigure_execute (action a, const action_targets& ts)
+ static bool
+ disfigure_project (action a, scope& root)
{
- tracer trace ("disfigure_execute");
+ tracer trace ("disfigure_project");
- for (void* v: ts)
- {
- scope& root (*static_cast<scope*> (v));
- const path& out_root (root.path ());
- const path& src_root (root.src_path ());
+ bool m (false); // Keep track of whether we actually did anything.
- bool m (false); // Keep track of whether we actually did anything.
+ const path& out_root (root.path ());
+ const path& src_root (root.src_path ());
- // We distinguish between a complete disfigure and operation-
- // specific.
- //
- if (a.operation () == default_id)
+ // Disfigure subprojects. Since we don't load buildfiles during
+ // disfigure, we do it for all known subprojects.
+ //
+ if (auto v = root.ro_variables ()["subprojects"])
+ {
+ for (const name& n: v.as<const list_value&> ().data)
{
- level4 ([&]{trace << "completely disfiguring " << out_root;});
+ // Create and bootstrap subproject's root scope.
+ //
+ path out_nroot (out_root / n.dir);
+ path src_nroot (src_root / n.dir);
+ scope& nroot (create_root (out_nroot, src_nroot));
- m = rmfile (out_root / config_file) || m;
+ bootstrap_out (nroot);
- if (out_root != src_root)
- {
- m = rmfile (out_root / src_root_file) || m;
+ // Check if the bootstrap process changed src_root.
+ //
+ const path& p (nroot.variables["src_root"].as<const path&> ());
- // Clean up the directories.
- //
- m = rmdir (out_root / bootstrap_dir) || m;
- m = rmdir (out_root / build_dir) || m;
+ if (src_nroot != p)
+ fail << "bootstrapped src_root " << p << " does not match "
+ << "subproject " << src_nroot;
+
+ nroot.src_path_ = &p;
+
+ bootstrap_src (nroot);
+
+ m = disfigure_project (a, nroot) || m;
+ }
+ }
+
+ // We distinguish between a complete disfigure and operation-
+ // specific.
+ //
+ if (a.operation () == default_id)
+ {
+ level4 ([&]{trace << "completely disfiguring " << out_root;});
- switch (rmdir (out_root))
+ m = rmfile (out_root / config_file) || m;
+
+ if (out_root != src_root)
+ {
+ m = rmfile (out_root / src_root_file) || m;
+
+ // Clean up the directories.
+ //
+ m = rmdir (out_root / bootstrap_dir) || m;
+ m = rmdir (out_root / build_dir) || m;
+
+ switch (rmdir (out_root))
+ {
+ case rmdir_status::not_empty:
{
- case rmdir_status::not_empty:
- {
- warn << "directory " << out_root.string () << " is "
- << (out_root == work
- ? "current working directory"
- : "not empty") << ", not removing";
- break;
- }
- case rmdir_status::success:
- m = true;
- default:
+ warn << "directory " << out_root.string () << " is "
+ << (out_root == work
+ ? "current working directory"
+ : "not empty") << ", not removing";
break;
}
+ case rmdir_status::success:
+ m = true;
+ default:
+ break;
}
}
- else
- {
- }
+ }
+ else
+ {
+ }
+
+ return m;
+ }
+
+ static void
+ disfigure_execute (action a, const action_targets& ts)
+ {
+ tracer trace ("disfigure_execute");
+
+ for (void* v: ts)
+ {
+ scope& root (*static_cast<scope*> (v));
- if (!m)
+ if (!disfigure_project (a, root))
{
// Create a dir{$out_root/} target to signify the project's
// root in diagnostics. Not very clean but seems harmless.
//
target& t (
targets.insert (
- dir::static_type, out_root, "", nullptr, trace).first);
+ dir::static_type, root.path (), "", nullptr, trace).first);
info << diag_already_done (a, t);
}