Unverified Commit 1e397d3f authored by xster's avatar xster Committed by GitHub

Break up and show more progression during an Xcode build (#14715)

* Created plumbing but has stream problem

* testing with makePipe

* Trying pipe but not really getting anywhere

* works by repeatedly reading line

* Minor cleanup

* works

* Clean up pipe after use.

* Move the last status forward

* Make sure failed script commands bubble up
parent 10393a12
......@@ -11,6 +11,14 @@ RunCommand() {
return $?
}
# When provided with a pipe by the host Flutter build process, output to the
# pipe goes to stdout of the Flutter build process directly.
StreamOutput() {
if [[ -n "$SCRIPT_OUTPUT_STREAM_FILE" ]]; then
echo "$1" > $SCRIPT_OUTPUT_STREAM_FILE
fi
}
EchoError() {
echo "$@" 1>&2
}
......@@ -103,18 +111,20 @@ BuildApp() {
aot_flags="--${build_mode}"
fi
StreamOutput " ├─Building Dart code..."
RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics build aot \
--output-dir="${build_dir}/aot" \
--target-platform=ios \
--target="${target_path}" \
${aot_flags} \
${local_engine_flag} \
${preview_dart_2_flag} \
${preview_dart_2_flag}
if [[ $? -ne 0 ]]; then
EchoError "Failed to build ${project_path}."
exit -1
fi
StreamOutput "done"
RunCommand cp -r -- "${build_dir}/aot/App.framework" "${derived_dir}"
else
......@@ -133,6 +143,7 @@ BuildApp() {
precompilation_flag="--precompiled"
fi
StreamOutput " ├─Assembling Flutter resources..."
RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics build flx \
--target="${target_path}" \
--output-file="${derived_dir}/app.flx" \
......@@ -141,12 +152,14 @@ BuildApp() {
--working-dir="${derived_dir}/flutter_assets" \
${precompilation_flag} \
${local_engine_flag} \
${preview_dart_2_flag} \
${preview_dart_2_flag}
if [[ $? -ne 0 ]]; then
EchoError "Failed to package ${project_path}."
exit -1
fi
StreamOutput "done"
StreamOutput " └─Compiling, linking and signing..."
RunCommand popd > /dev/null
......
......@@ -40,7 +40,15 @@ abstract class Logger {
///
/// [message] is the message to display to the user; [progressId] provides an ID which can be
/// used to identify this type of progress (`hot.reload`, `hot.restart`, ...).
Status startProgress(String message, { String progressId, bool expectSlowOperation: false });
///
/// [progressIndicatorPadding] can optionally be used to specify spacing
/// between the [message] and the progress indicator.
Status startProgress(
String message, {
String progressId,
bool expectSlowOperation: false,
int progressIndicatorPadding: 52,
});
}
class Status {
......@@ -96,13 +104,23 @@ class StdoutLogger extends Logger {
void printTrace(String message) { }
@override
Status startProgress(String message, { String progressId, bool expectSlowOperation: false }) {
Status startProgress(
String message, {
String progressId,
bool expectSlowOperation: false,
int progressIndicatorPadding: 52,
}) {
if (_status != null) {
// Ignore nested progresses; return a no-op status object.
return new Status();
} else {
if (supportsColor) {
_status = new _AnsiStatus(message, expectSlowOperation, () { _status = null; });
_status = new _AnsiStatus(
message,
expectSlowOperation,
() { _status = null; },
progressIndicatorPadding,
);
return _status;
} else {
printStatus(message);
......@@ -163,7 +181,12 @@ class BufferLogger extends Logger {
void printTrace(String message) => _trace.writeln(message);
@override
Status startProgress(String message, { String progressId, bool expectSlowOperation: false }) {
Status startProgress(
String message, {
String progressId,
bool expectSlowOperation: false,
int progressIndicatorPadding: 52,
}) {
printStatus(message);
return new Status();
}
......@@ -208,7 +231,12 @@ class VerboseLogger extends Logger {
}
@override
Status startProgress(String message, { String progressId, bool expectSlowOperation: false }) {
Status startProgress(
String message, {
String progressId,
bool expectSlowOperation: false,
int progressIndicatorPadding: 52,
}) {
printStatus(message);
return new Status();
}
......@@ -253,10 +281,10 @@ enum _LogType {
}
class _AnsiStatus extends Status {
_AnsiStatus(this.message, this.expectSlowOperation, this.onFinish) {
_AnsiStatus(this.message, this.expectSlowOperation, this.onFinish, int padding) {
stopwatch = new Stopwatch()..start();
stdout.write('${message.padRight(52)} ');
stdout.write('${message.padRight(padding)} ');
stdout.write('${_progress[0]}');
timer = new Timer.periodic(const Duration(milliseconds: 100), _callback);
......
......@@ -763,7 +763,12 @@ class NotifyingLogger extends Logger {
}
@override
Status startProgress(String message, { String progressId, bool expectSlowOperation: false }) {
Status startProgress(
String message, {
String progressId,
bool expectSlowOperation: false,
int progressIndicatorPadding: 52,
}) {
printStatus(message);
return new Status();
}
......@@ -863,7 +868,12 @@ class _AppRunLogger extends Logger {
Status _status;
@override
Status startProgress(String message, { String progressId, bool expectSlowOperation: false }) {
Status startProgress(
String message, {
String progressId,
bool expectSlowOperation: false,
int progressIndicatorPadding: 52,
}) {
// Ignore nested progresses; return a no-op status object.
if (_status != null)
return new Status();
......
......@@ -8,6 +8,7 @@ import 'dart:convert';
import '../application_package.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/port_scanner.dart';
import '../base/process.dart';
......@@ -239,6 +240,8 @@ class IOSDevice extends Device {
int installationResult = -1;
Uri localObservatoryUri;
final Status installStatus =
logger.startProgress('Installing and launching...', expectSlowOperation: true);
if (!debuggingOptions.debuggingEnabled) {
// If debugging is not enabled, just launch the application and continue.
printTrace('Debugging is not enabled');
......@@ -247,6 +250,7 @@ class IOSDevice extends Device {
mapFunction: monitorInstallationFailure,
trace: true,
);
installStatus.stop();
} else {
// Debugging is enabled, look for the observatory server port post launch.
printTrace('Debugging is enabled, connecting to observatory');
......@@ -282,6 +286,7 @@ class IOSDevice extends Device {
observatoryDiscovery.cancel();
});
}
installStatus.stop();
if (installationResult != 0) {
printError('Could not install ${bundle.path} on $id.');
......
......@@ -13,9 +13,11 @@ import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/os.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../base/process_manager.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../flx.dart' as flx;
import '../globals.dart';
......@@ -346,14 +348,58 @@ Future<XcodeBuildResult> buildXcodeProject({
);
}
final Status buildStatus =
logger.startProgress('Running Xcode build...', expectSlowOperation: true);
Status buildSubStatus;
Status initialBuildStatus;
Directory scriptOutputPipeTempDirectory;
if (logger.supportsColor) {
scriptOutputPipeTempDirectory = fs.systemTempDirectory
.createTempSync('flutter_build_log_pipe');
final File scriptOutputPipeFile =
scriptOutputPipeTempDirectory.childFile('pipe_to_stdout');
os.makePipe(scriptOutputPipeFile.path);
Future<void> listenToScriptOutputLine() async {
final List<String> lines = await scriptOutputPipeFile.readAsLines();
for (String line in lines) {
if (line == 'done') {
buildSubStatus?.stop();
buildSubStatus = null;
} else {
initialBuildStatus.cancel();
buildSubStatus = logger.startProgress(
line,
expectSlowOperation: true,
progressIndicatorPadding: 45,
);
}
}
return listenToScriptOutputLine();
}
// Trigger the start of the pipe -> stdout loop. Ignore exceptions.
listenToScriptOutputLine(); // ignore: unawaited_futures
buildCommands.add('SCRIPT_OUTPUT_STREAM_FILE=${scriptOutputPipeFile.absolute.path}');
}
final Stopwatch buildStopwatch = new Stopwatch()..start();
initialBuildStatus = logger.startProgress('Starting Xcode build...');
final RunResult buildResult = await runAsync(
buildCommands,
workingDirectory: app.appDirectory,
allowReentrantFlutter: true
);
buildStatus.stop();
buildSubStatus?.stop();
initialBuildStatus?.cancel();
buildStopwatch.stop();
// Free pipe file.
scriptOutputPipeTempDirectory?.deleteSync(recursive: true);
printStatus(
'Xcode build done',
ansiAlternative: 'Xcode build done'.padRight(53)
+ '${getElapsedAsSeconds(buildStopwatch.elapsed).padLeft(5)}',
);
// Run -showBuildSettings again but with the exact same parameters as the build.
final Map<String, String> buildSettings = parseXcodeBuildSettings(runCheckedSync(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment