Unverified Commit 4b8efad9 authored by Dan Field's avatar Dan Field Committed by GitHub

Font subset in the tool (#49737)

parent a4093edb
...@@ -422,6 +422,7 @@ class CompileTest { ...@@ -422,6 +422,7 @@ class CompileTest {
case DeviceOperatingSystem.android: case DeviceOperatingSystem.android:
options.insert(0, 'apk'); options.insert(0, 'apk');
options.add('--target-platform=android-arm'); options.add('--target-platform=android-arm');
options.add('--tree-shake-icons');
watch.start(); watch.start();
await flutter('build', options: options); await flutter('build', options: options);
watch.stop(); watch.stop();
......
...@@ -62,6 +62,11 @@ ephemeral_dir="${SOURCE_ROOT}/Flutter/ephemeral" ...@@ -62,6 +62,11 @@ ephemeral_dir="${SOURCE_ROOT}/Flutter/ephemeral"
build_inputs_path="${ephemeral_dir}/FlutterInputs.xcfilelist" build_inputs_path="${ephemeral_dir}/FlutterInputs.xcfilelist"
build_outputs_path="${ephemeral_dir}/FlutterOutputs.xcfilelist" build_outputs_path="${ephemeral_dir}/FlutterOutputs.xcfilelist"
icon_tree_shaker_flag="false"
if [[ -n "$TREE_SHAKE_ICONS" ]]; then
icon_tree_shaker_flag="true"
fi
RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics \ RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics \
${verbose_flag} \ ${verbose_flag} \
${flutter_engine_flag} \ ${flutter_engine_flag} \
...@@ -70,6 +75,7 @@ RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics \ ...@@ -70,6 +75,7 @@ RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics \
-dTargetPlatform=darwin-x64 \ -dTargetPlatform=darwin-x64 \
-dTargetFile="${target_path}" \ -dTargetFile="${target_path}" \
-dBuildMode="${build_mode}" \ -dBuildMode="${build_mode}" \
-dFontSubset="${icon_tree_shaker_flag}" \
--build-inputs="${build_inputs_path}" \ --build-inputs="${build_inputs_path}" \
--build-outputs="${build_outputs_path}" \ --build-outputs="${build_outputs_path}" \
--output="${ephemeral_dir}" \ --output="${ephemeral_dir}" \
......
...@@ -603,6 +603,10 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -603,6 +603,10 @@ class FlutterPlugin implements Plugin<Project> {
if (project.hasProperty('extra-gen-snapshot-options')) { if (project.hasProperty('extra-gen-snapshot-options')) {
extraGenSnapshotOptionsValue = project.property('extra-gen-snapshot-options') extraGenSnapshotOptionsValue = project.property('extra-gen-snapshot-options')
} }
Boolean treeShakeIconsOptionsValue = false
if (project.hasProperty('tree-shake-icons')) {
treeShakeIconsOptionsValue = project.property('tree-shake-icons').toBoolean()
}
def targetPlatforms = getTargetPlatforms() def targetPlatforms = getTargetPlatforms()
def addFlutterDeps = { variant -> def addFlutterDeps = { variant ->
if (shouldSplitPerAbi()) { if (shouldSplitPerAbi()) {
...@@ -637,6 +641,7 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -637,6 +641,7 @@ class FlutterPlugin implements Plugin<Project> {
intermediateDir project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}/") intermediateDir project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}/")
extraFrontEndOptions extraFrontEndOptionsValue extraFrontEndOptions extraFrontEndOptionsValue
extraGenSnapshotOptions extraGenSnapshotOptionsValue extraGenSnapshotOptions extraGenSnapshotOptionsValue
treeShakeIcons treeShakeIconsOptionsValue
} }
File libJar = project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}/libs.jar") File libJar = project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}/libs.jar")
Task packFlutterAppAotTask = project.tasks.create(name: "packLibs${FLUTTER_BUILD_PREFIX}${variant.name.capitalize()}", type: Jar) { Task packFlutterAppAotTask = project.tasks.create(name: "packLibs${FLUTTER_BUILD_PREFIX}${variant.name.capitalize()}", type: Jar) {
...@@ -769,6 +774,8 @@ abstract class BaseFlutterTask extends DefaultTask { ...@@ -769,6 +774,8 @@ abstract class BaseFlutterTask extends DefaultTask {
String extraFrontEndOptions String extraFrontEndOptions
@Optional @Input @Optional @Input
String extraGenSnapshotOptions String extraGenSnapshotOptions
@Optional @Input
Boolean treeShakeIcons
@OutputFiles @OutputFiles
FileCollection getDependenciesFiles() { FileCollection getDependenciesFiles() {
...@@ -825,6 +832,9 @@ abstract class BaseFlutterTask extends DefaultTask { ...@@ -825,6 +832,9 @@ abstract class BaseFlutterTask extends DefaultTask {
if (extraFrontEndOptions != null) { if (extraFrontEndOptions != null) {
args "-dExtraFrontEndOptions=${extraFrontEndOptions}" args "-dExtraFrontEndOptions=${extraFrontEndOptions}"
} }
if (treeShakeIcons == true) {
args "-dTreeShakeIcons=true"
}
if (extraGenSnapshotOptions != null) { if (extraGenSnapshotOptions != null) {
args "--ExtraGenSnapshotOptions=${extraGenSnapshotOptions}" args "--ExtraGenSnapshotOptions=${extraGenSnapshotOptions}"
} }
......
...@@ -338,6 +338,9 @@ Future<void> buildGradleApp({ ...@@ -338,6 +338,9 @@ Future<void> buildGradleApp({
if (androidBuildInfo.fastStart) { if (androidBuildInfo.fastStart) {
command.add('-Pfast-start=true'); command.add('-Pfast-start=true');
} }
if (androidBuildInfo.buildInfo.treeShakeIcons) {
command.add('-Ptree-shake-icons=true');
}
command.add(assembleTask); command.add(assembleTask);
GradleHandledError detectedGradleError; GradleHandledError detectedGradleError;
...@@ -546,6 +549,9 @@ Future<void> buildGradleAar({ ...@@ -546,6 +549,9 @@ Future<void> buildGradleAar({
command.add('-Plocal-engine-repo=${localEngineRepo.path}'); command.add('-Plocal-engine-repo=${localEngineRepo.path}');
command.add('-Plocal-engine-build-mode=${androidBuildInfo.buildInfo.modeName}'); command.add('-Plocal-engine-build-mode=${androidBuildInfo.buildInfo.modeName}');
command.add('-Plocal-engine-out=${localEngineArtifacts.engineOutPath}'); command.add('-Plocal-engine-out=${localEngineArtifacts.engineOutPath}');
if (androidBuildInfo.buildInfo.treeShakeIcons) {
command.add('-Pfont-subset=true');
}
// Copy the local engine repo in the output directory. // Copy the local engine repo in the output directory.
try { try {
...@@ -738,10 +744,11 @@ Future<void> buildPluginsAsAar( ...@@ -738,10 +744,11 @@ Future<void> buildPluginsAsAar(
try { try {
await buildGradleAar( await buildGradleAar(
project: FlutterProject.fromDirectory(pluginDirectory), project: FlutterProject.fromDirectory(pluginDirectory),
androidBuildInfo: const AndroidBuildInfo( androidBuildInfo: AndroidBuildInfo(
BuildInfo( BuildInfo(
BuildMode.release, // Plugins are built as release. BuildMode.release, // Plugins are built as release.
null, // Plugins don't define flavors. null, // Plugins don't define flavors.
treeShakeIcons: androidBuildInfo.buildInfo.treeShakeIcons,
), ),
), ),
target: '', target: '',
......
...@@ -36,6 +36,7 @@ class AotBuilder { ...@@ -36,6 +36,7 @@ class AotBuilder {
List<String> extraFrontEndOptions, List<String> extraFrontEndOptions,
List<String> extraGenSnapshotOptions, List<String> extraGenSnapshotOptions,
@required List<String> dartDefines, @required List<String> dartDefines,
@required bool treeShakeIcons,
}) async { }) async {
if (platform == null) { if (platform == null) {
throwToolExit('No AOT build platform specified'); throwToolExit('No AOT build platform specified');
......
...@@ -367,7 +367,10 @@ class CachedArtifacts extends Artifacts { ...@@ -367,7 +367,10 @@ class CachedArtifacts extends Artifacts {
return _fileSystem.path.join(dartPackageDirectory.path, _artifactToFileName(artifact)); return _fileSystem.path.join(dartPackageDirectory.path, _artifactToFileName(artifact));
case Artifact.fontSubset: case Artifact.fontSubset:
case Artifact.constFinder: case Artifact.constFinder:
return _cache.getArtifactDirectory('font-subset').childFile(_artifactToFileName(artifact, platform, mode)).path; return _cache.getArtifactDirectory('engine')
.childDirectory(getNameForTargetPlatform(platform))
.childFile(_artifactToFileName(artifact, platform, mode))
.path;
default: default:
assert(false, 'Artifact $artifact not available for platform $platform.'); assert(false, 'Artifact $artifact not available for platform $platform.');
return null; return null;
......
...@@ -21,6 +21,8 @@ const AssetBundleFactory _kManifestFactory = _ManifestAssetBundleFactory(); ...@@ -21,6 +21,8 @@ const AssetBundleFactory _kManifestFactory = _ManifestAssetBundleFactory();
const String defaultManifestPath = 'pubspec.yaml'; const String defaultManifestPath = 'pubspec.yaml';
const String kFontManifestJson = 'FontManifest.json';
/// Injected factory class for spawning [AssetBundle] instances. /// Injected factory class for spawning [AssetBundle] instances.
abstract class AssetBundleFactory { abstract class AssetBundleFactory {
/// The singleton instance, pulled from the [AppContext]. /// The singleton instance, pulled from the [AppContext].
...@@ -71,7 +73,6 @@ class _ManifestAssetBundle implements AssetBundle { ...@@ -71,7 +73,6 @@ class _ManifestAssetBundle implements AssetBundle {
DateTime _lastBuildTimestamp; DateTime _lastBuildTimestamp;
static const String _assetManifestJson = 'AssetManifest.json'; static const String _assetManifestJson = 'AssetManifest.json';
static const String _fontManifestJson = 'FontManifest.json';
static const String _fontSetMaterial = 'material'; static const String _fontSetMaterial = 'material';
static const String _license = 'LICENSE'; static const String _license = 'LICENSE';
...@@ -242,7 +243,7 @@ class _ManifestAssetBundle implements AssetBundle { ...@@ -242,7 +243,7 @@ class _ManifestAssetBundle implements AssetBundle {
entries[_assetManifestJson] = _createAssetManifest(assetVariants); entries[_assetManifestJson] = _createAssetManifest(assetVariants);
entries[_fontManifestJson] = DevFSStringContent(json.encode(fonts)); entries[kFontManifestJson] = DevFSStringContent(json.encode(fonts));
// TODO(ianh): Only do the following line if we've changed packages or if our LICENSE file changed // TODO(ianh): Only do the following line if we've changed packages or if our LICENSE file changed
entries[_license] = _obtainLicenses(packageMap, assetBasePath, reportPackages: reportLicensedPackages); entries[_license] = _obtainLicenses(packageMap, assetBasePath, reportPackages: reportLicensedPackages);
......
...@@ -2,8 +2,11 @@ ...@@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:meta/meta.dart';
import 'base/context.dart'; import 'base/context.dart';
import 'base/utils.dart'; import 'base/utils.dart';
import 'build_system/targets/icon_tree_shaker.dart';
import 'globals.dart' as globals; import 'globals.dart' as globals;
/// Information about a build to be performed or used. /// Information about a build to be performed or used.
...@@ -18,10 +21,14 @@ class BuildInfo { ...@@ -18,10 +21,14 @@ class BuildInfo {
this.fileSystemScheme, this.fileSystemScheme,
this.buildNumber, this.buildNumber,
this.buildName, this.buildName,
@required this.treeShakeIcons,
}); });
final BuildMode mode; final BuildMode mode;
/// Whether the build should subdset icon fonts.
final bool treeShakeIcons;
/// Represents a custom Android product flavor or an Xcode scheme, null for /// Represents a custom Android product flavor or an Xcode scheme, null for
/// using the default. /// using the default.
/// ///
...@@ -55,10 +62,10 @@ class BuildInfo { ...@@ -55,10 +62,10 @@ class BuildInfo {
/// On Xcode builds it is used as CFBundleShortVersionString, /// On Xcode builds it is used as CFBundleShortVersionString,
final String buildName; final String buildName;
static const BuildInfo debug = BuildInfo(BuildMode.debug, null); static const BuildInfo debug = BuildInfo(BuildMode.debug, null, treeShakeIcons: false);
static const BuildInfo profile = BuildInfo(BuildMode.profile, null); static const BuildInfo profile = BuildInfo(BuildMode.profile, null, treeShakeIcons: kIconTreeShakerEnabledDefault);
static const BuildInfo jitRelease = BuildInfo(BuildMode.jitRelease, null); static const BuildInfo jitRelease = BuildInfo(BuildMode.jitRelease, null, treeShakeIcons: kIconTreeShakerEnabledDefault);
static const BuildInfo release = BuildInfo(BuildMode.release, null); static const BuildInfo release = BuildInfo(BuildMode.release, null, treeShakeIcons: kIconTreeShakerEnabledDefault);
/// Returns whether a debug build is requested. /// Returns whether a debug build is requested.
/// ///
......
...@@ -12,6 +12,7 @@ import '../depfile.dart'; ...@@ -12,6 +12,7 @@ import '../depfile.dart';
import '../exceptions.dart'; import '../exceptions.dart';
import 'assets.dart'; import 'assets.dart';
import 'dart.dart'; import 'dart.dart';
import 'icon_tree_shaker.dart';
/// Prepares the asset bundle in the format expected by flutter.gradle. /// Prepares the asset bundle in the format expected by flutter.gradle.
/// ///
...@@ -25,6 +26,7 @@ abstract class AndroidAssetBundle extends Target { ...@@ -25,6 +26,7 @@ abstract class AndroidAssetBundle extends Target {
@override @override
List<Source> get inputs => const <Source>[ List<Source> get inputs => const <Source>[
Source.pattern('{BUILD_DIR}/app.dill'), Source.pattern('{BUILD_DIR}/app.dill'),
...IconTreeShaker.inputs,
]; ];
@override @override
......
...@@ -12,6 +12,8 @@ import '../../plugins.dart'; ...@@ -12,6 +12,8 @@ import '../../plugins.dart';
import '../../project.dart'; import '../../project.dart';
import '../build_system.dart'; import '../build_system.dart';
import '../depfile.dart'; import '../depfile.dart';
import 'dart.dart';
import 'icon_tree_shaker.dart';
/// A helper function to copy an asset bundle into an [environment]'s output /// A helper function to copy an asset bundle into an [environment]'s output
/// directory. /// directory.
...@@ -31,6 +33,16 @@ Future<Depfile> copyAssets(Environment environment, Directory outputDirectory) a ...@@ -31,6 +33,16 @@ Future<Depfile> copyAssets(Environment environment, Directory outputDirectory) a
pubspecFile, pubspecFile,
]; ];
final List<File> outputs = <File>[]; final List<File> outputs = <File>[];
final IconTreeShaker iconTreeShaker = IconTreeShaker(
environment,
assetBundle.entries[kFontManifestJson] as DevFSStringContent,
processManager: globals.processManager,
logger: globals.logger,
fileSystem: globals.fs,
artifacts: globals.artifacts,
);
await Future.wait<void>( await Future.wait<void>(
assetBundle.entries.entries.map<Future<void>>((MapEntry<String, DevFSContent> entry) async { assetBundle.entries.entries.map<Future<void>>((MapEntry<String, DevFSContent> entry) async {
final PoolResource resource = await pool.request(); final PoolResource resource = await pool.request();
...@@ -46,7 +58,13 @@ Future<Depfile> copyAssets(Environment environment, Directory outputDirectory) a ...@@ -46,7 +58,13 @@ Future<Depfile> copyAssets(Environment environment, Directory outputDirectory) a
final DevFSContent content = entry.value; final DevFSContent content = entry.value;
if (content is DevFSFileContent && content.file is File) { if (content is DevFSFileContent && content.file is File) {
inputs.add(globals.fs.file(content.file.path)); inputs.add(globals.fs.file(content.file.path));
await (content.file as File).copy(file.path); if (!await iconTreeShaker.subsetFont(
inputPath: content.file.path,
outputPath: file.path,
relativePath: entry.key,
)) {
await (content.file as File).copy(file.path);
}
} else { } else {
await file.writeAsBytes(await entry.value.contentsAsBytes()); await file.writeAsBytes(await entry.value.contentsAsBytes());
} }
...@@ -65,11 +83,14 @@ class CopyAssets extends Target { ...@@ -65,11 +83,14 @@ class CopyAssets extends Target {
String get name => 'copy_assets'; String get name => 'copy_assets';
@override @override
List<Target> get dependencies => const <Target>[]; List<Target> get dependencies => const <Target>[
KernelSnapshot(),
];
@override @override
List<Source> get inputs => const <Source>[ List<Source> get inputs => const <Source>[
Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/assets.dart'), Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/assets.dart'),
...IconTreeShaker.inputs,
]; ];
@override @override
......
...@@ -14,6 +14,7 @@ import '../build_system.dart'; ...@@ -14,6 +14,7 @@ import '../build_system.dart';
import '../depfile.dart'; import '../depfile.dart';
import '../exceptions.dart'; import '../exceptions.dart';
import 'assets.dart'; import 'assets.dart';
import 'icon_tree_shaker.dart';
/// The define to pass a [BuildMode]. /// The define to pass a [BuildMode].
const String kBuildMode= 'BuildMode'; const String kBuildMode= 'BuildMode';
...@@ -75,6 +76,7 @@ class CopyFlutterBundle extends Target { ...@@ -75,6 +76,7 @@ class CopyFlutterBundle extends Target {
Source.artifact(Artifact.vmSnapshotData, mode: BuildMode.debug), Source.artifact(Artifact.vmSnapshotData, mode: BuildMode.debug),
Source.artifact(Artifact.isolateSnapshotData, mode: BuildMode.debug), Source.artifact(Artifact.isolateSnapshotData, mode: BuildMode.debug),
Source.pattern('{BUILD_DIR}/app.dill'), Source.pattern('{BUILD_DIR}/app.dill'),
...IconTreeShaker.inputs,
]; ];
@override @override
......
...@@ -11,6 +11,7 @@ import '../depfile.dart'; ...@@ -11,6 +11,7 @@ import '../depfile.dart';
import '../exceptions.dart'; import '../exceptions.dart';
import 'assets.dart'; import 'assets.dart';
import 'dart.dart'; import 'dart.dart';
import 'icon_tree_shaker.dart';
/// The only files/subdirectories we care out. /// The only files/subdirectories we care out.
const List<String> _kLinuxArtifacts = <String>[ const List<String> _kLinuxArtifacts = <String>[
...@@ -119,6 +120,7 @@ class DebugBundleLinuxAssets extends Target { ...@@ -119,6 +120,7 @@ class DebugBundleLinuxAssets extends Target {
Source.pattern('{BUILD_DIR}/app.dill'), Source.pattern('{BUILD_DIR}/app.dill'),
Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/linux.dart'), Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/linux.dart'),
Source.pattern('{PROJECT_DIR}/pubspec.yaml'), Source.pattern('{PROJECT_DIR}/pubspec.yaml'),
...IconTreeShaker.inputs,
]; ];
@override @override
......
...@@ -14,6 +14,7 @@ import '../depfile.dart'; ...@@ -14,6 +14,7 @@ import '../depfile.dart';
import '../exceptions.dart'; import '../exceptions.dart';
import 'assets.dart'; import 'assets.dart';
import 'dart.dart'; import 'dart.dart';
import 'icon_tree_shaker.dart';
const String _kOutputPrefix = '{OUTPUT_DIR}/FlutterMacOS.framework'; const String _kOutputPrefix = '{OUTPUT_DIR}/FlutterMacOS.framework';
...@@ -243,6 +244,7 @@ abstract class MacOSBundleFlutterAssets extends Target { ...@@ -243,6 +244,7 @@ abstract class MacOSBundleFlutterAssets extends Target {
@override @override
List<Source> get inputs => const <Source>[ List<Source> get inputs => const <Source>[
Source.pattern('{BUILD_DIR}/App.framework/App'), Source.pattern('{BUILD_DIR}/App.framework/App'),
...IconTreeShaker.inputs,
]; ];
@override @override
......
...@@ -15,6 +15,7 @@ import 'build_info.dart'; ...@@ -15,6 +15,7 @@ import 'build_info.dart';
import 'build_system/build_system.dart'; import 'build_system/build_system.dart';
import 'build_system/depfile.dart'; import 'build_system/depfile.dart';
import 'build_system/targets/dart.dart'; import 'build_system/targets/dart.dart';
import 'build_system/targets/icon_tree_shaker.dart';
import 'cache.dart'; import 'cache.dart';
import 'dart/package_map.dart'; import 'dart/package_map.dart';
import 'devfs.dart'; import 'devfs.dart';
...@@ -68,6 +69,7 @@ class BundleBuilder { ...@@ -68,6 +69,7 @@ class BundleBuilder {
List<String> extraGenSnapshotOptions = const <String>[], List<String> extraGenSnapshotOptions = const <String>[],
List<String> fileSystemRoots, List<String> fileSystemRoots,
String fileSystemScheme, String fileSystemScheme,
@required bool treeShakeIcons,
}) async { }) async {
mainPath ??= defaultMainPath; mainPath ??= defaultMainPath;
depfilePath ??= defaultDepfilePath; depfilePath ??= defaultDepfilePath;
...@@ -83,6 +85,7 @@ class BundleBuilder { ...@@ -83,6 +85,7 @@ class BundleBuilder {
depfilePath: depfilePath, depfilePath: depfilePath,
precompiled: precompiledSnapshot, precompiled: precompiledSnapshot,
trackWidgetCreation: trackWidgetCreation, trackWidgetCreation: trackWidgetCreation,
treeShakeIcons: treeShakeIcons,
); );
// Work around for flutter_tester placing kernel artifacts in odd places. // Work around for flutter_tester placing kernel artifacts in odd places.
if (applicationKernelFilePath != null) { if (applicationKernelFilePath != null) {
...@@ -107,6 +110,7 @@ Future<void> buildWithAssemble({ ...@@ -107,6 +110,7 @@ Future<void> buildWithAssemble({
@required String depfilePath, @required String depfilePath,
@required bool precompiled, @required bool precompiled,
bool trackWidgetCreation, bool trackWidgetCreation,
@required bool treeShakeIcons,
}) async { }) async {
// If the precompiled flag was not passed, force us into debug mode. // If the precompiled flag was not passed, force us into debug mode.
buildMode = precompiled ? buildMode : BuildMode.debug; buildMode = precompiled ? buildMode : BuildMode.debug;
...@@ -121,6 +125,7 @@ Future<void> buildWithAssemble({ ...@@ -121,6 +125,7 @@ Future<void> buildWithAssemble({
kBuildMode: getNameForBuildMode(buildMode), kBuildMode: getNameForBuildMode(buildMode),
kTargetPlatform: getNameForTargetPlatform(targetPlatform), kTargetPlatform: getNameForTargetPlatform(targetPlatform),
kTrackWidgetCreation: trackWidgetCreation?.toString(), kTrackWidgetCreation: trackWidgetCreation?.toString(),
kIconTreeShakerFlag: treeShakeIcons ? 'true' : null,
}, },
); );
final Target target = buildMode == BuildMode.debug final Target target = buildMode == BuildMode.debug
......
...@@ -34,6 +34,7 @@ class BuildAarCommand extends BuildSubCommand { ...@@ -34,6 +34,7 @@ class BuildAarCommand extends BuildSubCommand {
defaultsTo: true, defaultsTo: true,
help: 'Build a release version of the current project.', help: 'Build a release version of the current project.',
); );
addTreeShakeIconsFlag();
usesFlavorOption(); usesFlavorOption();
usesBuildNumberOption(); usesBuildNumberOption();
usesPubOption(); usesPubOption();
...@@ -104,7 +105,7 @@ class BuildAarCommand extends BuildSubCommand { ...@@ -104,7 +105,7 @@ class BuildAarCommand extends BuildSubCommand {
for (final String buildMode in const <String>['debug', 'profile', 'release']) { for (final String buildMode in const <String>['debug', 'profile', 'release']) {
if (boolArg(buildMode)) { if (boolArg(buildMode)) {
androidBuildInfo.add(AndroidBuildInfo( androidBuildInfo.add(AndroidBuildInfo(
BuildInfo(BuildMode.fromName(buildMode), stringArg('flavor')), BuildInfo(BuildMode.fromName(buildMode), stringArg('flavor'), treeShakeIcons: boolArg('tree-shake-icons')),
targetArchs: targetArchitectures, targetArchs: targetArchitectures,
)); ));
} }
......
...@@ -15,6 +15,7 @@ import 'build.dart'; ...@@ -15,6 +15,7 @@ import 'build.dart';
/// Builds AOT snapshots into platform specific library containers. /// Builds AOT snapshots into platform specific library containers.
class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmentArtifacts { class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmentArtifacts {
BuildAotCommand({bool verboseHelp = false, this.aotBuilder}) { BuildAotCommand({bool verboseHelp = false, this.aotBuilder}) {
addTreeShakeIconsFlag();
usesTargetOption(); usesTargetOption();
addBuildModeFlags(); addBuildModeFlags();
usesPubOption(); usesPubOption();
...@@ -88,6 +89,7 @@ class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmen ...@@ -88,6 +89,7 @@ class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmen
extraFrontEndOptions: stringsArg(FlutterOptions.kExtraFrontEndOptions), extraFrontEndOptions: stringsArg(FlutterOptions.kExtraFrontEndOptions),
extraGenSnapshotOptions: stringsArg(FlutterOptions.kExtraGenSnapshotOptions), extraGenSnapshotOptions: stringsArg(FlutterOptions.kExtraGenSnapshotOptions),
dartDefines: dartDefines, dartDefines: dartDefines,
treeShakeIcons: boolArg('tree-shake-icons'),
); );
return FlutterCommandResult.success(); return FlutterCommandResult.success();
} }
......
...@@ -18,6 +18,7 @@ import 'build.dart'; ...@@ -18,6 +18,7 @@ import 'build.dart';
class BuildApkCommand extends BuildSubCommand { class BuildApkCommand extends BuildSubCommand {
BuildApkCommand({bool verboseHelp = false}) { BuildApkCommand({bool verboseHelp = false}) {
addTreeShakeIconsFlag();
usesTargetOption(); usesTargetOption();
addBuildModeFlags(verboseHelp: verboseHelp); addBuildModeFlags(verboseHelp: verboseHelp);
usesFlavorOption(); usesFlavorOption();
...@@ -25,7 +26,6 @@ class BuildApkCommand extends BuildSubCommand { ...@@ -25,7 +26,6 @@ class BuildApkCommand extends BuildSubCommand {
usesBuildNumberOption(); usesBuildNumberOption();
usesBuildNameOption(); usesBuildNameOption();
addShrinkingFlag(); addShrinkingFlag();
argParser argParser
..addFlag('split-per-abi', ..addFlag('split-per-abi',
negatable: false, negatable: false,
......
...@@ -16,6 +16,7 @@ import 'build.dart'; ...@@ -16,6 +16,7 @@ import 'build.dart';
class BuildAppBundleCommand extends BuildSubCommand { class BuildAppBundleCommand extends BuildSubCommand {
BuildAppBundleCommand({bool verboseHelp = false}) { BuildAppBundleCommand({bool verboseHelp = false}) {
addTreeShakeIconsFlag();
usesTargetOption(); usesTargetOption();
addBuildModeFlags(); addBuildModeFlags();
usesFlavorOption(); usesFlavorOption();
......
...@@ -16,6 +16,7 @@ import 'build.dart'; ...@@ -16,6 +16,7 @@ import 'build.dart';
class BuildBundleCommand extends BuildSubCommand { class BuildBundleCommand extends BuildSubCommand {
BuildBundleCommand({bool verboseHelp = false, this.bundleBuilder}) { BuildBundleCommand({bool verboseHelp = false, this.bundleBuilder}) {
addTreeShakeIconsFlag();
usesTargetOption(); usesTargetOption();
usesFilesystemOptions(hide: !verboseHelp); usesFilesystemOptions(hide: !verboseHelp);
usesBuildNumberOption(); usesBuildNumberOption();
...@@ -138,6 +139,7 @@ class BuildBundleCommand extends BuildSubCommand { ...@@ -138,6 +139,7 @@ class BuildBundleCommand extends BuildSubCommand {
extraGenSnapshotOptions: stringsArg(FlutterOptions.kExtraGenSnapshotOptions), extraGenSnapshotOptions: stringsArg(FlutterOptions.kExtraGenSnapshotOptions),
fileSystemScheme: stringArg('filesystem-scheme'), fileSystemScheme: stringArg('filesystem-scheme'),
fileSystemRoots: stringsArg('filesystem-root'), fileSystemRoots: stringsArg('filesystem-root'),
treeShakeIcons: boolArg('tree-shake-icons'),
); );
return FlutterCommandResult.success(); return FlutterCommandResult.success();
} }
......
...@@ -17,6 +17,7 @@ import 'build.dart'; ...@@ -17,6 +17,7 @@ import 'build.dart';
/// A command to build a Fuchsia target. /// A command to build a Fuchsia target.
class BuildFuchsiaCommand extends BuildSubCommand { class BuildFuchsiaCommand extends BuildSubCommand {
BuildFuchsiaCommand({bool verboseHelp = false}) { BuildFuchsiaCommand({bool verboseHelp = false}) {
addTreeShakeIconsFlag();
usesTargetOption(); usesTargetOption();
addBuildModeFlags(verboseHelp: verboseHelp); addBuildModeFlags(verboseHelp: verboseHelp);
argParser.addOption( argParser.addOption(
......
...@@ -18,6 +18,7 @@ import 'build.dart'; ...@@ -18,6 +18,7 @@ import 'build.dart';
/// .ipas, see https://flutter.dev/docs/deployment/ios. /// .ipas, see https://flutter.dev/docs/deployment/ios.
class BuildIOSCommand extends BuildSubCommand { class BuildIOSCommand extends BuildSubCommand {
BuildIOSCommand() { BuildIOSCommand() {
addTreeShakeIconsFlag();
addBuildModeFlags(defaultToRelease: false); addBuildModeFlags(defaultToRelease: false);
usesTargetOption(); usesTargetOption();
usesFlavorOption(); usesFlavorOption();
......
...@@ -44,6 +44,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -44,6 +44,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
_bundleBuilder = bundleBuilder, _bundleBuilder = bundleBuilder,
_cache = cache, _cache = cache,
_platform = platform { _platform = platform {
addTreeShakeIconsFlag();
usesTargetOption(); usesTargetOption();
usesFlavorOption(); usesFlavorOption();
usesPubOption(); usesPubOption();
...@@ -361,6 +362,7 @@ end ...@@ -361,6 +362,7 @@ end
mainPath: globals.fs.path.absolute(targetFile), mainPath: globals.fs.path.absolute(targetFile),
assetDirPath: destinationAppFrameworkDirectory.childDirectory('flutter_assets').path, assetDirPath: destinationAppFrameworkDirectory.childDirectory('flutter_assets').path,
precompiledSnapshot: mode != BuildMode.debug, precompiledSnapshot: mode != BuildMode.debug,
treeShakeIcons: boolArg('tree-shake-icons')
); );
} finally { } finally {
status.stop(); status.stop();
...@@ -426,6 +428,7 @@ end ...@@ -426,6 +428,7 @@ end
reportTimings: false, reportTimings: false,
iosBuildArchs: <DarwinArch>[DarwinArch.armv7, DarwinArch.arm64], iosBuildArchs: <DarwinArch>[DarwinArch.armv7, DarwinArch.arm64],
dartDefines: dartDefines, dartDefines: dartDefines,
treeShakeIcons: boolArg('tree-shake-icons'),
); );
} finally { } finally {
status.stop(); status.stop();
......
...@@ -17,6 +17,7 @@ import 'build.dart'; ...@@ -17,6 +17,7 @@ import 'build.dart';
/// A command to build a linux desktop target through a build shell script. /// A command to build a linux desktop target through a build shell script.
class BuildLinuxCommand extends BuildSubCommand { class BuildLinuxCommand extends BuildSubCommand {
BuildLinuxCommand() { BuildLinuxCommand() {
addTreeShakeIconsFlag();
addBuildModeFlags(); addBuildModeFlags();
usesTargetOption(); usesTargetOption();
} }
......
...@@ -17,6 +17,7 @@ import 'build.dart'; ...@@ -17,6 +17,7 @@ import 'build.dart';
/// A command to build a macOS desktop target through a build shell script. /// A command to build a macOS desktop target through a build shell script.
class BuildMacosCommand extends BuildSubCommand { class BuildMacosCommand extends BuildSubCommand {
BuildMacosCommand() { BuildMacosCommand() {
addTreeShakeIconsFlag();
usesTargetOption(); usesTargetOption();
addBuildModeFlags(); addBuildModeFlags();
} }
......
...@@ -15,6 +15,7 @@ import 'build.dart'; ...@@ -15,6 +15,7 @@ import 'build.dart';
class BuildWebCommand extends BuildSubCommand { class BuildWebCommand extends BuildSubCommand {
BuildWebCommand() { BuildWebCommand() {
addTreeShakeIconsFlag();
usesTargetOption(); usesTargetOption();
usesPubOption(); usesPubOption();
addBuildModeFlags(excludeDebug: true); addBuildModeFlags(excludeDebug: true);
......
...@@ -17,6 +17,7 @@ import 'build.dart'; ...@@ -17,6 +17,7 @@ import 'build.dart';
/// A command to build a windows desktop target through a build shell script. /// A command to build a windows desktop target through a build shell script.
class BuildWindowsCommand extends BuildSubCommand { class BuildWindowsCommand extends BuildSubCommand {
BuildWindowsCommand() { BuildWindowsCommand() {
addTreeShakeIconsFlag();
addBuildModeFlags(); addBuildModeFlags();
usesTargetOption(); usesTargetOption();
} }
......
...@@ -209,7 +209,6 @@ Future<XcodeBuildResult> buildXcodeProject({ ...@@ -209,7 +209,6 @@ Future<XcodeBuildResult> buildXcodeProject({
bool buildForDevice, bool buildForDevice,
DarwinArch activeArch, DarwinArch activeArch,
bool codesign = true, bool codesign = true,
}) async { }) async {
if (!upgradePbxProjWithFlutterAssets(app.project)) { if (!upgradePbxProjWithFlutterAssets(app.project)) {
return XcodeBuildResult(success: false); return XcodeBuildResult(success: false);
......
...@@ -428,7 +428,8 @@ class IOSSimulator extends Device { ...@@ -428,7 +428,8 @@ class IOSSimulator extends Device {
final BuildInfo debugBuildInfo = BuildInfo(BuildMode.debug, buildInfo.flavor, final BuildInfo debugBuildInfo = BuildInfo(BuildMode.debug, buildInfo.flavor,
trackWidgetCreation: buildInfo.trackWidgetCreation, trackWidgetCreation: buildInfo.trackWidgetCreation,
extraFrontEndOptions: buildInfo.extraFrontEndOptions, extraFrontEndOptions: buildInfo.extraFrontEndOptions,
extraGenSnapshotOptions: buildInfo.extraGenSnapshotOptions); extraGenSnapshotOptions: buildInfo.extraGenSnapshotOptions,
treeShakeIcons: buildInfo.treeShakeIcons);
final XcodeBuildResult buildResult = await buildXcodeProject( final XcodeBuildResult buildResult = await buildXcodeProject(
app: app, app: app,
...@@ -460,6 +461,7 @@ class IOSSimulator extends Device { ...@@ -460,6 +461,7 @@ class IOSSimulator extends Device {
precompiledSnapshot: false, precompiledSnapshot: false,
buildMode: buildInfo.mode, buildMode: buildInfo.mode,
trackWidgetCreation: buildInfo.trackWidgetCreation, trackWidgetCreation: buildInfo.trackWidgetCreation,
treeShakeIcons: false,
); );
} }
......
...@@ -216,6 +216,10 @@ List<String> _xcodeBuildSettingsLines({ ...@@ -216,6 +216,10 @@ List<String> _xcodeBuildSettingsLines({
xcodeBuildSettings.add('TRACK_WIDGET_CREATION=true'); xcodeBuildSettings.add('TRACK_WIDGET_CREATION=true');
} }
if (buildInfo.treeShakeIcons) {
xcodeBuildSettings.add('TREE_SHAKE_ICONS=true');
}
return xcodeBuildSettings; return xcodeBuildSettings;
} }
......
...@@ -85,6 +85,8 @@ Future<void> buildMacOS({ ...@@ -85,6 +85,8 @@ Future<void> buildMacOS({
'OBJROOT=${globals.fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Intermediates.noindex')}', 'OBJROOT=${globals.fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Intermediates.noindex')}',
'SYMROOT=${globals.fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Products')}', 'SYMROOT=${globals.fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Products')}',
'COMPILER_INDEX_STORE_ENABLE=NO', 'COMPILER_INDEX_STORE_ENABLE=NO',
if (buildInfo.treeShakeIcons)
'TREE_SHAKE_ICONS=true',
...environmentVariablesAsXcodeBuildSettings(globals.platform) ...environmentVariablesAsXcodeBuildSettings(globals.platform)
], trace: true); ], trace: true);
} finally { } finally {
......
...@@ -20,6 +20,7 @@ import '../base/time.dart'; ...@@ -20,6 +20,7 @@ import '../base/time.dart';
import '../base/user_messages.dart'; import '../base/user_messages.dart';
import '../base/utils.dart'; import '../base/utils.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../build_system/targets/icon_tree_shaker.dart' show kIconTreeShakerEnabledDefault;
import '../bundle.dart' as bundle; import '../bundle.dart' as bundle;
import '../cache.dart'; import '../cache.dart';
import '../dart/package_map.dart'; import '../dart/package_map.dart';
...@@ -365,6 +366,14 @@ abstract class FlutterCommand extends Command<void> { ...@@ -365,6 +366,14 @@ abstract class FlutterCommand extends Command<void> {
help: 'Build a JIT release version of your app${defaultToRelease ? ' (default mode)' : ''}.'); help: 'Build a JIT release version of your app${defaultToRelease ? ' (default mode)' : ''}.');
} }
void addTreeShakeIconsFlag() {
argParser.addFlag('tree-shake-icons',
negatable: true,
defaultsTo: kIconTreeShakerEnabledDefault,
help: 'Tree shake icon fonts so that only glyphs used by the application remain.',
);
}
void addShrinkingFlag() { void addShrinkingFlag() {
argParser.addFlag('shrink', argParser.addFlag('shrink',
negatable: true, negatable: true,
...@@ -490,6 +499,9 @@ abstract class FlutterCommand extends Command<void> { ...@@ -490,6 +499,9 @@ abstract class FlutterCommand extends Command<void> {
buildName: argParser.options.containsKey('build-name') buildName: argParser.options.containsKey('build-name')
? stringArg('build-name') ? stringArg('build-name')
: null, : null,
treeShakeIcons: argParser.options.containsKey('tree-shake-icons')
? boolArg('tree-shake-icons')
: kIconTreeShakerEnabledDefault,
); );
} }
......
...@@ -151,6 +151,7 @@ class FlutterTesterDevice extends Device { ...@@ -151,6 +151,7 @@ class FlutterTesterDevice extends Device {
precompiledSnapshot: false, precompiledSnapshot: false,
trackWidgetCreation: buildInfo.trackWidgetCreation, trackWidgetCreation: buildInfo.trackWidgetCreation,
platform: getTargetPlatformForName(getNameForHostPlatform(getCurrentHostPlatform())), platform: getTargetPlatformForName(getNameForHostPlatform(getCurrentHostPlatform())),
treeShakeIcons: buildInfo.treeShakeIcons,
); );
command.add('--flutter-assets-dir=$assetDirPath'); command.add('--flutter-assets-dir=$assetDirPath');
......
...@@ -52,6 +52,8 @@ Future<void> buildWeb( ...@@ -52,6 +52,8 @@ Future<void> buildWeb(
kHasWebPlugins: hasWebPlugins.toString(), kHasWebPlugins: hasWebPlugins.toString(),
kDartDefines: jsonEncode(dartDefines), kDartDefines: jsonEncode(dartDefines),
kCspMode: csp.toString(), kCspMode: csp.toString(),
// TODO(dnfield): Enable font subset. We need to get a kernel file to do
// that. https://github.com/flutter/flutter/issues/49730
}, },
)); ));
if (!result.success) { if (!result.success) {
......
...@@ -5,7 +5,7 @@ author: Flutter Authors <flutter-dev@googlegroups.com> ...@@ -5,7 +5,7 @@ author: Flutter Authors <flutter-dev@googlegroups.com>
environment: environment:
# The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite. # The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite.
sdk: ">=2.2.2 <3.0.0" sdk: ">=2.7.0 <3.0.0"
dependencies: dependencies:
# To update these, use "flutter update-packages --force-upgrade". # To update these, use "flutter update-packages --force-upgrade".
......
...@@ -7,6 +7,7 @@ import 'package:file/memory.dart'; ...@@ -7,6 +7,7 @@ import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/targets/dart.dart'; import 'package:flutter_tools/src/build_system/targets/dart.dart';
import 'package:flutter_tools/src/build_system/targets/icon_tree_shaker.dart';
import 'package:flutter_tools/src/bundle.dart'; import 'package:flutter_tools/src/bundle.dart';
import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/build_bundle.dart'; import 'package:flutter_tools/src/commands/build_bundle.dart';
...@@ -47,6 +48,7 @@ void main() { ...@@ -47,6 +48,7 @@ void main() {
extraGenSnapshotOptions: anyNamed('extraGenSnapshotOptions'), extraGenSnapshotOptions: anyNamed('extraGenSnapshotOptions'),
fileSystemRoots: anyNamed('fileSystemRoots'), fileSystemRoots: anyNamed('fileSystemRoots'),
fileSystemScheme: anyNamed('fileSystemScheme'), fileSystemScheme: anyNamed('fileSystemScheme'),
treeShakeIcons: anyNamed('treeShakeIcons'),
), ),
).thenAnswer((_) => Future<void>.value()); ).thenAnswer((_) => Future<void>.value());
}); });
...@@ -217,6 +219,7 @@ void main() { ...@@ -217,6 +219,7 @@ void main() {
kBuildMode: 'debug', kBuildMode: 'debug',
kTargetPlatform: 'android-arm', kTargetPlatform: 'android-arm',
kTrackWidgetCreation: 'true', kTrackWidgetCreation: 'true',
kIconTreeShakerFlag: null,
}); });
return BuildResult(success: true); return BuildResult(success: true);
......
...@@ -101,7 +101,7 @@ void main() { ...@@ -101,7 +101,7 @@ void main() {
mockApk, mockApk,
prebuiltApplication: true, prebuiltApplication: true,
debuggingOptions: DebuggingOptions.disabled( debuggingOptions: DebuggingOptions.disabled(
const BuildInfo(BuildMode.release, null), const BuildInfo(BuildMode.release, null, treeShakeIcons: false),
cacheSkSL: true, cacheSkSL: true,
), ),
platformArgs: <String, dynamic>{}, platformArgs: <String, dynamic>{},
...@@ -153,7 +153,7 @@ void main() { ...@@ -153,7 +153,7 @@ void main() {
mockApk, mockApk,
prebuiltApplication: true, prebuiltApplication: true,
debuggingOptions: DebuggingOptions.disabled( debuggingOptions: DebuggingOptions.disabled(
const BuildInfo(BuildMode.release, null), const BuildInfo(BuildMode.release, null, treeShakeIcons: false),
), ),
platformArgs: <String, dynamic>{}, platformArgs: <String, dynamic>{},
); );
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io';
import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/targets/assets.dart'; import 'package:flutter_tools/src/build_system/targets/assets.dart';
import 'package:flutter_tools/src/globals.dart' as globals; import 'package:flutter_tools/src/globals.dart' as globals;
...@@ -12,7 +10,6 @@ import '../../../src/common.dart'; ...@@ -12,7 +10,6 @@ import '../../../src/common.dart';
import '../../../src/testbed.dart'; import '../../../src/testbed.dart';
void main() { void main() {
const BuildSystem buildSystem = BuildSystem();
Environment environment; Environment environment;
Testbed testbed; Testbed testbed;
...@@ -21,6 +18,7 @@ void main() { ...@@ -21,6 +18,7 @@ void main() {
environment = Environment.test( environment = Environment.test(
globals.fs.currentDirectory, globals.fs.currentDirectory,
); );
globals.fs.file(environment.buildDir.childFile('app.dill')).createSync(recursive: true);
globals.fs.file(globals.fs.path.join('packages', 'flutter_tools', 'lib', 'src', globals.fs.file(globals.fs.path.join('packages', 'flutter_tools', 'lib', 'src',
'build_system', 'targets', 'assets.dart')) 'build_system', 'targets', 'assets.dart'))
..createSync(recursive: true); ..createSync(recursive: true);
...@@ -44,7 +42,7 @@ flutter: ...@@ -44,7 +42,7 @@ flutter:
}); });
test('Copies files to correct asset directory', () => testbed.run(() async { test('Copies files to correct asset directory', () => testbed.run(() async {
await buildSystem.build(const CopyAssets(), environment); await const CopyAssets().build(environment);
expect(globals.fs.file(globals.fs.path.join(environment.buildDir.path, 'flutter_assets', 'AssetManifest.json')).existsSync(), true); expect(globals.fs.file(globals.fs.path.join(environment.buildDir.path, 'flutter_assets', 'AssetManifest.json')).existsSync(), true);
expect(globals.fs.file(globals.fs.path.join(environment.buildDir.path, 'flutter_assets', 'FontManifest.json')).existsSync(), true); expect(globals.fs.file(globals.fs.path.join(environment.buildDir.path, 'flutter_assets', 'FontManifest.json')).existsSync(), true);
...@@ -55,24 +53,6 @@ flutter: ...@@ -55,24 +53,6 @@ flutter:
expect(globals.fs.file(globals.fs.path.join(environment.buildDir.path, 'flutter_assets', 'assets/wildcard/%23bar.png')).existsSync(), true); expect(globals.fs.file(globals.fs.path.join(environment.buildDir.path, 'flutter_assets', 'assets/wildcard/%23bar.png')).existsSync(), true);
})); }));
test('Does not leave stale files in build directory', () => testbed.run(() async {
await buildSystem.build(const CopyAssets(), environment);
expect(globals.fs.file(globals.fs.path.join(environment.buildDir.path, 'flutter_assets', 'assets/foo/bar.png')).existsSync(), true);
// Modify manifest to remove asset.
globals.fs.file('pubspec.yaml')
..createSync()
..writeAsStringSync('''
name: example
flutter:
''');
await buildSystem.build(const CopyAssets(), environment);
// See https://github.com/flutter/flutter/issues/35293
expect(globals.fs.file(globals.fs.path.join(environment.buildDir.path, 'flutter_assets', 'assets/foo/bar.png')).existsSync(), false);
}), skip: Platform.isWindows); // See https://github.com/google/file.dart/issues/131
test('FlutterPlugins updates required files as needed', () => testbed.run(() async { test('FlutterPlugins updates required files as needed', () => testbed.run(() async {
globals.fs.file('pubspec.yaml') globals.fs.file('pubspec.yaml')
..writeAsStringSync('name: foo\ndependencies:\n foo: any\n'); ..writeAsStringSync('name: foo\ndependencies:\n foo: any\n');
......
...@@ -39,6 +39,7 @@ void main() { ...@@ -39,6 +39,7 @@ void main() {
targetPlatform: TargetPlatform.ios, targetPlatform: TargetPlatform.ios,
depfilePath: 'example.d', depfilePath: 'example.d',
precompiled: false, precompiled: false,
treeShakeIcons: false,
); );
expect(globals.fs.file(globals.fs.path.join('example', 'kernel_blob.bin')).existsSync(), true); expect(globals.fs.file(globals.fs.path.join('example', 'kernel_blob.bin')).existsSync(), true);
expect(globals.fs.file(globals.fs.path.join('example', 'LICENSE')).existsSync(), true); expect(globals.fs.file(globals.fs.path.join('example', 'LICENSE')).existsSync(), true);
...@@ -61,6 +62,7 @@ void main() { ...@@ -61,6 +62,7 @@ void main() {
targetPlatform: TargetPlatform.linux_x64, targetPlatform: TargetPlatform.linux_x64,
depfilePath: 'example.d', depfilePath: 'example.d',
precompiled: false, precompiled: false,
treeShakeIcons: false,
), throwsToolExit()); ), throwsToolExit());
})); }));
} }
......
...@@ -720,7 +720,7 @@ void main() { ...@@ -720,7 +720,7 @@ void main() {
app = BuildableFuchsiaApp(project: FlutterProject.current().fuchsia); app = BuildableFuchsiaApp(project: FlutterProject.current().fuchsia);
} }
final DebuggingOptions debuggingOptions = DebuggingOptions.disabled(BuildInfo(mode, null)); final DebuggingOptions debuggingOptions = DebuggingOptions.disabled(BuildInfo(mode, null, treeShakeIcons: false));
return await device.startApp( return await device.startApp(
app, app,
prebuiltApplication: prebuilt, prebuiltApplication: prebuilt,
...@@ -753,7 +753,7 @@ void main() { ...@@ -753,7 +753,7 @@ void main() {
final FuchsiaApp app = FuchsiaApp.fromPrebuiltApp(far); final FuchsiaApp app = FuchsiaApp.fromPrebuiltApp(far);
final DebuggingOptions debuggingOptions = final DebuggingOptions debuggingOptions =
DebuggingOptions.disabled(const BuildInfo(BuildMode.release, null)); DebuggingOptions.disabled(const BuildInfo(BuildMode.release, null, treeShakeIcons: false));
final LaunchResult launchResult = await device.startApp(app, final LaunchResult launchResult = await device.startApp(app,
prebuiltApplication: true, prebuiltApplication: true,
debuggingOptions: debuggingOptions); debuggingOptions: debuggingOptions);
......
...@@ -292,7 +292,7 @@ void main() { ...@@ -292,7 +292,7 @@ void main() {
final LaunchResult launchResult = await device.startApp(mockApp, final LaunchResult launchResult = await device.startApp(mockApp,
prebuiltApplication: true, prebuiltApplication: true,
debuggingOptions: DebuggingOptions.enabled(const BuildInfo(BuildMode.debug, null)), debuggingOptions: DebuggingOptions.enabled(const BuildInfo(BuildMode.debug, null, treeShakeIcons: false)),
platformArgs: <String, dynamic>{}, platformArgs: <String, dynamic>{},
); );
verify(mockUsage.sendEvent('ios-mdns', 'success')).called(1); verify(mockUsage.sendEvent('ios-mdns', 'success')).called(1);
...@@ -362,7 +362,7 @@ void main() { ...@@ -362,7 +362,7 @@ void main() {
final LaunchResult launchResult = await device.startApp(mockApp, final LaunchResult launchResult = await device.startApp(mockApp,
prebuiltApplication: true, prebuiltApplication: true,
debuggingOptions: DebuggingOptions.enabled(const BuildInfo(BuildMode.debug, null)), debuggingOptions: DebuggingOptions.enabled(const BuildInfo(BuildMode.debug, null, treeShakeIcons: false)),
platformArgs: <String, dynamic>{}, platformArgs: <String, dynamic>{},
); );
verify(mockUsage.sendEvent('ios-mdns', 'failure')).called(1); verify(mockUsage.sendEvent('ios-mdns', 'failure')).called(1);
...@@ -395,7 +395,7 @@ void main() { ...@@ -395,7 +395,7 @@ void main() {
final LaunchResult launchResult = await device.startApp(mockApp, final LaunchResult launchResult = await device.startApp(mockApp,
prebuiltApplication: true, prebuiltApplication: true,
debuggingOptions: DebuggingOptions.enabled(const BuildInfo(BuildMode.debug, null)), debuggingOptions: DebuggingOptions.enabled(const BuildInfo(BuildMode.debug, null, treeShakeIcons: false)),
platformArgs: <String, dynamic>{}, platformArgs: <String, dynamic>{},
); );
verify(mockUsage.sendEvent('ios-mdns', 'failure')).called(1); verify(mockUsage.sendEvent('ios-mdns', 'failure')).called(1);
...@@ -416,7 +416,7 @@ void main() { ...@@ -416,7 +416,7 @@ void main() {
final IOSDevice device = IOSDevice('123'); final IOSDevice device = IOSDevice('123');
final LaunchResult launchResult = await device.startApp(mockApp, final LaunchResult launchResult = await device.startApp(mockApp,
prebuiltApplication: true, prebuiltApplication: true,
debuggingOptions: DebuggingOptions.disabled(const BuildInfo(BuildMode.release, null)), debuggingOptions: DebuggingOptions.disabled(const BuildInfo(BuildMode.release, null, treeShakeIcons: false)),
platformArgs: <String, dynamic>{}, platformArgs: <String, dynamic>{},
); );
expect(launchResult.started, isTrue); expect(launchResult.started, isTrue);
...@@ -455,7 +455,7 @@ void main() { ...@@ -455,7 +455,7 @@ void main() {
final LaunchResult launchResult = await device.startApp(mockApp, final LaunchResult launchResult = await device.startApp(mockApp,
prebuiltApplication: true, prebuiltApplication: true,
debuggingOptions: DebuggingOptions.enabled( debuggingOptions: DebuggingOptions.enabled(
const BuildInfo(BuildMode.debug, null), const BuildInfo(BuildMode.debug, null, treeShakeIcons: false),
cacheSkSL: true, cacheSkSL: true,
), ),
platformArgs: <String, dynamic>{}, platformArgs: <String, dynamic>{},
...@@ -499,7 +499,7 @@ void main() { ...@@ -499,7 +499,7 @@ void main() {
final LaunchResult launchResult = await device.startApp(mockApp, final LaunchResult launchResult = await device.startApp(mockApp,
prebuiltApplication: true, prebuiltApplication: true,
debuggingOptions: DebuggingOptions.enabled( debuggingOptions: DebuggingOptions.enabled(
const BuildInfo(BuildMode.debug, null), const BuildInfo(BuildMode.debug, null, treeShakeIcons: false),
deviceVmServicePort: 8181, deviceVmServicePort: 8181,
), ),
platformArgs: <String, dynamic>{}, platformArgs: <String, dynamic>{},
...@@ -600,7 +600,7 @@ void main() { ...@@ -600,7 +600,7 @@ void main() {
device.startApp( device.startApp(
app, app,
prebuiltApplication: false, prebuiltApplication: false,
debuggingOptions: DebuggingOptions.disabled(const BuildInfo(BuildMode.debug, null)), debuggingOptions: DebuggingOptions.disabled(const BuildInfo(BuildMode.debug, null, treeShakeIcons: false)),
platformArgs: <String, dynamic>{}, platformArgs: <String, dynamic>{},
).then((LaunchResult result) { ).then((LaunchResult result) {
completer.complete(result); completer.complete(result);
......
...@@ -10,6 +10,7 @@ import 'package:flutter_tools/src/build_info.dart'; ...@@ -10,6 +10,7 @@ import 'package:flutter_tools/src/build_info.dart';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/targets/dart.dart'; import 'package:flutter_tools/src/build_system/targets/dart.dart';
import 'package:flutter_tools/src/build_system/targets/icon_tree_shaker.dart';
import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/application_package.dart'; import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
...@@ -219,6 +220,7 @@ void main() { ...@@ -219,6 +220,7 @@ void main() {
kTargetPlatform: 'ios', kTargetPlatform: 'ios',
kBuildMode: 'debug', kBuildMode: 'debug',
kTrackWidgetCreation: 'false', kTrackWidgetCreation: 'false',
kIconTreeShakerFlag: null,
}); });
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
BuildSystem: () => MockBuildSystem(), BuildSystem: () => MockBuildSystem(),
...@@ -501,7 +503,7 @@ void main() { ...@@ -501,7 +503,7 @@ void main() {
final Directory mockDir = globals.fs.currentDirectory; final Directory mockDir = globals.fs.currentDirectory;
final IOSApp package = PrebuiltIOSApp(projectBundleId: 'incorrect', bundleName: 'name', bundleDir: mockDir); final IOSApp package = PrebuiltIOSApp(projectBundleId: 'incorrect', bundleName: 'name', bundleDir: mockDir);
const BuildInfo mockInfo = BuildInfo(BuildMode.debug, 'flavor'); const BuildInfo mockInfo = BuildInfo(BuildMode.debug, 'flavor', treeShakeIcons: false);
final DebuggingOptions mockOptions = DebuggingOptions.disabled(mockInfo); final DebuggingOptions mockOptions = DebuggingOptions.disabled(mockInfo);
await device.startApp(package, prebuiltApplication: true, debuggingOptions: mockOptions); await device.startApp(package, prebuiltApplication: true, debuggingOptions: mockOptions);
......
...@@ -148,7 +148,7 @@ void main() { ...@@ -148,7 +148,7 @@ void main() {
testUsingContext('not debug', () async { testUsingContext('not debug', () async {
final LaunchResult result = await device.startApp(null, final LaunchResult result = await device.startApp(null,
mainPath: mainPath, mainPath: mainPath,
debuggingOptions: DebuggingOptions.disabled(const BuildInfo(BuildMode.release, null))); debuggingOptions: DebuggingOptions.disabled(const BuildInfo(BuildMode.release, null, treeShakeIcons: false)));
expect(result.started, isFalse); expect(result.started, isFalse);
}, overrides: startOverrides); }, overrides: startOverrides);
...@@ -166,7 +166,7 @@ Hello! ...@@ -166,7 +166,7 @@ Hello!
final LaunchResult result = await device.startApp(null, final LaunchResult result = await device.startApp(null,
mainPath: mainPath, mainPath: mainPath,
debuggingOptions: DebuggingOptions.enabled(const BuildInfo(BuildMode.debug, null))); debuggingOptions: DebuggingOptions.enabled(const BuildInfo(BuildMode.debug, null, treeShakeIcons: false)));
expect(result.started, isTrue); expect(result.started, isTrue);
expect(result.observatoryUri, observatoryUri); expect(result.observatoryUri, observatoryUri);
expect(logLines.last, 'Hello!'); expect(logLines.last, 'Hello!');
......
...@@ -372,7 +372,7 @@ class CompleterIOSink extends MemoryIOSink { ...@@ -372,7 +372,7 @@ class CompleterIOSink extends MemoryIOSink {
_completer.complete(throwOnAdd ? <int>[] : data); _completer.complete(throwOnAdd ? <int>[] : data);
} }
if (throwOnAdd) { if (throwOnAdd) {
throw 'CompleterIOSink Error'; throw Exception('CompleterIOSink Error');
} }
super.add(data); super.add(data);
} }
......
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