Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dev/bots/test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ Future<void> _flutterBuild(
final File file = File(path.join(flutterRoot, relativePathToApplication, 'perf.json'));
if (!_allTargetsCached(file)) {
print('${red}Not all build targets cached after second run.$reset');
print('The target performance data was: ${file.readAsStringSync()}');
print('The target performance data was: ${file.readAsStringSync().replaceAll('},', '},\n')}');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes the log much more readable. Quick fix for me totally missing the "skipped: false" entries in this line because it was 90% cut off onscreen.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awesome!

exit(1);
}
}
Expand Down
64 changes: 51 additions & 13 deletions packages/flutter_tools/gradle/flutter.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,14 @@ class FlutterPlugin implements Plugin<Project> {
}
}
}

if (project.hasProperty('deferred-component-names')) {
String[] componentNames = project.property('deferred-component-names').split(',').collect {":${it}"}
project.android {
dynamicFeatures = componentNames
}
}

getTargetPlatforms().each { targetArch ->
String abiValue = PLATFORM_ARCH_MAP[targetArch]
project.android {
Expand Down Expand Up @@ -173,17 +181,23 @@ class FlutterPlugin implements Plugin<Project> {
matchingFallbacks = ["debug", "release"]
}
}
release {
// Enables code shrinking, obfuscation, and optimization for only
// your project's release build type.
minifyEnabled true
// Enables resource shrinking, which is performed by the
// Android Gradle plugin.
// NOTE: The resource shrinker can't be used for libraries.
shrinkResources isBuiltAsApp(project)
// Fallback to `android/app/proguard-rules.pro`.
// This way, custom Proguard rules can be configured as needed.
proguardFiles project.android.getDefaultProguardFile("proguard-android.txt"), flutterProguardRules, "proguard-rules.pro"
// TODO(garyq): Shrinking is only false for multi apk split aot builds, where shrinking is not allowed yet.
// This limitation has been removed experimentally in gradle plugin version 4.2, so we can remove
// this check when we upgrade to 4.2+ gradle. Currently, deferred components apps may see
// increased app size due to this.
if (shouldShrinkResources(project)) {
release {
// Enables code shrinking, obfuscation, and optimization for only
// your project's release build type.
minifyEnabled true
// Enables resource shrinking, which is performed by the
// Android Gradle plugin.
// NOTE: The resource shrinker can't be used for libraries.
shrinkResources isBuiltAsApp(project)
// Fallback to `android/app/proguard-rules.pro`.
// This way, custom Proguard rules can be configured as needed.
proguardFiles project.android.getDefaultProguardFile("proguard-android.txt"), flutterProguardRules, "proguard-rules.pro"
}
}
}

Expand All @@ -200,6 +214,13 @@ class FlutterPlugin implements Plugin<Project> {
project.android.buildTypes.all this.&addFlutterDependencies
}

private static Boolean shouldShrinkResources(Project project) {
if (project.hasProperty("shrink")) {
return project.property("shrink").toBoolean()
}
return true
}

/**
* Adds the dependencies required by the Flutter project.
* This includes:
Expand Down Expand Up @@ -706,6 +727,14 @@ class FlutterPlugin implements Plugin<Project> {
if (project.hasProperty('code-size-directory')) {
codeSizeDirectoryValue = project.property('code-size-directory')
}
Boolean deferredComponentsValue = false
if (project.hasProperty('deferred-components')) {
deferredComponentsValue = project.property('deferred-components').toBoolean()
}
Boolean validateDeferredComponentsValue = true
if (project.hasProperty('validate-deferred-components')) {
validateDeferredComponentsValue = project.property('validate-deferred-components').toBoolean()
}
def targetPlatforms = getTargetPlatforms()
def addFlutterDeps = { variant ->
if (shouldSplitPerAbi()) {
Expand Down Expand Up @@ -747,6 +776,8 @@ class FlutterPlugin implements Plugin<Project> {
bundleSkSLPath bundleSkSLPathValue
performanceMeasurementFile performanceMeasurementFileValue
codeSizeDirectory codeSizeDirectoryValue
deferredComponents deferredComponentsValue
validateDeferredComponents validateDeferredComponentsValue
doLast {
project.exec {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
Expand Down Expand Up @@ -810,7 +841,8 @@ class FlutterPlugin implements Plugin<Project> {
processResources.dependsOn(copyFlutterAssetsTask)
}
return copyFlutterAssetsTask
}
} // end def addFlutterDeps

if (isFlutterAppProject()) {
project.android.applicationVariants.all { variant ->
Task assembleTask = getAssembleTask(variant)
Expand Down Expand Up @@ -883,7 +915,7 @@ class FlutterPlugin implements Plugin<Project> {
// | ----------------- | ----------------------------- |
// | Build Variant | Flutter Equivalent Variant |
// | ----------------- | ----------------------------- |
// | freeRelease | relese |
// | freeRelease | release |
// | freeDebug | debug |
// | freeDevelop | debug |
// | profile | profile |
Expand Down Expand Up @@ -961,6 +993,10 @@ abstract class BaseFlutterTask extends DefaultTask {
@Optional @Input
String codeSizeDirectory;
String performanceMeasurementFile;
@Optional @Input
Boolean deferredComponents
@Optional @Input
Boolean validateDeferredComponents

@OutputFiles
FileCollection getDependenciesFiles() {
Expand All @@ -985,6 +1021,8 @@ abstract class BaseFlutterTask extends DefaultTask {
String[] ruleNames;
if (buildMode == "debug") {
ruleNames = ["debug_android_application"]
} else if (deferredComponents) {
ruleNames = targetPlatformValues.collect { "android_aot_deferred_components_bundle_${buildMode}_$it" }
} else {
ruleNames = targetPlatformValues.collect { "android_aot_bundle_${buildMode}_$it" }
}
Expand Down
2 changes: 2 additions & 0 deletions packages/flutter_tools/lib/src/android/android_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,7 @@ abstract class AndroidBuilder {
@required FlutterProject project,
@required AndroidBuildInfo androidBuildInfo,
@required String target,
bool validateDeferredComponents = true,
bool deferredComponentsEnabled = false,
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,17 @@ class DeferredComponentsGenSnapshotValidator extends DeferredComponentsValidator
/// When [exitOnFail] is set to true, the [handleResults] and [attemptToolExit]
/// methods will exit the tool when this validator detects a recommended
/// change. This defaults to true.
DeferredComponentsGenSnapshotValidator(Environment env, {
DeferredComponentsGenSnapshotValidator(this.env, {
bool exitOnFail = true,
String title,
}) : super(env, exitOnFail: exitOnFail, title: title);
}) : super(env.projectDir, env.logger, exitOnFail: exitOnFail, title: title);

/// The build environment that should be used to find the input files to run
/// checks against.
///
/// The checks in this class are meant to be used as part of a build process,
/// so an environment should be available.
final Environment env;

// The key used to identify the metadata element as the loading unit id to
// deferred component mapping.
Expand All @@ -58,8 +65,8 @@ class DeferredComponentsGenSnapshotValidator extends DeferredComponentsValidator
/// Where loading unit 2 is included in componentA, loading unit 3 is included
/// in componentB, and loading unit 4 is included in componentC.
bool checkAppAndroidManifestComponentLoadingUnitMapping(List<DeferredComponent> components, List<LoadingUnit> generatedLoadingUnits) {
final Directory androidDir = env.projectDir.childDirectory('android');
inputs.add(env.projectDir.childFile('pubspec.yaml'));
final Directory androidDir = projectDir.childDirectory('android');
inputs.add(projectDir.childFile('pubspec.yaml'));

// We do not use the Xml package to handle the writing, as we do not want to
// erase any user applied formatting and comments. The changes can be
Expand Down Expand Up @@ -106,8 +113,10 @@ class DeferredComponentsGenSnapshotValidator extends DeferredComponentsValidator
mappingBuffer.write('$key:${mapping[key]},');
}
String encodedMapping = mappingBuffer.toString();
// remove trailing comma.
encodedMapping = encodedMapping.substring(0, encodedMapping.length - 1);
// remove trailing comma if any
if (encodedMapping.endsWith(',')) {
encodedMapping = encodedMapping.substring(0, encodedMapping.length - 1);
}
// Check for existing metadata entry and see if needs changes.
bool exists = false;
bool modified = false;
Expand Down Expand Up @@ -163,7 +172,7 @@ class DeferredComponentsGenSnapshotValidator extends DeferredComponentsValidator
/// considered new.
bool checkAgainstLoadingUnitsCache(
List<LoadingUnit> generatedLoadingUnits) {
final List<LoadingUnit> cachedLoadingUnits = _parseLodingUnitsCache(env.projectDir.childFile(DeferredComponentsValidator.kLoadingUnitsCacheFileName));
final List<LoadingUnit> cachedLoadingUnits = _parseLodingUnitsCache(projectDir.childFile(DeferredComponentsValidator.kLoadingUnitsCacheFileName));
loadingUnitComparisonResults = <String, dynamic>{};
final Set<LoadingUnit> unmatchedLoadingUnits = <LoadingUnit>{};
final List<LoadingUnit> newLoadingUnits = <LoadingUnit>[];
Expand Down Expand Up @@ -276,7 +285,7 @@ class DeferredComponentsGenSnapshotValidator extends DeferredComponentsValidator
/// deferred components.
void writeLoadingUnitsCache(List<LoadingUnit> generatedLoadingUnits) {
generatedLoadingUnits ??= <LoadingUnit>[];
final File cacheFile = env.projectDir.childFile(DeferredComponentsValidator.kLoadingUnitsCacheFileName);
final File cacheFile = projectDir.childFile(DeferredComponentsValidator.kLoadingUnitsCacheFileName);
outputs.add(cacheFile);
ErrorHandlingFileSystem.deleteIfExists(cacheFile);
cacheFile.createSync(recursive: true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import 'package:xml/xml.dart';
import '../base/deferred_component.dart';
import '../base/error_handling_io.dart';
import '../base/file_system.dart';
import '../build_system/build_system.dart';
import '../base/logger.dart';
import '../globals.dart' as globals;
import '../project.dart';
import '../template.dart';
Expand All @@ -25,20 +25,18 @@ import 'deferred_components_validator.dart';
class DeferredComponentsPrebuildValidator extends DeferredComponentsValidator {
/// Constructs a validator instance.
///
/// The [env] property is used to locate the project files that are checked.
///
/// The [templatesDir] parameter is optional. If null, the tool's default
/// templates directory will be used.
///
/// When [exitOnFail] is set to true, the [handleResults] and [attemptToolExit]
/// methods will exit the tool when this validator detects a recommended
/// change. This defaults to true.
DeferredComponentsPrebuildValidator(Environment env, {
DeferredComponentsPrebuildValidator(Directory projectDir, Logger logger, {
bool exitOnFail = true,
String title,
Directory templatesDir,
}) : _templatesDir = templatesDir,
super(env, exitOnFail: exitOnFail, title: title);
super(projectDir, logger, exitOnFail: exitOnFail, title: title);

final Directory _templatesDir;

Expand All @@ -56,15 +54,16 @@ class DeferredComponentsPrebuildValidator extends DeferredComponentsValidator {
/// This method does not check if the contents of either of the files are
/// valid, as there are many ways that they can be validly configured.
Future<bool> checkAndroidDynamicFeature(List<DeferredComponent> components) async {
inputs.add(env.projectDir.childFile('pubspec.yaml'));
inputs.add(projectDir.childFile('pubspec.yaml'));
if (components == null || components.isEmpty) {
return false;
}
bool changesMade = false;
for (final DeferredComponent component in components) {
final _DeferredComponentAndroidFiles androidFiles = _DeferredComponentAndroidFiles(
name: component.name,
env: env,
projectDir: projectDir,
logger: logger,
templatesDir: _templatesDir
);
if (!androidFiles.verifyFilesExist()) {
Expand Down Expand Up @@ -106,8 +105,8 @@ class DeferredComponentsPrebuildValidator extends DeferredComponentsValidator {
/// The string element's name attribute should be the component name with
/// `Name` as a suffix, and the text contents should be the component name.
bool checkAndroidResourcesStrings(List<DeferredComponent> components) {
final Directory androidDir = env.projectDir.childDirectory('android');
inputs.add(env.projectDir.childFile('pubspec.yaml'));
final Directory androidDir = projectDir.childDirectory('android');
inputs.add(projectDir.childFile('pubspec.yaml'));

// Add component name mapping to strings.xml
final File stringRes = androidDir
Expand Down Expand Up @@ -202,7 +201,7 @@ class DeferredComponentsPrebuildValidator extends DeferredComponentsValidator {

/// Deletes all files inside of the validator's output directory.
void clearOutputDir() {
final Directory dir = env.projectDir.childDirectory('build').childDirectory(DeferredComponentsValidator.kDeferredComponentsTempDirectory);
final Directory dir = projectDir.childDirectory('build').childDirectory(DeferredComponentsValidator.kDeferredComponentsTempDirectory);
ErrorHandlingFileSystem.deleteIfExists(dir, recursive: true);
}
}
Expand All @@ -212,16 +211,18 @@ class DeferredComponentsPrebuildValidator extends DeferredComponentsValidator {
class _DeferredComponentAndroidFiles {
_DeferredComponentAndroidFiles({
@required this.name,
@required this.env,
@required this.projectDir,
this.logger,
Directory templatesDir,
}) : _templatesDir = templatesDir;

// The name of the deferred component.
final String name;
final Environment env;
final Directory projectDir;
final Logger logger;
final Directory _templatesDir;

Directory get androidDir => env.projectDir.childDirectory('android');
Directory get androidDir => projectDir.childDirectory('android');
Directory get componentDir => androidDir.childDirectory(name);

File get androidManifestFile => componentDir.childDirectory('src').childDirectory('main').childFile('AndroidManifest.xml');
Expand Down Expand Up @@ -250,18 +251,18 @@ class _DeferredComponentAndroidFiles {
Future<List<File>> _setupComponentFiles(Directory outputDir) async {
Template template;
if (_templatesDir != null) {
final Directory templateComponentDir = _templatesDir.childDirectory('module${env.fileSystem.path.separator}android${env.fileSystem.path.separator}deferred_component');
final Directory templateComponentDir = _templatesDir.childDirectory('module${globals.fs.path.separator}android${globals.fs.path.separator}deferred_component');
template = Template(templateComponentDir, templateComponentDir, _templatesDir,
fileSystem: env.fileSystem,
fileSystem: globals.fs,
templateManifest: null,
logger: env.logger,
logger: logger,
templateRenderer: globals.templateRenderer,
);
} else {
template = await Template.fromName('module${env.fileSystem.path.separator}android${env.fileSystem.path.separator}deferred_component',
fileSystem: env.fileSystem,
template = await Template.fromName('module${globals.fs.path.separator}android${globals.fs.path.separator}deferred_component',
fileSystem: globals.fs,
templateManifest: null,
logger: env.logger,
logger: logger,
templateRenderer: globals.templateRenderer,
);
}
Expand Down
Loading