aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-11-30 14:50:05 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-11-30 14:50:05 +0200
commit11dce6c2fa7dc39cd9e40c0fedda3280aa2757ad (patch)
tree7ae301e2e7df6f2679faf9d78622d58ae99c7fd2
parent879b5f52cb86f24352f4ed245fcce5f1ab885f97 (diff)
Implement module sidebuilds cleanup using scope operation callbacks
-rw-r--r--build2/cc/compile.cxx32
-rw-r--r--build2/cc/init.cxx46
-rw-r--r--build2/cc/utility.cxx4
-rw-r--r--build2/cc/utility.hxx3
-rw-r--r--build2/filesystem.txx6
5 files changed, 72 insertions, 19 deletions
diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx
index 0ab9bfc..ca07b42 100644
--- a/build2/cc/compile.cxx
+++ b/build2/cc/compile.cxx
@@ -3711,6 +3711,9 @@ namespace build2
// Use cc.core.vars as a proxy for {c,cxx}.config (a bit smelly).
//
+ // This is also the module that registers the scope operation
+ // callback that cleans up the subproject.
+ //
if (cast_false<bool> ((*s)["cc.core.vars.loaded"]))
as = s;
@@ -3723,11 +3726,7 @@ namespace build2
// So the first step is to check if the project has already been created
// and/or loaded and if not, then to go ahead and do so.
//
- dir_path pd (as->out_path ());
- pd /= "build";
- pd /= "cc";
- pd /= "modules";
- pd /= x;
+ dir_path pd (as->out_path () / modules_sidebuild_dir /= x);
{
const scope* ps (&scopes.find (pd));
@@ -3758,18 +3757,17 @@ namespace build2
extra += string (x) + ".features.modules = true";
- dir_path ad (((dir_path ("..") /= "..") /= "..") /= "..");
-
- config::create_project (pd,
- ad, /* amalgamation */
- {}, /* boot_modules */
- extra, /* root_pre */
- {string (x) + '.'}, /* root_modules */
- "", /* root_post */
- false, /* config */
- false, /* buildfile */
- "the cc module",
- 2); /* verbosity */
+ config::create_project (
+ pd,
+ as->out_path ().relative (pd), /* amalgamation */
+ {}, /* boot_modules */
+ extra, /* root_pre */
+ {string (x) + '.'}, /* root_modules */
+ "", /* root_post */
+ false, /* config */
+ false, /* buildfile */
+ "the cc module",
+ 2); /* verbosity */
}
ps = &load_project (as->rw () /* lock */, pd, pd);
diff --git a/build2/cc/init.cxx b/build2/cc/init.cxx
index 87a7b12..3108d6d 100644
--- a/build2/cc/init.cxx
+++ b/build2/cc/init.cxx
@@ -4,13 +4,16 @@
#include <build2/cc/init.hxx>
+#include <build2/file.hxx>
#include <build2/scope.hxx>
#include <build2/context.hxx>
+#include <build2/filesystem.hxx>
#include <build2/diagnostics.hxx>
#include <build2/config/utility.hxx>
#include <build2/cc/target.hxx>
+#include <build2/cc/utility.hxx>
using namespace std;
using namespace butl;
@@ -19,6 +22,39 @@ namespace build2
{
namespace cc
{
+ // Scope operation callback that cleans up module sidebuilds.
+ //
+ static target_state
+ clean_module_sidebuilds (action, const scope& rs, const dir&)
+ {
+ dir_path d (rs.out_path () / modules_sidebuild_dir);
+
+ if (exists (d))
+ {
+ if (build2::rmdir_r (d))
+ {
+ // Clean up cc/ if it became empty.
+ //
+ d = rs.out_path () / module_dir;
+ if (empty (d))
+ {
+ rmdir (d);
+
+ // And build/ if it also became empty (e.g., in case of a build
+ // with a transient configuration).
+ //
+ d = rs.out_path () / build_dir;
+ if (empty (d))
+ rmdir (d);
+ }
+
+ return target_state::changed;
+ }
+ }
+
+ return target_state::unchanged;
+ }
+
bool
core_vars_init (scope& rs,
scope&,
@@ -88,6 +124,16 @@ namespace build2
v.insert<bool> ("config.cc.reprocess", true);
v.insert<bool> ("cc.reprocess");
+ // Register scope operation callback.
+ //
+ // It feels natural to do clean up sidebuilds as a post operation but
+ // that prevents the (otherwise-empty) out root directory to be cleaned
+ // up (via the standard fsdir{} chain).
+ //
+ rs.operation_callbacks.emplace (
+ perform_clean_id,
+ scope::operation_callback {&clean_module_sidebuilds, nullptr /*post*/});
+
return true;
}
diff --git a/build2/cc/utility.cxx b/build2/cc/utility.cxx
index 7a2b7fe..aa47085 100644
--- a/build2/cc/utility.cxx
+++ b/build2/cc/utility.cxx
@@ -4,6 +4,7 @@
#include <build2/cc/utility.hxx>
+#include <build2/file.hxx>
#include <build2/variable.hxx>
#include <build2/algorithm.hxx> // search()
@@ -17,6 +18,9 @@ namespace build2
{
using namespace bin;
+ const dir_path module_dir (dir_path ("build") /= "cc");
+ const dir_path modules_sidebuild_dir (dir_path (module_dir) /= "modules");
+
lorder
link_order (const scope& bs, otype ot)
{
diff --git a/build2/cc/utility.hxx b/build2/cc/utility.hxx
index 2f6834f..d7d980d 100644
--- a/build2/cc/utility.hxx
+++ b/build2/cc/utility.hxx
@@ -19,6 +19,9 @@ namespace build2
namespace cc
{
+ extern const dir_path module_dir; // build/cc/
+ extern const dir_path modules_sidebuild_dir; // build/cc/modules/
+
// Compile output type.
//
otype
diff --git a/build2/filesystem.txx b/build2/filesystem.txx
index fe56498..8e50592 100644
--- a/build2/filesystem.txx
+++ b/build2/filesystem.txx
@@ -2,6 +2,8 @@
// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
+#include <type_traits> // is_base_of
+
#include <build2/context.hxx> // work
#include <build2/diagnostics.hxx>
@@ -64,9 +66,9 @@ namespace build2
if (verb >= v)
{
if (verb >= 2)
- text << "rm " << d;
+ text << "rmdir " << d;
else if (verb)
- text << "rm " << t;
+ text << (std::is_base_of<dir_path, T>::value ? "rmdir " : "rm ") << t;
}
};