Unverified Commit 7ffcd3d2 authored by Chris Bracken's avatar Chris Bracken Committed by GitHub

Extract KernelCompiler class (#16937)

Wraps the compile function in a class injected via the global context,
which makes it easier to mock in unit tests -- specifically tests for
AOT snapshotting, which already require pretty significant amounts of
mock inputs.
parent a21c93dd
......@@ -106,7 +106,7 @@ Future<void> build({
String kernelBinaryFilename;
if (needBuild) {
ensureDirectoryExists(applicationKernelFilePath);
final CompilerOutput compilerOutput = await compile(
final CompilerOutput compilerOutput = await kernelCompiler.compile(
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
incrementalCompilerByteStorePath: fs.path.absolute(getIncrementalCompilerByteStoreDirectory()),
mainPath: fs.file(mainPath).absolute.path,
......
......@@ -366,7 +366,7 @@ Future<String> _buildAotSnapshot(
}
if (previewDart2) {
final CompilerOutput compilerOutput = await compile(
final CompilerOutput compilerOutput = await kernelCompiler.compile(
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
mainPath: mainPath,
outputFilePath: kApplicationKernelPath,
......
......@@ -9,10 +9,13 @@ import 'package:usage/uuid/uuid.dart';
import 'artifacts.dart';
import 'base/common.dart';
import 'base/context.dart';
import 'base/io.dart';
import 'base/process_manager.dart';
import 'globals.dart';
KernelCompiler get kernelCompiler => context[KernelCompiler];
typedef void CompilerMessageConsumer(String message);
class CompilerOutput {
......@@ -59,7 +62,10 @@ class _StdoutHandler {
}
}
Future<CompilerOutput> compile(
class KernelCompiler {
const KernelCompiler();
Future<CompilerOutput> compile(
{String sdkRoot,
String mainPath,
String outputFilePath,
......@@ -73,80 +79,81 @@ Future<CompilerOutput> compile(
String packagesPath,
List<String> fileSystemRoots,
String fileSystemScheme}) async {
final String frontendServer = artifacts.getArtifactPath(
Artifact.frontendServerSnapshotForEngineDartSdk
);
// This is a URI, not a file path, so the forward slash is correct even on Windows.
if (!sdkRoot.endsWith('/'))
sdkRoot = '$sdkRoot/';
final String engineDartPath = artifacts.getArtifactPath(Artifact.engineDartBinary);
if (!processManager.canRun(engineDartPath)) {
throwToolExit('Unable to find Dart binary at $engineDartPath');
}
final List<String> command = <String>[
engineDartPath,
frontendServer,
'--sdk-root',
sdkRoot,
'--strong',
'--target=flutter',
];
if (trackWidgetCreation)
command.add('--track-widget-creation');
if (!linkPlatformKernelIn)
command.add('--no-link-platform');
if (aot) {
command.add('--aot');
command.add('--tfa');
}
if (entryPointsJsonFiles != null) {
for (String entryPointsJson in entryPointsJsonFiles) {
command.addAll(<String>['--entry-points', entryPointsJson]);
final String frontendServer = artifacts.getArtifactPath(
Artifact.frontendServerSnapshotForEngineDartSdk
);
// This is a URI, not a file path, so the forward slash is correct even on Windows.
if (!sdkRoot.endsWith('/'))
sdkRoot = '$sdkRoot/';
final String engineDartPath = artifacts.getArtifactPath(Artifact.engineDartBinary);
if (!processManager.canRun(engineDartPath)) {
throwToolExit('Unable to find Dart binary at $engineDartPath');
}
}
if (incrementalCompilerByteStorePath != null) {
command.add('--incremental');
}
if (packagesPath != null) {
command.addAll(<String>['--packages', packagesPath]);
}
if (outputFilePath != null) {
command.addAll(<String>['--output-dill', outputFilePath]);
}
if (depFilePath != null && (fileSystemRoots == null || fileSystemRoots.isEmpty)) {
command.addAll(<String>['--depfile', depFilePath]);
}
if (fileSystemRoots != null) {
for (String root in fileSystemRoots) {
command.addAll(<String>['--filesystem-root', root]);
final List<String> command = <String>[
engineDartPath,
frontendServer,
'--sdk-root',
sdkRoot,
'--strong',
'--target=flutter',
];
if (trackWidgetCreation)
command.add('--track-widget-creation');
if (!linkPlatformKernelIn)
command.add('--no-link-platform');
if (aot) {
command.add('--aot');
command.add('--tfa');
}
}
if (fileSystemScheme != null) {
command.addAll(<String>['--filesystem-scheme', fileSystemScheme]);
}
if (entryPointsJsonFiles != null) {
for (String entryPointsJson in entryPointsJsonFiles) {
command.addAll(<String>['--entry-points', entryPointsJson]);
}
}
if (incrementalCompilerByteStorePath != null) {
command.add('--incremental');
}
if (packagesPath != null) {
command.addAll(<String>['--packages', packagesPath]);
}
if (outputFilePath != null) {
command.addAll(<String>['--output-dill', outputFilePath]);
}
if (depFilePath != null && (fileSystemRoots == null || fileSystemRoots.isEmpty)) {
command.addAll(<String>['--depfile', depFilePath]);
}
if (fileSystemRoots != null) {
for (String root in fileSystemRoots) {
command.addAll(<String>['--filesystem-root', root]);
}
}
if (fileSystemScheme != null) {
command.addAll(<String>['--filesystem-scheme', fileSystemScheme]);
}
if (extraFrontEndOptions != null)
command.addAll(extraFrontEndOptions);
command.add(mainPath);
printTrace(command.join(' '));
final Process server = await processManager
.start(command)
.catchError((dynamic error, StackTrace stack) {
printError('Failed to start frontend server $error, $stack');
});
if (extraFrontEndOptions != null)
command.addAll(extraFrontEndOptions);
command.add(mainPath);
printTrace(command.join(' '));
final Process server = await processManager
.start(command)
.catchError((dynamic error, StackTrace stack) {
printError('Failed to start frontend server $error, $stack');
});
final _StdoutHandler stdoutHandler = new _StdoutHandler();
server.stderr
.transform(utf8.decoder)
.listen((String s) { printError('compiler message: $s'); });
server.stdout
.transform(utf8.decoder)
.transform(const LineSplitter())
.listen(stdoutHandler.handler);
final int exitCode = await server.exitCode;
return exitCode == 0 ? stdoutHandler.compilerOutput.future : null;
final _StdoutHandler stdoutHandler = new _StdoutHandler();
server.stderr
.transform(utf8.decoder)
.listen((String s) { printError('compiler message: $s'); });
server.stdout
.transform(utf8.decoder)
.transform(const LineSplitter())
.listen(stdoutHandler.handler);
final int exitCode = await server.exitCode;
return exitCode == 0 ? stdoutHandler.compilerOutput.future : null;
}
}
/// Wrapper around incremental frontend server compiler, that communicates with
......
......@@ -22,6 +22,7 @@ import 'base/platform.dart';
import 'base/port_scanner.dart';
import 'base/utils.dart';
import 'cache.dart';
import 'compile.dart';
import 'devfs.dart';
import 'device.dart';
import 'doctor.dart';
......@@ -63,6 +64,7 @@ Future<T> runInContext<T>(
IMobileDevice: () => const IMobileDevice(),
IOSSimulatorUtils: () => new IOSSimulatorUtils(),
IOSWorkflow: () => const IOSWorkflow(),
KernelCompiler: () => const KernelCompiler(),
Logger: () => platform.isWindows ? new WindowsStdoutLogger() : new StdoutLogger(),
OperatingSystemUtils: () => new OperatingSystemUtils(),
PortScanner: () => const HostPortScanner(),
......
......@@ -46,7 +46,7 @@ void main() {
'result abc\nline1\nline2\nabc /path/to/main.dart.dill 0'
))
));
final CompilerOutput output = await compile(sdkRoot: '/path/to/sdkroot',
final CompilerOutput output = await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
mainPath: '/path/to/main.dart'
);
expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
......@@ -66,7 +66,7 @@ void main() {
))
));
final CompilerOutput output = await compile(sdkRoot: '/path/to/sdkroot',
final CompilerOutput output = await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
mainPath: '/path/to/main.dart'
);
expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
......@@ -88,7 +88,7 @@ void main() {
))
));
final CompilerOutput output = await compile(sdkRoot: '/path/to/sdkroot',
final CompilerOutput output = await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
mainPath: '/path/to/main.dart'
);
expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
......
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