22// for details. All rights reserved. Use of this source code is governed by a
33// BSD-style license that can be found in the LICENSE file.
44
5+ import 'dart:async' ;
56import 'dart:io' ;
67import 'dart:math' ;
78
@@ -73,6 +74,12 @@ class BuildLog {
7374 /// Errors logged.
7475 final ListBuilder <String > _errors = ListBuilder ();
7576
77+ /// JIT compile progress, if there was a JIT compile.
78+ _CompileProgress ? _jitCompileProgress;
79+
80+ /// AOT compile progress, if there was an AOT compile.
81+ _CompileProgress ? _aotCompileProgress;
82+
7683 /// Progress by build phase.
7784 final Map <String , _PhaseProgress > _phaseProgress = {};
7885
@@ -102,6 +109,9 @@ class BuildLog {
102109 buildProcessState.doBeforeSend (() {
103110 buildProcessState.elapsedMillis = _processDuration.inMilliseconds;
104111 buildProcessState.buildLogMode = configuration.mode;
112+ buildProcessState.jitCompileProgress = _jitCompileProgress? .serialize ();
113+ buildProcessState.aotCompileProgress = _aotCompileProgress? .serialize ();
114+ buildProcessState.buildNumber = _buildNumber;
105115 });
106116 void updateFromProcessState () {
107117 _processDuration = Duration (
@@ -110,6 +120,13 @@ class BuildLog {
110120 configuration = configuration.rebuild ((b) {
111121 b.mode = buildProcessState.buildLogMode;
112122 });
123+ _jitCompileProgress = _CompileProgress .deserialize (
124+ buildProcessState.jitCompileProgress,
125+ );
126+ _aotCompileProgress = _CompileProgress .deserialize (
127+ buildProcessState.aotCompileProgress,
128+ );
129+ _buildNumber = buildProcessState.buildNumber;
113130 }
114131
115132 updateFromProcessState ();
@@ -226,6 +243,54 @@ class BuildLog {
226243 );
227244 }
228245
246+ Future <T > logCompile <T >({
247+ required bool isAot,
248+ required Future <T > Function () function,
249+ }) async {
250+ final progress = _CompileProgress ();
251+ if (isAot) {
252+ _aotCompileProgress = progress;
253+ } else {
254+ _jitCompileProgress = progress;
255+ }
256+ _compileTick (isAot: isAot, firstTick: true );
257+
258+ final timer = Timer .periodic (
259+ const Duration (milliseconds: 100 ),
260+ (_) => _compileTick (isAot: isAot, firstTick: false ),
261+ );
262+ try {
263+ return await function ();
264+ } finally {
265+ timer.cancel ();
266+ }
267+ }
268+
269+ void _compileTick ({required bool firstTick, required bool isAot}) {
270+ final duration = _stopwatch.elapsed;
271+ _stopwatch.reset ();
272+ _processDuration += duration;
273+
274+ if (! firstTick) {
275+ if (isAot) {
276+ _aotCompileProgress! .duration += duration;
277+ } else {
278+ _jitCompileProgress! .duration += duration;
279+ }
280+ }
281+
282+ if (_shouldShowProgressNow) {
283+ if (_display.displayingBlocks) {
284+ _display.block (render ());
285+ } else {
286+ _display.message (
287+ Severity .info,
288+ _renderCompiling (isAot: isAot).toString (),
289+ );
290+ }
291+ }
292+ }
293+
229294 /// Sets up logging of build phases with the number of primary inputs matching
230295 /// for each required phase.
231296 void startPhases (Map <InBuildPhase , int > primaryInputCountsByPhase) {
@@ -337,13 +402,16 @@ class BuildLog {
337402 /// build) has started.
338403 ///
339404 /// Clears timings and messages.
340- void nextBuild () {
405+ void nextBuild ({ bool recompilingBuilders = false } ) {
341406 _stopwatch.reset ();
342407 _processDuration = Duration .zero;
343408 activities.clear ();
344409 _messages.clear ();
345410 _status.clear ();
346- _display.flushAndPrint ('\n Starting build #${++_buildNumber }.\n ' );
411+ _display.flushAndPrint (
412+ '\n Starting build #${++_buildNumber }'
413+ '${recompilingBuilders ? ' with updated builders' : '' }.\n ' ,
414+ );
347415 }
348416
349417 /// Logs that the build has finished with [result] and the count of [outputs] .
@@ -374,6 +442,10 @@ class BuildLog {
374442 );
375443 }
376444
445+ _processDuration = Duration .zero;
446+ _jitCompileProgress = null ;
447+ _aotCompileProgress = null ;
448+
377449 final errors = _errors.build ();
378450 _errors.clear ();
379451 return errors;
@@ -442,6 +514,13 @@ class BuildLog {
442514 AnsiBuffer render () {
443515 final result = AnsiBuffer ();
444516
517+ if (_jitCompileProgress != null ) {
518+ result.write (_renderCompiling (isAot: false ));
519+ }
520+ if (_aotCompileProgress != null ) {
521+ result.write (_renderCompiling (isAot: true ));
522+ }
523+
445524 final displayedProgressEntries = _phaseProgress.entries.where (
446525 (e) => e.value.isDisplayed || _messages.hasMessages (phaseName: e.key),
447526 );
@@ -484,8 +563,20 @@ class BuildLog {
484563 return result;
485564 }
486565
566+ AnsiBufferLine _renderCompiling ({required bool isAot}) {
567+ final progress = isAot ? _aotCompileProgress! : _jitCompileProgress! ;
568+ return AnsiBufferLine ([
569+ renderDuration (progress.duration),
570+ ' ' ,
571+ AnsiBuffer .bold,
572+ 'compiling builders' ,
573+ AnsiBuffer .reset,
574+ '/${isAot ? 'aot' : 'jit' }' ,
575+ ]);
576+ }
577+
487578 /// Renders a line describing the progress of [phaseName] .
488- AnsiBufferLine _renderPhase (String phaseName, { int padDuration = 0 } ) {
579+ AnsiBufferLine _renderPhase (String phaseName) {
489580 final activities = this .activities.render (phaseName: phaseName);
490581
491582 var firstSeparator = true ;
@@ -499,7 +590,7 @@ class BuildLog {
499590
500591 final progress = _phaseProgress[phaseName]! ;
501592 return AnsiBufferLine ([
502- renderDuration (progress.duration). padLeft (padDuration) ,
593+ renderDuration (progress.duration),
503594 ' ' ,
504595 AnsiBuffer .bold,
505596 phaseName,
@@ -554,6 +645,19 @@ extension _PhaseExtension on InBuildPhase {
554645 lazy ? '$displayName (lazy)' : displayName;
555646}
556647
648+ /// Compile progress.
649+ class _CompileProgress {
650+ Duration duration = Duration .zero;
651+
652+ Object ? serialize () => duration.inMilliseconds;
653+
654+ static _CompileProgress ? deserialize (Object ? serialized) {
655+ if (serialized == null ) return null ;
656+ return _CompileProgress ()
657+ ..duration = Duration (milliseconds: serialized as int );
658+ }
659+ }
660+
557661/// Progress metrics tracked for each build phase.
558662class _PhaseProgress {
559663 Duration duration = Duration .zero;
0 commit comments