diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-06-26 17:25:10 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-06-26 17:25:10 +0200 |
commit | 18568ff0ff3dce89d694b494c5dfc9a32e63c9e6 (patch) | |
tree | cd36895fdab3b30b8b61fcc3e12f8a92bb292203 /build/cli | |
parent | 95239b7c5404965d4f5ef997b5b75bf542a25192 (diff) |
Part two of dependency injection with auto-generation support
Diffstat (limited to 'build/cli')
-rw-r--r-- | build/cli/rule.cxx | 147 |
1 files changed, 93 insertions, 54 deletions
diff --git a/build/cli/rule.cxx b/build/cli/rule.cxx index abcbb70..6f8b648 100644 --- a/build/cli/rule.cxx +++ b/build/cli/rule.cxx @@ -8,6 +8,7 @@ #include <build/scope> #include <build/target> +#include <build/context> #include <build/algorithm> #include <build/diagnostics> @@ -217,68 +218,95 @@ namespace build // cli* s (execute_prerequisites<cli> (a, t, t.h ()->mtime ())); + target_state ts; + if (s == nullptr) - return target_state::unchanged; + ts = target_state::unchanged; + else + { + // Translate source path to relative (to working directory). This + // results in easier to read diagnostics. + // + path relo (relative (t.dir)); + path rels (relative (s->path ())); - // Translate source path to relative (to working directory). This - // results in easier to read diagnostics. - // - path relo (relative (t.dir)); - path rels (relative (s->path ())); + scope& rs (t.root_scope ()); + const string& cli (rs["config.cli"].as<const string&> ()); - scope& rs (t.root_scope ()); - const string& cli (rs["config.cli"].as<const string&> ()); + vector<const char*> args {cli.c_str ()}; - vector<const char*> args {cli.c_str ()}; + // See if we need to pass any --?xx-suffix options. + // + append_extension (args, *t.h (), "--hxx-suffix", "hxx"); + append_extension (args, *t.c (), "--cxx-suffix", "cxx"); + if (t.i () != nullptr) + append_extension (args, *t.i (), "--ixx-suffix", "ixx"); - // See if we need to pass any --?xx-suffix options. - // - append_extension (args, *t.h (), "--hxx-suffix", "hxx"); - append_extension (args, *t.c (), "--cxx-suffix", "cxx"); - if (t.i () != nullptr) - append_extension (args, *t.i (), "--ixx-suffix", "ixx"); + append_options (args, t, "cli.options"); - append_options (args, t, "cli.options"); + if (!relo.empty ()) + { + args.push_back ("-o"); + args.push_back (relo.string ().c_str ()); + } - if (!relo.empty ()) - { - args.push_back ("-o"); - args.push_back (relo.string ().c_str ()); - } + args.push_back (rels.string ().c_str ()); + args.push_back (nullptr); - args.push_back (rels.string ().c_str ()); - args.push_back (nullptr); + if (verb) + print_process (args); + else + text << "cli " << *s; - if (verb) - print_process (args); - else - text << "cli " << *s; + try + { + process pr (args.data ()); - try - { - process pr (args.data ()); + if (!pr.wait ()) + throw failed (); - if (!pr.wait ()) - throw failed (); + timestamp s (system_clock::now ()); - timestamp ts (system_clock::now ()); + // Update member timestamps. + // + t.h ()->mtime (s); + t.c ()->mtime (s); + if (t.i () != nullptr) + t.i ()->mtime (s); - t.h ()->mtime (ts); - t.c ()->mtime (ts); - if (t.i () != nullptr) - t.i ()->mtime (ts); + ts = target_state::changed; + } + catch (const process_error& e) + { + error << "unable to execute " << args[0] << ": " << e.what (); - return target_state::changed; + if (e.child ()) + exit (1); + + throw failed (); + } } - catch (const process_error& e) - { - error << "unable to execute " << args[0] << ": " << e.what (); - if (e.child ()) - exit (1); + // Update member recipes. Without that the state update below + // won't stick. + // + if (!t.h ()->recipe (a)) + t.h ()->recipe (a, &delegate); + + if (!t.c ()->recipe (a)) + t.c ()->recipe (a, &delegate); - throw failed (); - } + if (t.i () != nullptr && !t.i ()->recipe (a)) + t.i ()->recipe (a, &delegate); + + // Update member states. + // + t.h ()->state = ts; + t.c ()->state = ts; + if (t.i () != nullptr) + t.i ()->state = ts; + + return ts; } target_state compile:: @@ -286,19 +314,30 @@ namespace build { cli_cxx& t (static_cast<cli_cxx&> (xt)); - target_state ts (target_state::unchanged); + // The reverse order of update: first delete the files, then clean + // prerequisites. Also update timestamp in case there are operations + // after us that could use the information. + // + // + bool r (false); + + if (t.i () != nullptr) + { + r = rmfile (t.i ()->path (), *t.i ()) || r; + t.i ()->mtime (timestamp_nonexistent); + } - if (t.i () != nullptr && - build::perform_clean (a, *t.i ()) == target_state::changed) - ts = target_state::changed; + r = rmfile (t.c ()->path (), *t.c ()) || r; + t.c ()->mtime (timestamp_nonexistent); - if (build::perform_clean (a, *t.c ()) == target_state::changed) - ts = target_state::changed; + r = rmfile (t.h ()->path (), *t.h ()) || r; + t.h ()->mtime (timestamp_nonexistent); - if (build::perform_clean (a, *t.h ()) == target_state::changed) - ts = target_state::changed; + // Clean prerequisites. + // + target_state ts (reverse_execute_prerequisites (a, t)); - return ts; + return r ? target_state::changed : ts; } target_state compile:: |