diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2017-11-30 14:50:05 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2017-11-30 14:50:05 +0200 |
commit | 11dce6c2fa7dc39cd9e40c0fedda3280aa2757ad (patch) | |
tree | 7ae301e2e7df6f2679faf9d78622d58ae99c7fd2 | |
parent | 879b5f52cb86f24352f4ed245fcce5f1ab885f97 (diff) |
Implement module sidebuilds cleanup using scope operation callbacks
-rw-r--r-- | build2/cc/compile.cxx | 32 | ||||
-rw-r--r-- | build2/cc/init.cxx | 46 | ||||
-rw-r--r-- | build2/cc/utility.cxx | 4 | ||||
-rw-r--r-- | build2/cc/utility.hxx | 3 | ||||
-rw-r--r-- | build2/filesystem.txx | 6 |
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; } }; |