aboutsummaryrefslogtreecommitdiff
path: root/build/cli/rule.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'build/cli/rule.cxx')
-rw-r--r--build/cli/rule.cxx147
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::