From 11dce6c2fa7dc39cd9e40c0fedda3280aa2757ad Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 30 Nov 2017 14:50:05 +0200 Subject: Implement module sidebuilds cleanup using scope operation callbacks --- build2/cc/compile.cxx | 32 +++++++++++++++----------------- build2/cc/init.cxx | 46 ++++++++++++++++++++++++++++++++++++++++++++++ build2/cc/utility.cxx | 4 ++++ build2/cc/utility.hxx | 3 +++ 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 ((*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 +#include #include #include +#include #include #include #include +#include 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 ("config.cc.reprocess", true); v.insert ("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 +#include #include #include // 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 // is_base_of + #include // work #include @@ -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::value ? "rmdir " : "rm ") << t; } }; -- cgit v1.1