diff options
Diffstat (limited to 'build/config')
-rw-r--r-- | build/config/module.cxx | 10 | ||||
-rw-r--r-- | build/config/operation.cxx | 166 |
2 files changed, 163 insertions, 13 deletions
diff --git a/build/config/module.cxx b/build/config/module.cxx index dca6ede..41c2526 100644 --- a/build/config/module.cxx +++ b/build/config/module.cxx @@ -28,15 +28,17 @@ namespace build void init (scope& root, scope& base, const location& l) { - tracer trace ("config::init"); - //@@ TODO: avoid multiple inits (generally, for modules). // - level4 ([&]{trace << "for " << root.path () << '/';}); + + tracer trace ("config::init"); if (&root != &base) fail (l) << "config module must be initialized in project root scope"; + const path& out_root (root.path ()); + level4 ([&]{trace << "for " << out_root << '/';}); + // Register meta-operations. // if (root.meta_operations.insert (configure) != configure_id || @@ -45,7 +47,7 @@ namespace build // Register the build/config.build sourcing trigger. // - root.triggers[path ("build/config.build")] = &trigger; + root.triggers[out_root / path ("build/config.build")] = &trigger; } } } diff --git a/build/config/operation.cxx b/build/config/operation.cxx index 1411ce4..df4682e 100644 --- a/build/config/operation.cxx +++ b/build/config/operation.cxx @@ -4,6 +4,11 @@ #include <build/config/operation> +#include <fstream> + +#include <build/scope> +#include <build/context> +#include <build/filesystem> #include <build/diagnostics> using namespace std; @@ -12,14 +17,114 @@ namespace build { namespace config { - meta_operation_info configure {"configure"}; + static const path build_dir ("build"); + static const path bootstrap_dir ("build/bootstrap"); + + static const path config_file ("build/config.build"); + static const path src_root_file ("build/bootstrap/src-root.build"); + + // configure + // + static operation_id + configure_operation_pre (operation_id o) + { + // Don't translate default to update. In our case unspecified + // means configure everything. + // + return o; + } + + static void + save_src_root (const path& out_root, const path& src_root) + { + path f (out_root / src_root_file); + + if (verb >= 1) + text << "config::save_src_root " << f.string (); + else + text << "save " << f; + + try + { + ofstream ofs (f.string ()); + if (!ofs.is_open ()) + fail << "unable to open " << f; + + ofs.exceptions (ofstream::failbit | ofstream::badbit); + + //@@ TODO: quote path + // + ofs << "# Created automatically by the config module." << endl + << "#" << endl + << "src_root = " << src_root.string () << '/' << endl; + } + catch (const ios_base::failure&) + { + fail << "failed to write to " << f; + } + } + + static void + configure_execute (action a, const action_targets& ts) + { + tracer trace ("configure_execute"); + + for (void* v: ts) + { + target& t (*static_cast<target*> (v)); + scope& s (scopes.find (t.dir)); + + const path& out_root (s["out_root"].as<const path&> ()); + const path& src_root (s["src_root"].as<const path&> ()); + + // Make sure the directories exist. + // + if (out_root != src_root) + { + mkdir (out_root); + mkdir (out_root / build_dir); + } + + mkdir (out_root / bootstrap_dir); + + // We distinguish between a complete configure and operation- + // specific. + // + if (a.operation () == default_id) + { + level4 ([&]{trace << "completely configuring " << out_root;}); + + // Save src-root.build unless out_root is the same as src. + // + if (out_root != src_root) + save_src_root (out_root, src_root); + } + else + { + } + } + } + + meta_operation_info configure { + "configure", + nullptr, // meta-operation pre + &configure_operation_pre, + &load, // normal load + &match, // normal match + &configure_execute, + nullptr, // operation post + nullptr // meta-operation post + }; // disfigure // static operation_id disfigure_operation_pre (operation_id o) { - return o; // Don't translate default to update. + // Don't translate default to update. In our case unspecified + // means disfigure everything. + // + return o; } static void @@ -30,32 +135,75 @@ namespace build const location&) { tracer trace ("disfigure_load"); - level4 ([&]{trace << "skipping " << bf;}); + level5 ([&]{trace << "skipping " << bf;}); } static void disfigure_match (action a, + scope& root, const target_key& tk, const location& l, action_targets& ts) { tracer trace ("disfigure_match"); - //level4 ([&]{trace << "matching " << t;}); - //ts.push_back (&t); + level5 ([&]{trace << "collecting " << root.path ();}); + ts.push_back (&root); } static void disfigure_execute (action a, const action_targets& ts) { - tracer trace ("execute"); - + tracer trace ("disfigure_execute"); for (void* v: ts) { - //level4 ([&]{trace << "disfiguring target " << t;}); + scope& root (*static_cast<scope*> (v)); + 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) + { + level4 ([&]{trace << "completely disfiguring " << out_root;}); + + rmfile (out_root / config_file); + rmfile (out_root / src_root_file); + + // Clean up the directories. + // + rmdir (out_root / bootstrap_dir); + + if (out_root != src_root) + { + rmdir (out_root / build_dir); + + if (rmdir (out_root) == rmdir_status::not_empty) + warn << "directory " << out_root.string () << " is " + << (out_root == work + ? "current working directory" + : "not empty") << ", not removing"; + } + } + else + { + } } } + static void + disfigure_meta_operation_post () + { + tracer trace ("disfigure_meta_operation_post"); + + // Reset the dependency state since anything that could have been + // loaded earlier using a previous configuration is now invalid. + // + level5 ([&]{trace << "resetting dependency state";}); + reset (); + } + meta_operation_info disfigure { "disfigure", nullptr, // meta-operation pre @@ -64,7 +212,7 @@ namespace build &disfigure_match, &disfigure_execute, nullptr, // operation post - nullptr // meta-operation post + &disfigure_meta_operation_post }; } } |