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