Unverified Commit bcaf026c authored by Stanislav Baranov's avatar Stanislav Baranov Committed by GitHub

Add flutter tool support for creating app-specific VM snapshots. (#18417)

Add flutter tool support for creating app-specific VM snapshots.
parent a6cdc2b7
...@@ -166,8 +166,10 @@ BuildApp() { ...@@ -166,8 +166,10 @@ BuildApp() {
RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics \ RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics \
${verbose_flag} \ ${verbose_flag} \
build bundle \ build bundle \
--target-platform=ios \
--target="${target_path}" \ --target="${target_path}" \
--snapshot="${build_dir}/snapshot_blob.bin" \ --snapshot="${build_dir}/snapshot_blob.bin" \
--${build_mode} \
--depfile="${build_dir}/snapshot_blob.bin.d" \ --depfile="${build_dir}/snapshot_blob.bin.d" \
--asset-dir="${derived_dir}/flutter_assets" \ --asset-dir="${derived_dir}/flutter_assets" \
${precompilation_flag} \ ${precompilation_flag} \
......
...@@ -276,7 +276,10 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -276,7 +276,10 @@ class FlutterPlugin implements Plugin<Project> {
if (project.hasProperty('track-widget-creation')) { if (project.hasProperty('track-widget-creation')) {
trackWidgetCreationValue = project.property('track-widget-creation').toBoolean() trackWidgetCreationValue = project.property('track-widget-creation').toBoolean()
} }
Boolean buildSnapshotValue = false
if (project.hasProperty('build-snapshot')) {
buildSnapshotValue = project.property('build-snapshot').toBoolean()
}
String extraFrontEndOptionsValue = null String extraFrontEndOptionsValue = null
if (project.hasProperty('extra-front-end-options')) { if (project.hasProperty('extra-front-end-options')) {
extraFrontEndOptionsValue = project.property('extra-front-end-options') extraFrontEndOptionsValue = project.property('extra-front-end-options')
...@@ -319,6 +322,7 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -319,6 +322,7 @@ class FlutterPlugin implements Plugin<Project> {
fileSystemRoots fileSystemRootsValue fileSystemRoots fileSystemRootsValue
fileSystemScheme fileSystemSchemeValue fileSystemScheme fileSystemSchemeValue
trackWidgetCreation trackWidgetCreationValue trackWidgetCreation trackWidgetCreationValue
buildSnapshot buildSnapshotValue
buildSharedLibrary buildSharedLibraryValue buildSharedLibrary buildSharedLibraryValue
targetPlatform targetPlatformValue targetPlatform targetPlatformValue
sourceDir project.file(project.flutter.source) sourceDir project.file(project.flutter.source)
...@@ -368,6 +372,8 @@ abstract class BaseFlutterTask extends DefaultTask { ...@@ -368,6 +372,8 @@ abstract class BaseFlutterTask extends DefaultTask {
@Optional @Input @Optional @Input
Boolean trackWidgetCreation Boolean trackWidgetCreation
@Optional @Input @Optional @Input
Boolean buildSnapshot
@Optional @Input
Boolean buildSharedLibrary Boolean buildSharedLibrary
@Optional @Input @Optional @Input
String targetPlatform String targetPlatform
...@@ -380,8 +386,7 @@ abstract class BaseFlutterTask extends DefaultTask { ...@@ -380,8 +386,7 @@ abstract class BaseFlutterTask extends DefaultTask {
@OutputFiles @OutputFiles
FileCollection getDependenciesFiles() { FileCollection getDependenciesFiles() {
if (buildMode != 'debug') { // For AOT and Core JIT builds, include the gen_snapshot depfile.
// For AOT builds, include the gen_snapshot depfile.
FileCollection depfiles = project.files("${intermediateDir}/snapshot.d") FileCollection depfiles = project.files("${intermediateDir}/snapshot.d")
if (previewDart2) { if (previewDart2) {
// For Dart 2, also include the kernel compiler depfile, since // For Dart 2, also include the kernel compiler depfile, since
...@@ -389,10 +394,13 @@ abstract class BaseFlutterTask extends DefaultTask { ...@@ -389,10 +394,13 @@ abstract class BaseFlutterTask extends DefaultTask {
// and it includes all the Dart sources. // and it includes all the Dart sources.
depfiles += project.files("${intermediateDir}/kernel_compile.d") depfiles += project.files("${intermediateDir}/kernel_compile.d")
} }
// Include Core JIT kernel compiler depfile, since kernel compile is
// the first stage of JIT builds in this mode, and it includes all the
// Dart sources.
depfiles += project.files("${intermediateDir}/snapshot_blob.bin.d")
return depfiles return depfiles
} }
return project.files("${intermediateDir}/snapshot_blob.bin.d")
}
void buildBundle() { void buildBundle() {
if (!sourceDir.isDirectory()) { if (!sourceDir.isDirectory()) {
...@@ -468,9 +476,18 @@ abstract class BaseFlutterTask extends DefaultTask { ...@@ -468,9 +476,18 @@ abstract class BaseFlutterTask extends DefaultTask {
if (trackWidgetCreation) { if (trackWidgetCreation) {
args "--track-widget-creation" args "--track-widget-creation"
} }
if (buildSnapshot) {
args "--build-snapshot"
}
if (extraFrontEndOptions != null) { if (extraFrontEndOptions != null) {
args "--extra-front-end-options", "${extraFrontEndOptions}" args "--extra-front-end-options", "${extraFrontEndOptions}"
} }
if (extraGenSnapshotOptions != null) {
args "--extra-gen-snapshot-options", "${extraGenSnapshotOptions}"
}
if (targetPlatform != null) {
args "--target-platform", "${targetPlatform}"
}
if (buildMode != "debug") { if (buildMode != "debug") {
args "--precompiled" args "--precompiled"
} else { } else {
...@@ -480,6 +497,7 @@ abstract class BaseFlutterTask extends DefaultTask { ...@@ -480,6 +497,7 @@ abstract class BaseFlutterTask extends DefaultTask {
} }
} }
args "--asset-dir", "${intermediateDir}/flutter_assets" args "--asset-dir", "${intermediateDir}/flutter_assets"
args "--${buildMode}"
} }
} }
} }
...@@ -496,7 +514,7 @@ class FlutterTask extends BaseFlutterTask { ...@@ -496,7 +514,7 @@ class FlutterTask extends BaseFlutterTask {
include "flutter_assets/**" // the working dir and its files include "flutter_assets/**" // the working dir and its files
if (buildMode != 'debug') { if (buildMode != 'debug' || buildSnapshot) {
if (buildSharedLibrary) { if (buildSharedLibrary) {
include "app.so" include "app.so"
} else { } else {
......
...@@ -331,6 +331,8 @@ Future<Null> _buildGradleProjectV2(String gradle, BuildInfo buildInfo, String ta ...@@ -331,6 +331,8 @@ Future<Null> _buildGradleProjectV2(String gradle, BuildInfo buildInfo, String ta
command.add('-Ppreview-dart-2=true'); command.add('-Ppreview-dart-2=true');
if (buildInfo.trackWidgetCreation) if (buildInfo.trackWidgetCreation)
command.add('-Ptrack-widget-creation=true'); command.add('-Ptrack-widget-creation=true');
if (buildInfo.buildSnapshot)
command.add('-Pbuild-snapshot=true');
if (buildInfo.extraFrontEndOptions != null) if (buildInfo.extraFrontEndOptions != null)
command.add('-Pextra-front-end-options=${buildInfo.extraFrontEndOptions}'); command.add('-Pextra-front-end-options=${buildInfo.extraFrontEndOptions}');
if (buildInfo.extraGenSnapshotOptions != null) if (buildInfo.extraGenSnapshotOptions != null)
...@@ -345,8 +347,8 @@ Future<Null> _buildGradleProjectV2(String gradle, BuildInfo buildInfo, String ta ...@@ -345,8 +347,8 @@ Future<Null> _buildGradleProjectV2(String gradle, BuildInfo buildInfo, String ta
if (buildInfo.buildSharedLibrary && androidSdk.ndk != null) { if (buildInfo.buildSharedLibrary && androidSdk.ndk != null) {
command.add('-Pbuild-shared-library=true'); command.add('-Pbuild-shared-library=true');
} }
if (buildInfo.targetPlatform == TargetPlatform.android_arm64) if (buildInfo.targetPlatform != null)
command.add('-Ptarget-platform=android-arm64'); command.add('-Ptarget-platform=${getNameForTargetPlatform(buildInfo.targetPlatform)}');
command.add(assembleTask); command.add(assembleTask);
final int exitCode = await runCommandAndStreamOutput( final int exitCode = await runCommandAndStreamOutput(
......
...@@ -416,3 +416,119 @@ class AOTSnapshotter { ...@@ -416,3 +416,119 @@ class AOTSnapshotter {
return fs.path.dirname(fs.path.fromUri(packageMap.map[package])); return fs.path.dirname(fs.path.fromUri(packageMap.map[package]));
} }
} }
class CoreJITSnapshotter {
/// Builds a "Core JIT" VM snapshot of the specified kernel. This snapshot
/// includes data as well as either machine code or DBC, depending on build
/// configuration.
Future<int> build({
@required TargetPlatform platform,
@required BuildMode buildMode,
@required String mainPath,
@required String packagesPath,
@required String outputPath,
List<String> extraGenSnapshotOptions = const <String>[],
}) async {
if (!_isValidCoreJitPlatform(platform)) {
printError('${getNameForTargetPlatform(platform)} does not support Core JIT compilation.');
return 1;
}
final Directory outputDir = fs.directory(outputPath);
outputDir.createSync(recursive: true);
final List<String> inputPaths = <String>[mainPath];
final Set<String> outputPaths = new Set<String>();
final String depfilePath = fs.path.join(outputDir.path, 'snapshot.d');
final List<String> genSnapshotArgs = <String>[
'--reify-generic-functions',
'--strong',
];
if (buildMode == BuildMode.debug) {
genSnapshotArgs.add('--enable_asserts');
}
if (extraGenSnapshotOptions != null && extraGenSnapshotOptions.isNotEmpty) {
printTrace('Extra gen_snapshot options: $extraGenSnapshotOptions');
genSnapshotArgs.addAll(extraGenSnapshotOptions);
}
// Blob Core JIT snapshot.
final String vmSnapshotData = fs.path.join(outputDir.path, 'vm_snapshot_data');
final String isolateSnapshotData = fs.path.join(outputDir.path, 'isolate_snapshot_data');
final String vmSnapshotInstructions = fs.path.join(outputDir.path, 'vm_snapshot_instr');
final String isolateSnapshotInstructions = fs.path.join(outputDir.path, 'isolate_snapshot_instr');
outputPaths.addAll(<String>[vmSnapshotData, isolateSnapshotData, vmSnapshotInstructions, isolateSnapshotInstructions]);
genSnapshotArgs.addAll(<String>[
'--snapshot_kind=core-jit',
'--vm_snapshot_data=$vmSnapshotData',
'--isolate_snapshot_data=$isolateSnapshotData',
'--vm_snapshot_instructions=$vmSnapshotInstructions',
'--isolate_snapshot_instructions=$isolateSnapshotInstructions',
'--load_compilation_trace=trace.txt',
]);
if (platform == TargetPlatform.android_arm) {
// Use softfp for Android armv7 devices.
// TODO(cbracken) eliminate this when we fix https://github.com/flutter/flutter/issues/17489
genSnapshotArgs.add('--no-sim-use-hardfp');
// Not supported by the Pixel in 32-bit mode.
genSnapshotArgs.add('--no-use-integer-division');
}
genSnapshotArgs.add(mainPath);
// Verify that all required inputs exist.
final Iterable<String> missingInputs = inputPaths.where((String p) => !fs.isFileSync(p));
if (missingInputs.isNotEmpty) {
printError('Missing input files: $missingInputs from $inputPaths');
return 1;
}
// If inputs and outputs have not changed since last run, skip the build.
final Fingerprinter fingerprinter = new Fingerprinter(
fingerprintPath: '$depfilePath.fingerprint',
paths: <String>[mainPath]..addAll(inputPaths)..addAll(outputPaths),
properties: <String, String>{
'buildMode': buildMode.toString(),
'targetPlatform': platform.toString(),
'entryPoint': mainPath,
'extraGenSnapshotOptions': extraGenSnapshotOptions.join(' '),
},
depfilePaths: <String>[depfilePath],
);
if (await fingerprinter.doesFingerprintMatch()) {
printTrace('Skipping Core JIT snapshot build. Fingerprint match.');
return 0;
}
final SnapshotType snapshotType = new SnapshotType(platform, buildMode);
final int genSnapshotExitCode = await genSnapshot.run(
snapshotType: snapshotType,
packagesPath: packagesPath,
depfilePath: depfilePath,
additionalArgs: genSnapshotArgs,
);
if (genSnapshotExitCode != 0) {
printError('Dart snapshot generator failed with exit code $genSnapshotExitCode');
return genSnapshotExitCode;
}
// Write path to gen_snapshot, since snapshots have to be re-generated when we roll
// the Dart SDK.
final String genSnapshotPath = GenSnapshot.getSnapshotterPath(snapshotType);
await outputDir.childFile('gen_snapshot.d').writeAsString('snapshot.d: $genSnapshotPath\n');
// Compute and record build fingerprint.
await fingerprinter.writeFingerprint();
return 0;
}
bool _isValidCoreJitPlatform(TargetPlatform platform) {
return const <TargetPlatform>[
TargetPlatform.android_arm,
TargetPlatform.android_arm64,
].contains(platform);
}
}
...@@ -13,6 +13,7 @@ class BuildInfo { ...@@ -13,6 +13,7 @@ class BuildInfo {
const BuildInfo(this.mode, this.flavor, { const BuildInfo(this.mode, this.flavor, {
this.previewDart2 = false, this.previewDart2 = false,
this.trackWidgetCreation = false, this.trackWidgetCreation = false,
this.buildSnapshot = false,
this.extraFrontEndOptions, this.extraFrontEndOptions,
this.extraGenSnapshotOptions, this.extraGenSnapshotOptions,
this.buildSharedLibrary, this.buildSharedLibrary,
...@@ -42,6 +43,9 @@ class BuildInfo { ...@@ -42,6 +43,9 @@ class BuildInfo {
/// Whether the build should track widget creation locations. /// Whether the build should track widget creation locations.
final bool trackWidgetCreation; final bool trackWidgetCreation;
/// Whether the build should create VM snapshot instead of using prebuilt one from engine.
final bool buildSnapshot;
/// Extra command-line options for front-end. /// Extra command-line options for front-end.
final String extraFrontEndOptions; final String extraFrontEndOptions;
...@@ -95,6 +99,7 @@ class BuildInfo { ...@@ -95,6 +99,7 @@ class BuildInfo {
new BuildInfo(mode, flavor, new BuildInfo(mode, flavor,
previewDart2: previewDart2, previewDart2: previewDart2,
trackWidgetCreation: trackWidgetCreation, trackWidgetCreation: trackWidgetCreation,
buildSnapshot: buildSnapshot,
extraFrontEndOptions: extraFrontEndOptions, extraFrontEndOptions: extraFrontEndOptions,
extraGenSnapshotOptions: extraGenSnapshotOptions, extraGenSnapshotOptions: extraGenSnapshotOptions,
buildSharedLibrary: buildSharedLibrary, buildSharedLibrary: buildSharedLibrary,
......
...@@ -26,11 +26,15 @@ const String defaultPrivateKeyPath = 'privatekey.der'; ...@@ -26,11 +26,15 @@ const String defaultPrivateKeyPath = 'privatekey.der';
const String _kKernelKey = 'kernel_blob.bin'; const String _kKernelKey = 'kernel_blob.bin';
const String _kSnapshotKey = 'snapshot_blob.bin'; const String _kSnapshotKey = 'snapshot_blob.bin';
const String _kVMSnapshotData = 'vm_snapshot_data'; const String _kVMSnapshotData = 'vm_snapshot_data';
const String _kVMSnapshotInstr = 'vm_snapshot_instr';
const String _kIsolateSnapshotData = 'isolate_snapshot_data'; const String _kIsolateSnapshotData = 'isolate_snapshot_data';
const String _kIsolateSnapshotInstr = 'isolate_snapshot_instr';
const String _kDylibKey = 'libapp.so'; const String _kDylibKey = 'libapp.so';
const String _kPlatformKernelKey = 'platform.dill'; const String _kPlatformKernelKey = 'platform.dill';
Future<void> build({ Future<void> build({
TargetPlatform platform,
BuildMode buildMode,
String mainPath = defaultMainPath, String mainPath = defaultMainPath,
String manifestPath = defaultManifestPath, String manifestPath = defaultManifestPath,
String snapshotPath, String snapshotPath,
...@@ -43,7 +47,9 @@ Future<void> build({ ...@@ -43,7 +47,9 @@ Future<void> build({
bool precompiledSnapshot = false, bool precompiledSnapshot = false,
bool reportLicensedPackages = false, bool reportLicensedPackages = false,
bool trackWidgetCreation = false, bool trackWidgetCreation = false,
bool buildSnapshot = false,
List<String> extraFrontEndOptions = const <String>[], List<String> extraFrontEndOptions = const <String>[],
List<String> extraGenSnapshotOptions = const <String>[],
List<String> fileSystemRoots, List<String> fileSystemRoots,
String fileSystemScheme, String fileSystemScheme,
}) async { }) async {
...@@ -78,7 +84,8 @@ Future<void> build({ ...@@ -78,7 +84,8 @@ Future<void> build({
ensureDirectoryExists(applicationKernelFilePath); ensureDirectoryExists(applicationKernelFilePath);
final CompilerOutput compilerOutput = await kernelCompiler.compile( final CompilerOutput compilerOutput = await kernelCompiler.compile(
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath), sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
incrementalCompilerByteStorePath: fs.path.absolute(getIncrementalCompilerByteStoreDirectory()), incrementalCompilerByteStorePath: buildSnapshot ? null :
fs.path.absolute(getIncrementalCompilerByteStoreDirectory()),
mainPath: fs.file(mainPath).absolute.path, mainPath: fs.file(mainPath).absolute.path,
outputFilePath: applicationKernelFilePath, outputFilePath: applicationKernelFilePath,
depFilePath: depfilePath, depFilePath: depfilePath,
...@@ -87,6 +94,7 @@ Future<void> build({ ...@@ -87,6 +94,7 @@ Future<void> build({
fileSystemRoots: fileSystemRoots, fileSystemRoots: fileSystemRoots,
fileSystemScheme: fileSystemScheme, fileSystemScheme: fileSystemScheme,
packagesPath: packagesPath, packagesPath: packagesPath,
linkPlatformKernelIn: buildSnapshot,
); );
if (compilerOutput?.outputFilename == null) { if (compilerOutput?.outputFilename == null) {
throwToolExit('Compiler failed on $mainPath'); throwToolExit('Compiler failed on $mainPath');
...@@ -95,6 +103,22 @@ Future<void> build({ ...@@ -95,6 +103,22 @@ Future<void> build({
await fs.directory(getBuildDirectory()).childFile('frontend_server.d') await fs.directory(getBuildDirectory()).childFile('frontend_server.d')
.writeAsString('frontend_server.d: ${artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk)}\n'); .writeAsString('frontend_server.d: ${artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk)}\n');
if (buildSnapshot) {
final CoreJITSnapshotter snapshotter = new CoreJITSnapshotter();
final int snapshotExitCode = await snapshotter.build(
platform: platform,
buildMode: buildMode,
mainPath: applicationKernelFilePath,
outputPath: getBuildDirectory(),
packagesPath: packagesPath,
extraGenSnapshotOptions: extraGenSnapshotOptions,
);
if (snapshotExitCode != 0) {
printError('Snapshotting exited with non-zero exit code: $snapshotExitCode');
return;
}
}
} }
final AssetBundle assets = await buildAssets( final AssetBundle assets = await buildAssets(
...@@ -112,6 +136,7 @@ Future<void> build({ ...@@ -112,6 +136,7 @@ Future<void> build({
snapshotFile: snapshotFile, snapshotFile: snapshotFile,
privateKeyPath: privateKeyPath, privateKeyPath: privateKeyPath,
assetDirPath: assetDirPath, assetDirPath: assetDirPath,
buildSnapshot: buildSnapshot,
); );
} }
...@@ -147,22 +172,35 @@ Future<void> assemble({ ...@@ -147,22 +172,35 @@ Future<void> assemble({
File dylibFile, File dylibFile,
String privateKeyPath = defaultPrivateKeyPath, String privateKeyPath = defaultPrivateKeyPath,
String assetDirPath, String assetDirPath,
bool buildSnapshot,
}) async { }) async {
assetDirPath ??= getAssetBuildDirectory(); assetDirPath ??= getAssetBuildDirectory();
printTrace('Building bundle'); printTrace('Building bundle');
final Map<String, DevFSContent> assetEntries = new Map<String, DevFSContent>.from(assetBundle.entries); final Map<String, DevFSContent> assetEntries = new Map<String, DevFSContent>.from(assetBundle.entries);
final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData);
final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData);
if (kernelContent != null) { if (kernelContent != null) {
if (buildSnapshot) {
final String vmSnapshotData = fs.path.join(getBuildDirectory(), _kVMSnapshotData);
final String vmSnapshotInstr = fs.path.join(getBuildDirectory(), _kVMSnapshotInstr);
final String isolateSnapshotData = fs.path.join(getBuildDirectory(), _kIsolateSnapshotData);
final String isolateSnapshotInstr = fs.path.join(getBuildDirectory(), _kIsolateSnapshotInstr);
assetEntries[_kVMSnapshotData] = new DevFSFileContent(fs.file(vmSnapshotData));
assetEntries[_kVMSnapshotInstr] = new DevFSFileContent(fs.file(vmSnapshotInstr));
assetEntries[_kIsolateSnapshotData] = new DevFSFileContent(fs.file(isolateSnapshotData));
assetEntries[_kIsolateSnapshotInstr] = new DevFSFileContent(fs.file(isolateSnapshotInstr));
} else {
final String platformKernelDill = artifacts.getArtifactPath(Artifact.platformKernelDill); final String platformKernelDill = artifacts.getArtifactPath(Artifact.platformKernelDill);
final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData);
final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData);
assetEntries[_kKernelKey] = kernelContent; assetEntries[_kKernelKey] = kernelContent;
assetEntries[_kPlatformKernelKey] = new DevFSFileContent(fs.file(platformKernelDill)); assetEntries[_kPlatformKernelKey] = new DevFSFileContent(fs.file(platformKernelDill));
assetEntries[_kVMSnapshotData] = new DevFSFileContent(fs.file(vmSnapshotData)); assetEntries[_kVMSnapshotData] = new DevFSFileContent(fs.file(vmSnapshotData));
assetEntries[_kIsolateSnapshotData] = new DevFSFileContent(fs.file(isolateSnapshotData)); assetEntries[_kIsolateSnapshotData] = new DevFSFileContent(fs.file(isolateSnapshotData));
} }
}
if (snapshotFile != null) { if (snapshotFile != null) {
final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData);
final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData);
assetEntries[_kSnapshotKey] = new DevFSFileContent(snapshotFile); assetEntries[_kSnapshotKey] = new DevFSFileContent(snapshotFile);
assetEntries[_kVMSnapshotData] = new DevFSFileContent(fs.file(vmSnapshotData)); assetEntries[_kVMSnapshotData] = new DevFSFileContent(fs.file(vmSnapshotData));
assetEntries[_kIsolateSnapshotData] = new DevFSFileContent(fs.file(isolateSnapshotData)); assetEntries[_kIsolateSnapshotData] = new DevFSFileContent(fs.file(isolateSnapshotData));
...@@ -190,5 +228,3 @@ Future<void> writeBundle( ...@@ -190,5 +228,3 @@ Future<void> writeBundle(
await file.writeAsBytes(await entry.value.contentsAsBytes()); await file.writeAsBytes(await entry.value.contentsAsBytes());
})); }));
} }
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'dart:async'; import 'dart:async';
import '../base/common.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../bundle.dart'; import '../bundle.dart';
import '../runner/flutter_command.dart' show FlutterOptions; import '../runner/flutter_command.dart' show FlutterOptions;
...@@ -12,6 +13,7 @@ import 'build.dart'; ...@@ -12,6 +13,7 @@ import 'build.dart';
class BuildBundleCommand extends BuildSubCommand { class BuildBundleCommand extends BuildSubCommand {
BuildBundleCommand({bool verboseHelp = false}) { BuildBundleCommand({bool verboseHelp = false}) {
usesTargetOption(); usesTargetOption();
addBuildModeFlags();
argParser argParser
..addFlag('precompiled', negatable: false) ..addFlag('precompiled', negatable: false)
// This option is still referenced by the iOS build scripts. We should // This option is still referenced by the iOS build scripts. We should
...@@ -27,14 +29,28 @@ class BuildBundleCommand extends BuildSubCommand { ...@@ -27,14 +29,28 @@ class BuildBundleCommand extends BuildSubCommand {
hide: !verboseHelp, hide: !verboseHelp,
help: 'Preview Dart 2.0 functionality.', help: 'Preview Dart 2.0 functionality.',
) )
..addOption('target-platform',
defaultsTo: 'android-arm',
allowed: <String>['android-arm', 'android-arm64', 'ios']
)
..addFlag('track-widget-creation', ..addFlag('track-widget-creation',
hide: !verboseHelp, hide: !verboseHelp,
help: 'Track widget creation locations. Requires Dart 2.0 functionality.', help: 'Track widget creation locations. Requires Dart 2.0 functionality.',
) )
..addFlag('build-snapshot',
hide: !verboseHelp,
defaultsTo: false,
help: 'Build and use application-specific VM snapshot instead of\n'
'prebuilt one provided by the engine.',
)
..addMultiOption(FlutterOptions.kExtraFrontEndOptions, ..addMultiOption(FlutterOptions.kExtraFrontEndOptions,
splitCommas: true, splitCommas: true,
hide: true, hide: true,
) )
..addMultiOption(FlutterOptions.kExtraGenSnapshotOptions,
splitCommas: true,
hide: true,
)
..addOption('asset-dir', defaultsTo: getAssetBuildDirectory()) ..addOption('asset-dir', defaultsTo: getAssetBuildDirectory())
..addFlag('report-licensed-packages', ..addFlag('report-licensed-packages',
help: 'Whether to report the names of all the packages that are included ' help: 'Whether to report the names of all the packages that are included '
...@@ -69,7 +85,16 @@ class BuildBundleCommand extends BuildSubCommand { ...@@ -69,7 +85,16 @@ class BuildBundleCommand extends BuildSubCommand {
Future<Null> runCommand() async { Future<Null> runCommand() async {
await super.runCommand(); await super.runCommand();
final String targetPlatform = argResults['target-platform'];
final TargetPlatform platform = getTargetPlatformForName(targetPlatform);
if (platform == null)
throwToolExit('Unknown platform: $targetPlatform');
final BuildMode buildMode = getBuildMode();
await build( await build(
platform: platform,
buildMode: buildMode,
mainPath: targetFile, mainPath: targetFile,
manifestPath: argResults['manifest'], manifestPath: argResults['manifest'],
snapshotPath: argResults['snapshot'], snapshotPath: argResults['snapshot'],
...@@ -81,7 +106,9 @@ class BuildBundleCommand extends BuildSubCommand { ...@@ -81,7 +106,9 @@ class BuildBundleCommand extends BuildSubCommand {
precompiledSnapshot: argResults['precompiled'], precompiledSnapshot: argResults['precompiled'],
reportLicensedPackages: argResults['report-licensed-packages'], reportLicensedPackages: argResults['report-licensed-packages'],
trackWidgetCreation: argResults['track-widget-creation'], trackWidgetCreation: argResults['track-widget-creation'],
buildSnapshot: argResults['build-snapshot'],
extraFrontEndOptions: argResults[FlutterOptions.kExtraFrontEndOptions], extraFrontEndOptions: argResults[FlutterOptions.kExtraFrontEndOptions],
extraGenSnapshotOptions: argResults[FlutterOptions.kExtraGenSnapshotOptions],
fileSystemScheme: argResults['filesystem-scheme'], fileSystemScheme: argResults['filesystem-scheme'],
fileSystemRoots: argResults['filesystem-root'], fileSystemRoots: argResults['filesystem-root'],
); );
......
...@@ -125,6 +125,12 @@ class RunCommand extends RunCommandBase { ...@@ -125,6 +125,12 @@ class RunCommand extends RunCommandBase {
hide: !verboseHelp, hide: !verboseHelp,
help: 'Preview Dart 2.0 functionality.', help: 'Preview Dart 2.0 functionality.',
) )
..addFlag('build-snapshot',
hide: !verboseHelp,
defaultsTo: false,
help: 'Build and use application-specific VM snapshot instead of\n'
'prebuilt one provided by the engine.',
)
..addFlag('track-widget-creation', ..addFlag('track-widget-creation',
hide: !verboseHelp, hide: !verboseHelp,
help: 'Track widget creation locations. Requires Dart 2.0 functionality.', help: 'Track widget creation locations. Requires Dart 2.0 functionality.',
......
...@@ -216,6 +216,9 @@ abstract class FlutterCommand extends Command<Null> { ...@@ -216,6 +216,9 @@ abstract class FlutterCommand extends Command<Null> {
: null, : null,
previewDart2: previewDart2, previewDart2: previewDart2,
trackWidgetCreation: trackWidgetCreation, trackWidgetCreation: trackWidgetCreation,
buildSnapshot: argParser.options.containsKey('build-snapshot')
? argResults['build-snapshot']
: false,
extraFrontEndOptions: argParser.options.containsKey(FlutterOptions.kExtraFrontEndOptions) extraFrontEndOptions: argParser.options.containsKey(FlutterOptions.kExtraFrontEndOptions)
? argResults[FlutterOptions.kExtraFrontEndOptions] ? argResults[FlutterOptions.kExtraFrontEndOptions]
: null, : null,
......
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