feat(cross): emit per-phase build timings (augment, build)

A --build run now reports how long each phase took, alongside the existing
resolve time from the progress spinner:
  augment       : libdisplay-info staged (42.1s)
  build         : 1 backend(s) in 63.4s

This makes emb's cache-hit speedup measurable in CI (a warm consume build shows
resolve in seconds, no download/extract) and surfaces where cold time goes.

Signed-off-by: Joel Winarske <joel.winarske@gmail.com>
This commit is contained in:
Joel Winarske
2026-06-19 18:01:06 -07:00
parent b147711714
commit 3498ddb691
+17
View File
@@ -545,6 +545,7 @@ class CrossCommand extends Command<int> {
// embedder's pkg-config probes resolve them. Native builds use the host's
// system libraries instead (install via the manifest deps / emb deps).
if (!native && target.augment.isNotEmpty) {
final sw = Stopwatch()..start();
final overlay = OverlayBuilder(workspace, profile);
try {
await overlay.build(
@@ -557,6 +558,10 @@ class CrossCommand extends Command<int> {
} finally {
overlay.close();
}
_logger.info(
' augment : ${target.augment.map((a) => a.pkg).join(", ")} '
'staged (${_secs(sw)})',
);
}
final buildRoot = workspace.ensurePlatformDir(
@@ -569,6 +574,7 @@ class CrossCommand extends Command<int> {
hostTools: hostTools,
);
final buildSw = Stopwatch()..start();
final results = backends.isEmpty
? [
await builder.build(
@@ -586,6 +592,7 @@ class CrossCommand extends Command<int> {
backends: backends,
cmakeArgs: target.cmakeArgs,
);
buildSw.stop();
for (final r in results) {
final tag = r.backend != null ? '${r.backend}: ' : '';
@@ -595,6 +602,12 @@ class CrossCommand extends Command<int> {
_logger.err(' $tag${r.message ?? "build failed"}');
}
}
final okCount = results.where((r) => r.success).length;
if (okCount > 0) {
_logger.info(
' build : $okCount backend(s) in ${_secs(buildSw)}',
);
}
if (!results.every((r) => r.success)) return ExitCode.software.code;
final built = results.where((r) => r.success).toList();
@@ -1037,6 +1050,10 @@ class CrossCommand extends Command<int> {
}
}
/// A stopwatch rendered as `X.Ys`, for the per-phase build timings.
static String _secs(Stopwatch sw) =>
'${(sw.elapsedMilliseconds / 1000).toStringAsFixed(1)}s';
/// Emit a Dockerfile + .dockerignore that bake the resolved arm-gnu toolchain
/// + sysroot into an OCI image (build context = the platform dir). Other
/// providers don't lay out a self-contained dir to bake.