Unverified Commit 1f256447 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Migrate android build target to null safety (#91455)

parent 5047fdcc
...@@ -2,14 +2,12 @@ ...@@ -2,14 +2,12 @@
// 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.
// @dart = 2.8
import '../../artifacts.dart'; import '../../artifacts.dart';
import '../../base/build.dart'; import '../../base/build.dart';
import '../../base/deferred_component.dart'; import '../../base/deferred_component.dart';
import '../../base/file_system.dart'; import '../../base/file_system.dart';
import '../../build_info.dart'; import '../../build_info.dart';
import '../../globals_null_migrated.dart' as globals show platform, printError, xcode; import '../../globals_null_migrated.dart' as globals show xcode;
import '../../project.dart'; import '../../project.dart';
import '../build_system.dart'; import '../build_system.dart';
import '../depfile.dart'; import '../depfile.dart';
...@@ -43,10 +41,11 @@ abstract class AndroidAssetBundle extends Target { ...@@ -43,10 +41,11 @@ abstract class AndroidAssetBundle extends Target {
@override @override
Future<void> build(Environment environment) async { Future<void> build(Environment environment) async {
if (environment.defines[kBuildMode] == null) { final String? buildModeEnvironment = environment.defines[kBuildMode];
if (buildModeEnvironment == null) {
throw MissingDefineException(kBuildMode, name); throw MissingDefineException(kBuildMode, name);
} }
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]); final BuildMode buildMode = getBuildModeForName(buildModeEnvironment);
final Directory outputDirectory = environment.outputDir final Directory outputDirectory = environment.outputDir
.childDirectory('flutter_assets') .childDirectory('flutter_assets')
..createSync(recursive: true); ..createSync(recursive: true);
...@@ -209,13 +208,13 @@ class AndroidAot extends AotElfBase { ...@@ -209,13 +208,13 @@ class AndroidAot extends AotElfBase {
final AOTSnapshotter snapshotter = AOTSnapshotter( final AOTSnapshotter snapshotter = AOTSnapshotter(
fileSystem: environment.fileSystem, fileSystem: environment.fileSystem,
logger: environment.logger, logger: environment.logger,
xcode: globals.xcode, xcode: globals.xcode!,
processManager: environment.processManager, processManager: environment.processManager,
artifacts: environment.artifacts, artifacts: environment.artifacts,
); );
final Directory output = environment.buildDir.childDirectory(_androidAbiName); final Directory output = environment.buildDir.childDirectory(_androidAbiName);
final String splitDebugInfo = environment.defines[kSplitDebugInfo]; final String? buildModeEnvironment = environment.defines[kBuildMode];
if (environment.defines[kBuildMode] == null) { if (buildModeEnvironment == null) {
throw MissingDefineException(kBuildMode, 'aot_elf'); throw MissingDefineException(kBuildMode, 'aot_elf');
} }
if (!output.existsSync()) { if (!output.existsSync()) {
...@@ -223,14 +222,14 @@ class AndroidAot extends AotElfBase { ...@@ -223,14 +222,14 @@ class AndroidAot extends AotElfBase {
} }
final List<String> extraGenSnapshotOptions = decodeCommaSeparated(environment.defines, kExtraGenSnapshotOptions); final List<String> extraGenSnapshotOptions = decodeCommaSeparated(environment.defines, kExtraGenSnapshotOptions);
final List<File> outputs = <File>[]; // outputs for the depfile final List<File> outputs = <File>[]; // outputs for the depfile
final String manifestPath = '${output.path}${globals.platform.pathSeparator}manifest.json'; final String manifestPath = '${output.path}${environment.platform.pathSeparator}manifest.json';
if (environment.defines[kDeferredComponents] == 'true') { if (environment.defines[kDeferredComponents] == 'true') {
extraGenSnapshotOptions.add('--loading_unit_manifest=$manifestPath'); extraGenSnapshotOptions.add('--loading_unit_manifest=$manifestPath');
outputs.add(environment.fileSystem.file(manifestPath)); outputs.add(environment.fileSystem.file(manifestPath));
} }
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]); final BuildMode buildMode = getBuildModeForName(buildModeEnvironment);
final bool dartObfuscation = environment.defines[kDartObfuscation] == 'true'; final bool dartObfuscation = environment.defines[kDartObfuscation] == 'true';
final String codeSizeDirectory = environment.defines[kCodeSizeDirectory]; final String? codeSizeDirectory = environment.defines[kCodeSizeDirectory];
if (codeSizeDirectory != null) { if (codeSizeDirectory != null) {
final File codeSizeFile = environment.fileSystem final File codeSizeFile = environment.fileSystem
...@@ -243,6 +242,7 @@ class AndroidAot extends AotElfBase { ...@@ -243,6 +242,7 @@ class AndroidAot extends AotElfBase {
extraGenSnapshotOptions.add('--trace-precompiler-to=${precompilerTraceFile.path}'); extraGenSnapshotOptions.add('--trace-precompiler-to=${precompilerTraceFile.path}');
} }
final String? splitDebugInfo = environment.defines[kSplitDebugInfo];
final int snapshotExitCode = await snapshotter.build( final int snapshotExitCode = await snapshotter.build(
platform: targetPlatform, platform: targetPlatform,
buildMode: buildMode, buildMode: buildMode,
...@@ -375,12 +375,12 @@ class AndroidAotDeferredComponentsBundle extends Target { ...@@ -375,12 +375,12 @@ class AndroidAotDeferredComponentsBundle extends Target {
/// Create an [AndroidAotDeferredComponentsBundle] implementation for a given [targetPlatform] and [buildMode]. /// Create an [AndroidAotDeferredComponentsBundle] implementation for a given [targetPlatform] and [buildMode].
/// ///
/// If [components] is not provided, it will be read from the pubspec.yaml manifest. /// If [components] is not provided, it will be read from the pubspec.yaml manifest.
AndroidAotDeferredComponentsBundle(this.dependency, {List<DeferredComponent> components}) : _components = components; AndroidAotDeferredComponentsBundle(this.dependency, {List<DeferredComponent>? components}) : _components = components;
/// The [AndroidAotBundle] instance this bundle rule depends on. /// The [AndroidAotBundle] instance this bundle rule depends on.
final AndroidAotBundle dependency; final AndroidAotBundle dependency;
List<DeferredComponent> _components; List<DeferredComponent>? _components;
/// The name of the produced Android ABI. /// The name of the produced Android ABI.
String get _androidAbiName { String get _androidAbiName {
...@@ -422,10 +422,10 @@ class AndroidAotDeferredComponentsBundle extends Target { ...@@ -422,10 +422,10 @@ class AndroidAotDeferredComponentsBundle extends Target {
_components ??= FlutterProject.current().manifest.deferredComponents ?? <DeferredComponent>[]; _components ??= FlutterProject.current().manifest.deferredComponents ?? <DeferredComponent>[];
final List<String> abis = <String>[_androidAbiName]; final List<String> abis = <String>[_androidAbiName];
final List<LoadingUnit> generatedLoadingUnits = LoadingUnit.parseGeneratedLoadingUnits(environment.outputDir, environment.logger, abis: abis); final List<LoadingUnit> generatedLoadingUnits = LoadingUnit.parseGeneratedLoadingUnits(environment.outputDir, environment.logger, abis: abis);
for (final DeferredComponent component in _components) { for (final DeferredComponent component in _components!) {
component.assignLoadingUnits(generatedLoadingUnits); component.assignLoadingUnits(generatedLoadingUnits);
} }
final Depfile libDepfile = copyDeferredComponentSoFiles(environment, _components, generatedLoadingUnits, environment.projectDir.childDirectory('build'), abis, dependency.buildMode); final Depfile libDepfile = copyDeferredComponentSoFiles(environment, _components!, generatedLoadingUnits, environment.projectDir.childDirectory('build'), abis, dependency.buildMode);
final File manifestFile = environment.outputDir.childDirectory(_androidAbiName).childFile('manifest.json'); final File manifestFile = environment.outputDir.childDirectory(_androidAbiName).childFile('manifest.json');
if (manifestFile.existsSync()) { if (manifestFile.existsSync()) {
...@@ -473,21 +473,23 @@ Depfile copyDeferredComponentSoFiles( ...@@ -473,21 +473,23 @@ Depfile copyDeferredComponentSoFiles(
List<LoadingUnit> loadingUnits, List<LoadingUnit> loadingUnits,
Directory buildDir, // generally `<projectDir>/build` Directory buildDir, // generally `<projectDir>/build`
List<String> abis, List<String> abis,
BuildMode buildMode,) { BuildMode buildMode,
) {
final List<File> inputs = <File>[]; final List<File> inputs = <File>[];
final List<File> outputs = <File>[]; final List<File> outputs = <File>[];
final Set<int> usedLoadingUnits = <int>{}; final Set<int> usedLoadingUnits = <int>{};
// Copy all .so files for loading units that are paired with a deferred component. // Copy all .so files for loading units that are paired with a deferred component.
for (final String abi in abis) { for (final String abi in abis) {
for (final DeferredComponent component in components) { for (final DeferredComponent component in components) {
if (!component.assigned) { final Set<LoadingUnit>? loadingUnits = component.loadingUnits;
globals.printError('Deferred component require loading units to be assigned.'); if (loadingUnits == null || !component.assigned) {
env.logger.printError('Deferred component require loading units to be assigned.');
return Depfile(inputs, outputs); return Depfile(inputs, outputs);
} }
for (final LoadingUnit unit in component.loadingUnits) { for (final LoadingUnit unit in loadingUnits) {
// ensure the abi for the unit is one of the abis we build for. // ensure the abi for the unit is one of the abis we build for.
final List<String> splitPath = unit.path.split(env.fileSystem.path.separator); final List<String>? splitPath = unit.path?.split(env.fileSystem.path.separator);
if (splitPath[splitPath.length - 2] != abi) { if (splitPath == null || splitPath[splitPath.length - 2] != abi) {
continue; continue;
} }
usedLoadingUnits.add(unit.id); usedLoadingUnits.add(unit.id);
...@@ -517,8 +519,8 @@ Depfile copyDeferredComponentSoFiles( ...@@ -517,8 +519,8 @@ Depfile copyDeferredComponentSoFiles(
continue; continue;
} }
// ensure the abi for the unit is one of the abis we build for. // ensure the abi for the unit is one of the abis we build for.
final List<String> splitPath = unit.path.split(env.fileSystem.path.separator); final List<String>? splitPath = unit.path?.split(env.fileSystem.path.separator);
if (splitPath[splitPath.length - 2] != abi) { if (splitPath == null || splitPath[splitPath.length - 2] != abi) {
continue; continue;
} }
final File destination = env.outputDir final File destination = env.outputDir
......
...@@ -68,9 +68,6 @@ void main() { ...@@ -68,9 +68,6 @@ void main() {
expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'isolate_snapshot_data')).existsSync(), true); expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'isolate_snapshot_data')).existsSync(), true);
expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'vm_snapshot_data')).existsSync(), true); expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'vm_snapshot_data')).existsSync(), true);
expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'kernel_blob.bin')).existsSync(), true); expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'kernel_blob.bin')).existsSync(), true);
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
}); });
testUsingContext('debug bundle contains expected resources with bundle SkSL', () async { testUsingContext('debug bundle contains expected resources with bundle SkSL', () async {
...@@ -116,12 +113,9 @@ void main() { ...@@ -116,12 +113,9 @@ void main() {
expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'vm_snapshot_data')), exists); expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'vm_snapshot_data')), exists);
expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'kernel_blob.bin')), exists); expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'kernel_blob.bin')), exists);
expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'io.flutter.shaders.json')), exists); expect(fileSystem.file(fileSystem.path.join('out', 'flutter_assets', 'io.flutter.shaders.json')), exists);
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
}); });
testUsingContext('profile bundle contains expected resources', () async { testWithoutContext('profile bundle contains expected resources', () async {
final Environment environment = Environment.test( final Environment environment = Environment.test(
fileSystem.currentDirectory, fileSystem.currentDirectory,
outputDir: fileSystem.directory('out')..createSync(), outputDir: fileSystem.directory('out')..createSync(),
...@@ -142,9 +136,6 @@ void main() { ...@@ -142,9 +136,6 @@ void main() {
await const ProfileAndroidApplication().build(environment); await const ProfileAndroidApplication().build(environment);
expect(fileSystem.file(fileSystem.path.join('out', 'app.so')).existsSync(), true); expect(fileSystem.file(fileSystem.path.join('out', 'app.so')).existsSync(), true);
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
}); });
testWithoutContext('release bundle contains expected resources', () async { testWithoutContext('release bundle contains expected resources', () async {
...@@ -204,9 +195,6 @@ void main() { ...@@ -204,9 +195,6 @@ void main() {
await androidAot.build(environment); await androidAot.build(environment);
expect(processManager, hasNoRemainingExpectations); expect(processManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
}); });
testUsingContext('AndroidAot provide code size information.', () async { testUsingContext('AndroidAot provide code size information.', () async {
...@@ -246,9 +234,6 @@ void main() { ...@@ -246,9 +234,6 @@ void main() {
await androidAot.build(environment); await androidAot.build(environment);
expect(processManager, hasNoRemainingExpectations); expect(processManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
}); });
testUsingContext('kExtraGenSnapshotOptions passes values to gen_snapshot', () async { testUsingContext('kExtraGenSnapshotOptions passes values to gen_snapshot', () async {
...@@ -289,9 +274,6 @@ void main() { ...@@ -289,9 +274,6 @@ void main() {
await const AndroidAot(TargetPlatform.android_arm64, BuildMode.release) await const AndroidAot(TargetPlatform.android_arm64, BuildMode.release)
.build(environment); .build(environment);
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
}); });
testUsingContext('--no-strip in kExtraGenSnapshotOptions suppresses --strip gen_snapshot flag', () async { testUsingContext('--no-strip in kExtraGenSnapshotOptions suppresses --strip gen_snapshot flag', () async {
...@@ -330,9 +312,6 @@ void main() { ...@@ -330,9 +312,6 @@ void main() {
await const AndroidAot(TargetPlatform.android_arm64, BuildMode.release) await const AndroidAot(TargetPlatform.android_arm64, BuildMode.release)
.build(environment); .build(environment);
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
}); });
testWithoutContext('android aot bundle copies so from abi directory', () async { testWithoutContext('android aot bundle copies so from abi directory', () async {
......
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