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