| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:async'; |
| |
| import 'artifacts.dart'; |
| import 'asset.dart'; |
| import 'base/common.dart'; |
| import 'base/file_system.dart'; |
| import 'base/process.dart'; |
| import 'build_info.dart'; |
| import 'dart/package_map.dart'; |
| import 'devfs.dart'; |
| import 'globals.dart'; |
| import 'zip.dart'; |
| |
| const String defaultMainPath = 'lib/main.dart'; |
| const String defaultAssetBasePath = '.'; |
| const String defaultManifestPath = 'pubspec.yaml'; |
| String get defaultFlxOutputPath => fs.path.join(getBuildDirectory(), 'app.flx'); |
| String get defaultSnapshotPath => fs.path.join(getBuildDirectory(), 'snapshot_blob.bin'); |
| String get defaultDepfilePath => fs.path.join(getBuildDirectory(), 'snapshot_blob.bin.d'); |
| String get defaultKernelPath => fs.path.join(getBuildDirectory(), 'kernel_blob.bin'); |
| const String defaultPrivateKeyPath = 'privatekey.der'; |
| |
| const String _kKernelKey = 'kernel_blob.bin'; |
| const String _kSnapshotKey = 'snapshot_blob.bin'; |
| |
| Future<int> createSnapshot({ |
| String mainPath, |
| String snapshotPath, |
| String depfilePath, |
| String packages |
| }) { |
| assert(mainPath != null); |
| assert(snapshotPath != null); |
| assert(packages != null); |
| final String snapshotterPath = artifacts.getArtifactPath(Artifact.genSnapshot, null, BuildMode.debug); |
| final String vmSnapshotData = artifacts.getArtifactPath(Artifact.vmSnapshotData); |
| final String isolateSnapshotData = artifacts.getArtifactPath(Artifact.isolateSnapshotData); |
| |
| final List<String> args = <String>[ |
| snapshotterPath, |
| '--snapshot_kind=script', |
| '--vm_snapshot_data=$vmSnapshotData', |
| '--isolate_snapshot_data=$isolateSnapshotData', |
| '--packages=$packages', |
| '--script_snapshot=$snapshotPath' |
| ]; |
| if (depfilePath != null) { |
| args.add('--dependencies=$depfilePath'); |
| fs.file(depfilePath).parent.childFile('gen_snapshot.d').writeAsString('$depfilePath: $snapshotterPath\n'); |
| } |
| args.add(mainPath); |
| return runCommandAndStreamOutput(args); |
| } |
| |
| /// Build the flx in the build directory and return `localBundlePath` on success. |
| /// |
| /// Return `null` on failure. |
| Future<String> buildFlx({ |
| String mainPath: defaultMainPath, |
| DevFSContent kernelContent, |
| bool precompiledSnapshot: false, |
| bool includeRobotoFonts: true |
| }) async { |
| await build( |
| snapshotPath: defaultSnapshotPath, |
| outputPath: defaultFlxOutputPath, |
| mainPath: mainPath, |
| kernelContent: kernelContent, |
| precompiledSnapshot: precompiledSnapshot, |
| includeRobotoFonts: includeRobotoFonts |
| ); |
| return defaultFlxOutputPath; |
| } |
| |
| Future<Null> build({ |
| String mainPath: defaultMainPath, |
| String manifestPath: defaultManifestPath, |
| String outputPath, |
| String snapshotPath, |
| String depfilePath, |
| String privateKeyPath: defaultPrivateKeyPath, |
| String workingDirPath, |
| String packagesPath, |
| String kernelPath, |
| DevFSContent kernelContent, |
| bool precompiledSnapshot: false, |
| bool includeRobotoFonts: true, |
| bool reportLicensedPackages: false |
| }) async { |
| outputPath ??= defaultFlxOutputPath; |
| kernelPath ??= defaultKernelPath; |
| snapshotPath ??= defaultSnapshotPath; |
| depfilePath ??= defaultDepfilePath; |
| workingDirPath ??= getAssetBuildDirectory(); |
| packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath); |
| File snapshotFile; |
| |
| File kernelFile; |
| if (kernelContent != null) { |
| // TODO(danrubel) in the future, call the VM to generate this file |
| kernelFile = fs.file(kernelPath); |
| final IOSink sink = kernelFile.openWrite(); |
| await sink.addStream(kernelContent.contentsAsStream()); |
| sink.close(); |
| } |
| if (!precompiledSnapshot) { |
| ensureDirectoryExists(snapshotPath); |
| |
| // In a precompiled snapshot, the instruction buffer contains script |
| // content equivalents |
| final int result = await createSnapshot( |
| mainPath: mainPath, |
| snapshotPath: snapshotPath, |
| depfilePath: depfilePath, |
| packages: packagesPath |
| ); |
| if (result != 0) |
| throwToolExit('Failed to run the Flutter compiler. Exit code: $result', exitCode: result); |
| |
| snapshotFile = fs.file(snapshotPath); |
| } |
| |
| return assemble( |
| manifestPath: manifestPath, |
| kernelFile: kernelFile, |
| snapshotFile: snapshotFile, |
| outputPath: outputPath, |
| privateKeyPath: privateKeyPath, |
| workingDirPath: workingDirPath, |
| packagesPath: packagesPath, |
| includeRobotoFonts: includeRobotoFonts, |
| reportLicensedPackages: reportLicensedPackages |
| ); |
| } |
| |
| Future<Null> assemble({ |
| String manifestPath, |
| File kernelFile, |
| File snapshotFile, |
| String outputPath, |
| String privateKeyPath: defaultPrivateKeyPath, |
| String workingDirPath, |
| String packagesPath, |
| bool includeDefaultFonts: true, |
| bool includeRobotoFonts: true, |
| bool reportLicensedPackages: false |
| }) async { |
| outputPath ??= defaultFlxOutputPath; |
| workingDirPath ??= getAssetBuildDirectory(); |
| packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath); |
| printTrace('Building $outputPath'); |
| |
| // Build the asset bundle. |
| final AssetBundle assetBundle = new AssetBundle(); |
| final int result = await assetBundle.build( |
| manifestPath: manifestPath, |
| workingDirPath: workingDirPath, |
| packagesPath: packagesPath, |
| includeDefaultFonts: includeDefaultFonts, |
| includeRobotoFonts: includeRobotoFonts, |
| reportLicensedPackages: reportLicensedPackages |
| ); |
| if (result != 0) |
| throwToolExit('Error building $outputPath: $result', exitCode: result); |
| |
| final ZipBuilder zipBuilder = new ZipBuilder(); |
| |
| // Add all entries from the asset bundle. |
| zipBuilder.entries.addAll(assetBundle.entries); |
| |
| if (kernelFile != null) |
| zipBuilder.entries[_kKernelKey] = new DevFSFileContent(kernelFile); |
| if (snapshotFile != null) |
| zipBuilder.entries[_kSnapshotKey] = new DevFSFileContent(snapshotFile); |
| |
| ensureDirectoryExists(outputPath); |
| |
| printTrace('Encoding zip file to $outputPath'); |
| await zipBuilder.createZip(fs.file(outputPath), fs.directory(workingDirPath)); |
| |
| printTrace('Built $outputPath.'); |
| } |