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,59 @@ 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 , lastTick: false );
257+
258+ final timer = Timer .periodic (
259+ const Duration (milliseconds: 100 ),
260+ (_) => _compileTick (isAot: isAot, firstTick: false , lastTick: false ),
261+ );
262+ try {
263+ return await function ();
264+ } finally {
265+ timer.cancel ();
266+ _compileTick (isAot: isAot, firstTick: false , lastTick: true );
267+ }
268+ }
269+
270+ void _compileTick ({
271+ required bool isAot,
272+ required bool firstTick,
273+ required bool lastTick,
274+ }) {
275+ final duration = _stopwatch.elapsed;
276+ _stopwatch.reset ();
277+ _processDuration += duration;
278+
279+ if (! firstTick) {
280+ if (isAot) {
281+ _aotCompileProgress! .duration += duration;
282+ } else {
283+ _jitCompileProgress! .duration += duration;
284+ }
285+ }
286+
287+ if (_shouldShowProgressNow || lastTick) {
288+ if (_display.displayingBlocks) {
289+ _display.block (render ());
290+ } else {
291+ _display.message (
292+ Severity .info,
293+ _renderCompiling (isAot: isAot).toString (),
294+ );
295+ }
296+ }
297+ }
298+
229299 /// Sets up logging of build phases with the number of primary inputs matching
230300 /// for each required phase.
231301 void startPhases (Map <InBuildPhase , int > primaryInputCountsByPhase) {
@@ -337,13 +407,16 @@ class BuildLog {
337407 /// build) has started.
338408 ///
339409 /// Clears timings and messages.
340- void nextBuild () {
410+ void nextBuild ({ bool recompilingBuilders = false } ) {
341411 _stopwatch.reset ();
342412 _processDuration = Duration .zero;
343413 activities.clear ();
344414 _messages.clear ();
345415 _status.clear ();
346- _display.flushAndPrint ('\n Starting build #${++_buildNumber }.\n ' );
416+ _display.flushAndPrint (
417+ '\n Starting build #${++_buildNumber }'
418+ '${recompilingBuilders ? ' with updated builders' : '' }.\n ' ,
419+ );
347420 }
348421
349422 /// Logs that the build has finished with [result] and the count of [outputs] .
@@ -374,6 +447,10 @@ class BuildLog {
374447 );
375448 }
376449
450+ _processDuration = Duration .zero;
451+ _jitCompileProgress = null ;
452+ _aotCompileProgress = null ;
453+
377454 final errors = _errors.build ();
378455 _errors.clear ();
379456 return errors;
@@ -442,6 +519,13 @@ class BuildLog {
442519 AnsiBuffer render () {
443520 final result = AnsiBuffer ();
444521
522+ if (_jitCompileProgress != null ) {
523+ result.write (_renderCompiling (isAot: false ));
524+ }
525+ if (_aotCompileProgress != null ) {
526+ result.write (_renderCompiling (isAot: true ));
527+ }
528+
445529 final displayedProgressEntries = _phaseProgress.entries.where (
446530 (e) => e.value.isDisplayed || _messages.hasMessages (phaseName: e.key),
447531 );
@@ -484,8 +568,20 @@ class BuildLog {
484568 return result;
485569 }
486570
571+ AnsiBufferLine _renderCompiling ({required bool isAot}) {
572+ final progress = isAot ? _aotCompileProgress! : _jitCompileProgress! ;
573+ return AnsiBufferLine ([
574+ renderDuration (progress.duration),
575+ ' ' ,
576+ AnsiBuffer .bold,
577+ 'compiling builders' ,
578+ AnsiBuffer .reset,
579+ '/${isAot ? 'aot' : 'jit' }' ,
580+ ]);
581+ }
582+
487583 /// Renders a line describing the progress of [phaseName] .
488- AnsiBufferLine _renderPhase (String phaseName, { int padDuration = 0 } ) {
584+ AnsiBufferLine _renderPhase (String phaseName) {
489585 final activities = this .activities.render (phaseName: phaseName);
490586
491587 var firstSeparator = true ;
@@ -499,7 +595,7 @@ class BuildLog {
499595
500596 final progress = _phaseProgress[phaseName]! ;
501597 return AnsiBufferLine ([
502- renderDuration (progress.duration). padLeft (padDuration) ,
598+ renderDuration (progress.duration),
503599 ' ' ,
504600 AnsiBuffer .bold,
505601 phaseName,
@@ -554,6 +650,19 @@ extension _PhaseExtension on InBuildPhase {
554650 lazy ? '$displayName (lazy)' : displayName;
555651}
556652
653+ /// Compile progress.
654+ class _CompileProgress {
655+ Duration duration = Duration .zero;
656+
657+ Object ? serialize () => duration.inMilliseconds;
658+
659+ static _CompileProgress ? deserialize (Object ? serialized) {
660+ if (serialized == null ) return null ;
661+ return _CompileProgress ()
662+ ..duration = Duration (milliseconds: serialized as int );
663+ }
664+ }
665+
557666/// Progress metrics tracked for each build phase.
558667class _PhaseProgress {
559668 Duration duration = Duration .zero;
0 commit comments