aboutsummaryrefslogtreecommitdiff
path: root/build2/b.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-12-16 09:43:38 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-12-16 09:43:38 +0200
commit630dc4ccf3207f7cdd5b410582e1e572081b80e8 (patch)
treedc6b4dfb5608799fc63f4f1b6f6fceee8530cb0c /build2/b.cxx
parentb3df2f69ff340e2c5c6d215bea6689594f0a3d80 (diff)
Add support for structured result output (--structured-result)
Diffstat (limited to 'build2/b.cxx')
-rw-r--r--build2/b.cxx115
1 files changed, 94 insertions, 21 deletions
diff --git a/build2/b.cxx b/build2/b.cxx
index a88d1c0..0d88f5f 100644
--- a/build2/b.cxx
+++ b/build2/b.cxx
@@ -57,12 +57,67 @@ namespace build2
{
int
main (int argc, char* argv[]);
-}
-int
-main (int argc, char* argv[])
-{
- return build2::main (argc, argv);
+ // Structured result printer (--structured-result mode).
+ //
+ class result_printer
+ {
+ public:
+ result_printer (const action_targets& tgs): tgs_ (tgs) {}
+ ~result_printer ();
+
+ private:
+ const action_targets& tgs_;
+ };
+
+ result_printer::
+ ~result_printer ()
+ {
+ // Let's do some sanity checking even when we are not in the structred
+ // output mode.
+ //
+ for (const action_target& at: tgs_)
+ {
+ switch (at.state)
+ {
+ case target_state::unknown: continue; // Not a target/no result.
+ case target_state::unchanged:
+ case target_state::changed:
+ case target_state::failed: break; // Valid states.
+ default: assert (false);
+ }
+
+ if (ops.structured_result ())
+ {
+ cout << at.state
+ << ' ' << current_mif->name
+ << ' ' << current_inner_oif->name;
+
+ if (current_outer_oif != nullptr)
+ cout << '(' << current_outer_oif->name << ')';
+
+ // There are two ways one may wish to identify the target of the
+ // operation: as something specific but inherently non-portable (say,
+ // a filesystem path, for example c:\tmp\foo.exe) or as something
+ // regular that can be used to refer to a target in a portable way
+ // (for example, c:\tmp\exe{foo}; note that the directory part is
+ // still not portable). Which one should we use is a good question.
+ // Let's go with the portable one for now and see how it goes (we
+ // can always add a format version, e.g., --structured-result=2).
+
+ // Set the stream verbosity to 0 to suppress extension printing by
+ // default (this can still be overriden by the target type's print
+ // function as is the case for file{}, for example).
+ //
+ uint16_t v (stream_verb (cout));
+ stream_verb (cout, 0);
+
+ cout << ' ' << at.as_target () << endl;
+
+ stream_verb (cout, v);
+ }
+ }
+ }
}
int build2::
@@ -1143,33 +1198,43 @@ main (int argc, char* argv[])
action a (mid, pre_oid, oid);
- // Run quiet.
- //
- if (mif->match != nullptr)
- mif->match (mparams, a, tgs);
+ {
+ result_printer p (tgs);
- if (mif->execute != nullptr && !ops.match_only ())
- mif->execute (mparams, a, tgs, true);
+ if (mif->match != nullptr)
+ mif->match (mparams, a, tgs);
+
+ if (mif->execute != nullptr && !ops.match_only ())
+ mif->execute (mparams, a, tgs, true /* quiet */);
+ }
if (mif->operation_post != nullptr)
mif->operation_post (mparams, pre_oid);
l5 ([&]{trace << "end pre-operation batch " << pre_oif->name
<< ", id " << static_cast<uint16_t> (pre_oid);});
+
+ tgs.reset ();
}
set_current_oif (*oif);
action a (mid, oid, 0);
- if (mif->match != nullptr)
- mif->match (mparams, a, tgs);
+ {
+ result_printer p (tgs);
- if (mif->execute != nullptr && !ops.match_only ())
- mif->execute (mparams, a, tgs, verb == 0);
+ if (mif->match != nullptr)
+ mif->match (mparams, a, tgs);
+
+ if (mif->execute != nullptr && !ops.match_only ())
+ mif->execute (mparams, a, tgs, ops.structured_result () /*quiet*/);
+ }
if (post_oid != 0)
{
+ tgs.reset ();
+
l5 ([&]{trace << "start post-operation batch " << post_oif->name
<< ", id " << static_cast<uint16_t> (post_oid);});
@@ -1180,13 +1245,15 @@ main (int argc, char* argv[])
action a (mid, post_oid, oid);
- // Run quiet.
- //
- if (mif->match != nullptr)
- mif->match (mparams, a, tgs);
+ {
+ result_printer p (tgs);
- if (mif->execute != nullptr && !ops.match_only ())
- mif->execute (mparams, a, tgs, true);
+ if (mif->match != nullptr)
+ mif->match (mparams, a, tgs);
+
+ if (mif->execute != nullptr && !ops.match_only ())
+ mif->execute (mparams, a, tgs, true /* quiet */);
+ }
if (mif->operation_post != nullptr)
mif->operation_post (mparams, post_oid);
@@ -1248,3 +1315,9 @@ main (int argc, char* argv[])
return r;
}
+
+int
+main (int argc, char* argv[])
+{
+ return build2::main (argc, argv);
+}