Skip to content

Commit 621e7ef

Browse files
authored
[flutter_tools] Cleanup of native asset related code (removes around 50% of the native asset related code) (#155430)
tl;dr Removes 50% (>1650 locs) of native asset related code in `packages/flutter_tools` Before this PR the invocation of dart build/link/dry-run was implemented per OS. This lead to very large code duplication of almost identical, but slightly different code. It also led to similarly duplicated test code. Almost the entire dart build/link/dry-run implementation is identical across OSes. There's small variations: - configuration of the build (e.g. android/macos/ios version, ios sdk, ...) - determining target locations & copying the final shared libraries This PR unifies the implementation by reducing the code to basically two main functions: * `runFlutterSpecificDartBuild` which is responsible for - obtain flutter configuration - perform dart build (& link) - determine target location & install binaries * `runFlutterSpecificDartDryRunOnPlatforms` which is responsible for a similar (but not same): - obtain flutter configuration - perform dart dry run - determine target location these two functions will call out to helpers for the OS specific functionality: * `_assetTargetLocationsForOS` for determining the location of the code assets * `_copyNativeCodeAssetsForOS` for copying the code assets (and possibly overriting the install name, etc) => Since we get rid of the code duplication across OSes and have only a single code path for the build/link/dry-run, we can also remove the duplicated tests that were pretty much identical across OSes. We also harden the building code by adding asserts, e.g. * the dry fun functionality should never be used by `flutter test` * the `build/native_assets/<os>/native_assets.yaml` should only be used by `flutter test` and the dry-run of `flutter run` => We change the tests to also comply with these invariants (so the tests are not testing things that cannot happen in reality) We also rename `{,Flutter}NativeAssetsBuildRunner` to disambiguate it from the `package:native_asset_builder`'s `NativeAssetsBuildRunner`.
1 parent 936cfb8 commit 621e7ef

File tree

19 files changed

+1163
-2810
lines changed

19 files changed

+1163
-2810
lines changed

packages/flutter_tools/lib/src/build_system/targets/native_assets.dart

Lines changed: 22 additions & 290 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,14 @@
33
// found in the LICENSE file.
44

55
import 'package:meta/meta.dart';
6-
import 'package:native_assets_builder/native_assets_builder.dart' hide NativeAssetsBuildRunner;
6+
import 'package:native_assets_builder/native_assets_builder.dart';
77
import 'package:package_config/package_config_types.dart';
88

9-
import '../../android/gradle_utils.dart';
109
import '../../base/common.dart';
1110
import '../../base/file_system.dart';
12-
import '../../base/platform.dart';
1311
import '../../build_info.dart';
1412
import '../../dart/package_map.dart';
15-
import '../../isolated/native_assets/android/native_assets.dart';
16-
import '../../isolated/native_assets/ios/native_assets.dart';
17-
import '../../isolated/native_assets/linux/native_assets.dart';
18-
import '../../isolated/native_assets/macos/native_assets.dart';
1913
import '../../isolated/native_assets/native_assets.dart';
20-
import '../../isolated/native_assets/windows/native_assets.dart';
21-
import '../../macos/xcode.dart';
2214
import '../build_system.dart';
2315
import '../depfile.dart';
2416
import '../exceptions.dart';
@@ -43,20 +35,21 @@ import 'common.dart';
4335
/// rebuild.
4436
class NativeAssets extends Target {
4537
const NativeAssets({
46-
@visibleForTesting NativeAssetsBuildRunner? buildRunner,
38+
@visibleForTesting FlutterNativeAssetsBuildRunner? buildRunner,
4739
}) : _buildRunner = buildRunner;
4840

49-
final NativeAssetsBuildRunner? _buildRunner;
41+
final FlutterNativeAssetsBuildRunner? _buildRunner;
5042

5143
@override
5244
Future<void> build(Environment environment) async {
5345
final String? nativeAssetsEnvironment = environment.defines[kNativeAssets];
54-
final List<Uri> dependencies;
5546
final FileSystem fileSystem = environment.fileSystem;
56-
final File nativeAssetsFile = environment.buildDir.childFile('native_assets.yaml');
47+
final Uri nativeAssetsFileUri = environment.buildDir.childFile('native_assets.yaml').uri;
48+
49+
final DartBuildResult result;
5750
if (nativeAssetsEnvironment == 'false') {
58-
dependencies = <Uri>[];
59-
await writeNativeAssetsYaml(KernelAssets(), environment.buildDir.uri, fileSystem);
51+
result = const DartBuildResult.empty();
52+
await writeNativeAssetsYaml(KernelAssets(), nativeAssetsFileUri, fileSystem);
6053
} else {
6154
final String? targetPlatformEnvironment = environment.defines[kTargetPlatform];
6255
if (targetPlatformEnvironment == null) {
@@ -69,300 +62,46 @@ class NativeAssets extends Target {
6962
fileSystem.file(environment.packageConfigPath),
7063
logger: environment.logger,
7164
);
72-
final NativeAssetsBuildRunner buildRunner = _buildRunner ??
73-
NativeAssetsBuildRunnerImpl(
65+
final FlutterNativeAssetsBuildRunner buildRunner = _buildRunner ??
66+
FlutterNativeAssetsBuildRunnerImpl(
7467
projectUri,
7568
environment.packageConfigPath,
7669
packageConfig,
7770
fileSystem,
7871
environment.logger,
7972
);
8073

81-
switch (targetPlatform) {
82-
case TargetPlatform.ios:
83-
dependencies = await _buildIOS(
84-
environment,
85-
projectUri,
86-
fileSystem,
87-
buildRunner,
88-
);
89-
case TargetPlatform.darwin:
90-
dependencies = await _buildMacOS(
91-
environment,
92-
projectUri,
93-
fileSystem,
94-
buildRunner,
95-
);
96-
case TargetPlatform.linux_arm64:
97-
case TargetPlatform.linux_x64:
98-
dependencies = await _buildLinux(
99-
environment,
100-
targetPlatform,
101-
projectUri,
102-
fileSystem,
103-
buildRunner,
104-
);
105-
case TargetPlatform.windows_arm64:
106-
case TargetPlatform.windows_x64:
107-
dependencies = await _buildWindows(
108-
environment,
109-
targetPlatform,
110-
projectUri,
111-
fileSystem,
112-
buildRunner,
113-
);
114-
case TargetPlatform.tester:
115-
if (const LocalPlatform().isMacOS) {
116-
(_, dependencies) = await buildNativeAssetsMacOS(
117-
buildMode: BuildMode.debug,
118-
projectUri: projectUri,
119-
codesignIdentity: environment.defines[kCodesignIdentity],
120-
yamlParentDirectory: environment.buildDir.uri,
121-
fileSystem: fileSystem,
122-
buildRunner: buildRunner,
123-
flutterTester: true,
124-
);
125-
} else if (const LocalPlatform().isLinux) {
126-
(_, dependencies) = await buildNativeAssetsLinux(
127-
buildMode: BuildMode.debug,
128-
projectUri: projectUri,
129-
yamlParentDirectory: environment.buildDir.uri,
130-
fileSystem: fileSystem,
131-
buildRunner: buildRunner,
132-
flutterTester: true,
133-
);
134-
} else if (const LocalPlatform().isWindows) {
135-
(_, dependencies) = await buildNativeAssetsWindows(
136-
buildMode: BuildMode.debug,
137-
projectUri: projectUri,
138-
yamlParentDirectory: environment.buildDir.uri,
139-
fileSystem: fileSystem,
140-
buildRunner: buildRunner,
141-
flutterTester: true,
142-
);
143-
} else {
144-
// TODO(dacoharkes): Implement other OSes. https://github.com/flutter/flutter/issues/129757
145-
// Write the file we claim to have in the [outputs].
146-
await writeNativeAssetsYaml(KernelAssets(), environment.buildDir.uri, fileSystem);
147-
dependencies = <Uri>[];
148-
}
149-
case TargetPlatform.android_arm:
150-
case TargetPlatform.android_arm64:
151-
case TargetPlatform.android_x64:
152-
case TargetPlatform.android_x86:
153-
case TargetPlatform.android:
154-
(_, dependencies) = await _buildAndroid(
155-
environment,
156-
targetPlatform,
157-
projectUri,
158-
fileSystem,
159-
buildRunner,
160-
);
161-
case TargetPlatform.fuchsia_arm64:
162-
case TargetPlatform.fuchsia_x64:
163-
case TargetPlatform.web_javascript:
164-
// TODO(dacoharkes): Implement other OSes. https://github.com/flutter/flutter/issues/129757
165-
// Write the file we claim to have in the [outputs].
166-
await writeNativeAssetsYaml(KernelAssets(), environment.buildDir.uri, fileSystem);
167-
dependencies = <Uri>[];
168-
}
74+
(result, _) = await runFlutterSpecificDartBuild(
75+
environmentDefines: environment.defines,
76+
buildRunner: buildRunner,
77+
targetPlatform: targetPlatform,
78+
projectUri: projectUri,
79+
nativeAssetsYamlUri : nativeAssetsFileUri,
80+
fileSystem: fileSystem,
81+
);
16982
}
17083

17184
final Depfile depfile = Depfile(
17285
<File>[
173-
for (final Uri dependency in dependencies) fileSystem.file(dependency),
86+
for (final Uri dependency in result.dependencies) fileSystem.file(dependency),
17487
],
17588
<File>[
176-
nativeAssetsFile,
89+
fileSystem.file(nativeAssetsFileUri),
17790
],
17891
);
17992
final File outputDepfile = environment.buildDir.childFile('native_assets.d');
18093
if (!outputDepfile.parent.existsSync()) {
18194
outputDepfile.parent.createSync(recursive: true);
18295
}
18396
environment.depFileService.writeToFile(depfile, outputDepfile);
184-
if (!await nativeAssetsFile.exists()) {
185-
throwToolExit("${nativeAssetsFile.path} doesn't exist.");
97+
if (!await fileSystem.file(nativeAssetsFileUri).exists()) {
98+
throwToolExit("${nativeAssetsFileUri.path} doesn't exist.");
18699
}
187100
if (!await outputDepfile.exists()) {
188101
throwToolExit("${outputDepfile.path} doesn't exist.");
189102
}
190103
}
191104

192-
Future<List<Uri>> _buildWindows(
193-
Environment environment,
194-
TargetPlatform targetPlatform,
195-
Uri projectUri,
196-
FileSystem fileSystem,
197-
NativeAssetsBuildRunner buildRunner,
198-
) async {
199-
final String? environmentBuildMode = environment.defines[kBuildMode];
200-
if (environmentBuildMode == null) {
201-
throw MissingDefineException(kBuildMode, name);
202-
}
203-
final BuildMode buildMode = BuildMode.fromCliName(environmentBuildMode);
204-
final (_, List<Uri> dependencies) = await buildNativeAssetsWindows(
205-
targetPlatform: targetPlatform,
206-
buildMode: buildMode,
207-
projectUri: projectUri,
208-
yamlParentDirectory: environment.buildDir.uri,
209-
fileSystem: fileSystem,
210-
buildRunner: buildRunner,
211-
);
212-
return dependencies;
213-
}
214-
215-
Future<List<Uri>> _buildLinux(
216-
Environment environment,
217-
TargetPlatform targetPlatform,
218-
Uri projectUri,
219-
FileSystem fileSystem,
220-
NativeAssetsBuildRunner buildRunner,
221-
) async {
222-
final String? environmentBuildMode = environment.defines[kBuildMode];
223-
if (environmentBuildMode == null) {
224-
throw MissingDefineException(kBuildMode, name);
225-
}
226-
final BuildMode buildMode = BuildMode.fromCliName(environmentBuildMode);
227-
final (_, List<Uri> dependencies) = await buildNativeAssetsLinux(
228-
targetPlatform: targetPlatform,
229-
buildMode: buildMode,
230-
projectUri: projectUri,
231-
yamlParentDirectory: environment.buildDir.uri,
232-
fileSystem: fileSystem,
233-
buildRunner: buildRunner,
234-
);
235-
return dependencies;
236-
}
237-
238-
Future<List<Uri>> _buildMacOS(
239-
Environment environment,
240-
Uri projectUri,
241-
FileSystem fileSystem,
242-
NativeAssetsBuildRunner buildRunner,
243-
) async {
244-
final List<DarwinArch> darwinArchs =
245-
_emptyToNull(environment.defines[kDarwinArchs])
246-
?.split(' ')
247-
.map(getDarwinArchForName)
248-
.toList() ??
249-
<DarwinArch>[DarwinArch.x86_64, DarwinArch.arm64];
250-
final String? environmentBuildMode = environment.defines[kBuildMode];
251-
if (environmentBuildMode == null) {
252-
throw MissingDefineException(kBuildMode, name);
253-
}
254-
final BuildMode buildMode = BuildMode.fromCliName(environmentBuildMode);
255-
final (_, List<Uri> dependencies) = await buildNativeAssetsMacOS(
256-
darwinArchs: darwinArchs,
257-
buildMode: buildMode,
258-
projectUri: projectUri,
259-
codesignIdentity: environment.defines[kCodesignIdentity],
260-
yamlParentDirectory: environment.buildDir.uri,
261-
fileSystem: fileSystem,
262-
buildRunner: buildRunner,
263-
);
264-
return dependencies;
265-
}
266-
267-
Future<List<Uri>> _buildIOS(
268-
Environment environment,
269-
Uri projectUri,
270-
FileSystem fileSystem,
271-
NativeAssetsBuildRunner buildRunner,
272-
) {
273-
final List<DarwinArch> iosArchs =
274-
_emptyToNull(environment.defines[kIosArchs])
275-
?.split(' ')
276-
.map(getIOSArchForName)
277-
.toList() ??
278-
<DarwinArch>[DarwinArch.arm64];
279-
final String? environmentBuildMode = environment.defines[kBuildMode];
280-
if (environmentBuildMode == null) {
281-
throw MissingDefineException(kBuildMode, name);
282-
}
283-
final BuildMode buildMode = BuildMode.fromCliName(environmentBuildMode);
284-
final String? sdkRoot = environment.defines[kSdkRoot];
285-
if (sdkRoot == null) {
286-
throw MissingDefineException(kSdkRoot, name);
287-
}
288-
final EnvironmentType environmentType =
289-
environmentTypeFromSdkroot(sdkRoot, environment.fileSystem)!;
290-
return buildNativeAssetsIOS(
291-
environmentType: environmentType,
292-
darwinArchs: iosArchs,
293-
buildMode: buildMode,
294-
projectUri: projectUri,
295-
codesignIdentity: environment.defines[kCodesignIdentity],
296-
fileSystem: fileSystem,
297-
buildRunner: buildRunner,
298-
yamlParentDirectory: environment.buildDir.uri,
299-
);
300-
}
301-
302-
Future<(Uri? nativeAssetsYaml, List<Uri> dependencies)> _buildAndroid(
303-
Environment environment,
304-
TargetPlatform targetPlatform,
305-
Uri projectUri,
306-
FileSystem fileSystem,
307-
NativeAssetsBuildRunner buildRunner) {
308-
final String? androidArchsEnvironment = environment.defines[kAndroidArchs];
309-
final List<AndroidArch> androidArchs = _androidArchs(
310-
targetPlatform,
311-
androidArchsEnvironment,
312-
);
313-
final int targetAndroidNdkApi =
314-
int.parse(environment.defines[kMinSdkVersion] ?? minSdkVersion);
315-
final String? environmentBuildMode = environment.defines[kBuildMode];
316-
if (environmentBuildMode == null) {
317-
throw MissingDefineException(kBuildMode, name);
318-
}
319-
final BuildMode buildMode = BuildMode.fromCliName(environmentBuildMode);
320-
return buildNativeAssetsAndroid(
321-
buildMode: buildMode,
322-
projectUri: projectUri,
323-
yamlParentDirectory: environment.buildDir.uri,
324-
fileSystem: fileSystem,
325-
buildRunner: buildRunner,
326-
androidArchs: androidArchs,
327-
targetAndroidNdkApi: targetAndroidNdkApi,
328-
);
329-
}
330-
331-
List<AndroidArch> _androidArchs(
332-
TargetPlatform targetPlatform,
333-
String? androidArchsEnvironment,
334-
) {
335-
switch (targetPlatform) {
336-
case TargetPlatform.android_arm:
337-
return <AndroidArch>[AndroidArch.armeabi_v7a];
338-
case TargetPlatform.android_arm64:
339-
return <AndroidArch>[AndroidArch.arm64_v8a];
340-
case TargetPlatform.android_x64:
341-
return <AndroidArch>[AndroidArch.x86_64];
342-
case TargetPlatform.android_x86:
343-
return <AndroidArch>[AndroidArch.x86];
344-
case TargetPlatform.android:
345-
if (androidArchsEnvironment == null) {
346-
throw MissingDefineException(kAndroidArchs, name);
347-
}
348-
return androidArchsEnvironment
349-
.split(' ')
350-
.map(getAndroidArchForName)
351-
.toList();
352-
case TargetPlatform.darwin:
353-
case TargetPlatform.fuchsia_arm64:
354-
case TargetPlatform.fuchsia_x64:
355-
case TargetPlatform.ios:
356-
case TargetPlatform.linux_arm64:
357-
case TargetPlatform.linux_x64:
358-
case TargetPlatform.tester:
359-
case TargetPlatform.web_javascript:
360-
case TargetPlatform.windows_x64:
361-
case TargetPlatform.windows_arm64:
362-
throwToolExit('Unsupported Android target platform: $targetPlatform.');
363-
}
364-
}
365-
366105
@override
367106
List<String> get depfiles => <String>[
368107
'native_assets.d',
@@ -390,10 +129,3 @@ class NativeAssets extends Target {
390129
Source.pattern('{BUILD_DIR}/native_assets.yaml'),
391130
];
392131
}
393-
394-
String? _emptyToNull(String? input) {
395-
if (input == null || input.isEmpty) {
396-
return null;
397-
}
398-
return input;
399-
}

0 commit comments

Comments
 (0)