Skip to content

Commit 4e814a5

Browse files
authored
Enable asset transformation for flutter build for iOS, Android, Windows, MacOS, Linux, and web (also flutter run without hot reload support) (#143815)
See title. These are are the platforms that use the `CopyAssets` `Target` as part of their build target. Partial implementation of flutter/flutter#143348.
1 parent 15f8ef7 commit 4e814a5

File tree

8 files changed

+767
-10
lines changed

8 files changed

+767
-10
lines changed

packages/flutter_tools/lib/src/asset.dart

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,12 @@ enum AssetKind {
8888
final class AssetBundleEntry {
8989
const AssetBundleEntry(this.content, {
9090
required this.kind,
91+
required this.transformers,
9192
});
9293

9394
final DevFSContent content;
9495
final AssetKind kind;
96+
final List<AssetTransformerEntry> transformers;
9597

9698
Future<List<int>> contentsAsBytes() => content.contentsAsBytes();
9799
}
@@ -264,6 +266,7 @@ class ManifestAssetBundle implements AssetBundle {
264266
entries[_kAssetManifestJsonFilename] = AssetBundleEntry(
265267
DevFSStringContent('{}'),
266268
kind: AssetKind.regular,
269+
transformers: const <AssetTransformerEntry>[],
267270
);
268271
final ByteData emptyAssetManifest =
269272
const StandardMessageCodec().encodeMessage(<dynamic, dynamic>{})!;
@@ -272,12 +275,14 @@ class ManifestAssetBundle implements AssetBundle {
272275
emptyAssetManifest.buffer.asUint8List(0, emptyAssetManifest.lengthInBytes),
273276
),
274277
kind: AssetKind.regular,
278+
transformers: const <AssetTransformerEntry>[],
275279
);
276280
// Create .bin.json on web builds.
277281
if (targetPlatform == TargetPlatform.web_javascript) {
278282
entries[_kAssetManifestBinJsonFilename] = AssetBundleEntry(
279283
DevFSStringContent('""'),
280284
kind: AssetKind.regular,
285+
transformers: const <AssetTransformerEntry>[],
281286
);
282287
}
283288
return 0;
@@ -423,6 +428,7 @@ class ManifestAssetBundle implements AssetBundle {
423428
entries[variant.entryUri.path] ??= AssetBundleEntry(
424429
DevFSFileContent(variantFile),
425430
kind: variant.kind,
431+
transformers: variant.transformers,
426432
);
427433
}
428434
}
@@ -456,6 +462,7 @@ class ManifestAssetBundle implements AssetBundle {
456462
deferredComponentsEntries[componentName]![variant.entryUri.path] ??= AssetBundleEntry(
457463
DevFSFileContent(variantFile),
458464
kind: AssetKind.regular,
465+
transformers: variant.transformers,
459466
);
460467
}
461468
}
@@ -471,7 +478,11 @@ class ManifestAssetBundle implements AssetBundle {
471478
for (final _Asset asset in materialAssets) {
472479
final File assetFile = asset.lookupAssetFile(_fileSystem);
473480
assert(assetFile.existsSync(), 'Missing ${assetFile.path}');
474-
entries[asset.entryUri.path] ??= AssetBundleEntry(DevFSFileContent(assetFile), kind: asset.kind);
481+
entries[asset.entryUri.path] ??= AssetBundleEntry(
482+
DevFSFileContent(assetFile),
483+
kind: asset.kind,
484+
transformers: const <AssetTransformerEntry>[],
485+
);
475486
}
476487

477488
// Update wildcard directories we can detect changes in them.
@@ -534,6 +545,7 @@ class ManifestAssetBundle implements AssetBundle {
534545
entries[key] = AssetBundleEntry(
535546
content,
536547
kind: assetKind,
548+
transformers: const <AssetTransformerEntry>[],
537549
);
538550
}
539551

@@ -579,6 +591,7 @@ class ManifestAssetBundle implements AssetBundle {
579591
hintString: 'copyrightsoftwaretothisinandorofthe',
580592
),
581593
kind: AssetKind.regular,
594+
transformers: const<AssetTransformerEntry>[],
582595
);
583596
}
584597
}
@@ -684,6 +697,8 @@ class ManifestAssetBundle implements AssetBundle {
684697
cache,
685698
componentAssets,
686699
assetsEntry.uri,
700+
flavors: assetsEntry.flavors,
701+
transformers: assetsEntry.transformers,
687702
);
688703
} else {
689704
_parseAssetFromFile(
@@ -693,6 +708,8 @@ class ManifestAssetBundle implements AssetBundle {
693708
cache,
694709
componentAssets,
695710
assetsEntry.uri,
711+
flavors: assetsEntry.flavors,
712+
transformers: assetsEntry.transformers,
696713
);
697714
}
698715
}
@@ -863,6 +880,7 @@ class ManifestAssetBundle implements AssetBundle {
863880
packageName: packageName,
864881
attributedPackage: attributedPackage,
865882
flavors: assetsEntry.flavors,
883+
transformers: assetsEntry.transformers,
866884
);
867885
} else {
868886
_parseAssetFromFile(
@@ -875,6 +893,7 @@ class ManifestAssetBundle implements AssetBundle {
875893
packageName: packageName,
876894
attributedPackage: attributedPackage,
877895
flavors: assetsEntry.flavors,
896+
transformers: assetsEntry.transformers,
878897
);
879898
}
880899
}
@@ -900,6 +919,8 @@ class ManifestAssetBundle implements AssetBundle {
900919
packageName: packageName,
901920
attributedPackage: attributedPackage,
902921
assetKind: AssetKind.shader,
922+
flavors: <String>{},
923+
transformers: <AssetTransformerEntry>[],
903924
);
904925
}
905926

@@ -914,6 +935,8 @@ class ManifestAssetBundle implements AssetBundle {
914935
packageName: packageName,
915936
attributedPackage: attributedPackage,
916937
assetKind: AssetKind.model,
938+
flavors: <String>{},
939+
transformers: <AssetTransformerEntry>[],
917940
);
918941
}
919942

@@ -927,6 +950,8 @@ class ManifestAssetBundle implements AssetBundle {
927950
packageName,
928951
attributedPackage,
929952
assetKind: AssetKind.font,
953+
flavors: <String>{},
954+
transformers: <AssetTransformerEntry>[],
930955
);
931956
final File baseAssetFile = baseAsset.lookupAssetFile(_fileSystem);
932957
if (!baseAssetFile.existsSync()) {
@@ -949,7 +974,8 @@ class ManifestAssetBundle implements AssetBundle {
949974
Uri assetUri, {
950975
String? packageName,
951976
Package? attributedPackage,
952-
Set<String>? flavors,
977+
required Set<String> flavors,
978+
required List<AssetTransformerEntry> transformers,
953979
}) {
954980
final String directoryPath;
955981
try {
@@ -985,6 +1011,7 @@ class ManifestAssetBundle implements AssetBundle {
9851011
attributedPackage: attributedPackage,
9861012
originUri: assetUri,
9871013
flavors: flavors,
1014+
transformers: transformers,
9881015
);
9891016
}
9901017
}
@@ -1000,7 +1027,8 @@ class ManifestAssetBundle implements AssetBundle {
10001027
String? packageName,
10011028
Package? attributedPackage,
10021029
AssetKind assetKind = AssetKind.regular,
1003-
Set<String>? flavors,
1030+
required Set<String> flavors,
1031+
required List<AssetTransformerEntry> transformers,
10041032
}) {
10051033
final _Asset asset = _resolveAsset(
10061034
packageConfig,
@@ -1011,6 +1039,7 @@ class ManifestAssetBundle implements AssetBundle {
10111039
assetKind: assetKind,
10121040
originUri: originUri,
10131041
flavors: flavors,
1042+
transformers: transformers,
10141043
);
10151044

10161045
_checkForFlavorConflicts(asset, result.keys.toList());
@@ -1032,6 +1061,8 @@ class ManifestAssetBundle implements AssetBundle {
10321061
relativeUri: relativeUri,
10331062
package: attributedPackage,
10341063
kind: assetKind,
1064+
flavors: flavors,
1065+
transformers: transformers,
10351066
),
10361067
);
10371068
}
@@ -1116,7 +1147,8 @@ class ManifestAssetBundle implements AssetBundle {
11161147
Package? attributedPackage, {
11171148
Uri? originUri,
11181149
AssetKind assetKind = AssetKind.regular,
1119-
Set<String>? flavors,
1150+
required Set<String> flavors,
1151+
required List<AssetTransformerEntry> transformers,
11201152
}) {
11211153
final String assetPath = _fileSystem.path.fromUri(assetUri);
11221154
if (assetUri.pathSegments.first == 'packages'
@@ -1130,6 +1162,7 @@ class ManifestAssetBundle implements AssetBundle {
11301162
assetKind: assetKind,
11311163
originUri: originUri,
11321164
flavors: flavors,
1165+
transformers: transformers,
11331166
);
11341167
if (packageAsset != null) {
11351168
return packageAsset;
@@ -1146,6 +1179,7 @@ class ManifestAssetBundle implements AssetBundle {
11461179
originUri: originUri,
11471180
kind: assetKind,
11481181
flavors: flavors,
1182+
transformers: transformers,
11491183
);
11501184
}
11511185

@@ -1156,6 +1190,7 @@ class ManifestAssetBundle implements AssetBundle {
11561190
AssetKind assetKind = AssetKind.regular,
11571191
Uri? originUri,
11581192
Set<String>? flavors,
1193+
List<AssetTransformerEntry>? transformers,
11591194
}) {
11601195
assert(assetUri.pathSegments.first == 'packages');
11611196
if (assetUri.pathSegments.length > 1) {
@@ -1171,6 +1206,7 @@ class ManifestAssetBundle implements AssetBundle {
11711206
kind: assetKind,
11721207
originUri: originUri,
11731208
flavors: flavors,
1209+
transformers: transformers,
11741210
);
11751211
}
11761212
}
@@ -1193,7 +1229,10 @@ class _Asset {
11931229
required this.package,
11941230
this.kind = AssetKind.regular,
11951231
Set<String>? flavors,
1196-
}): originUri = originUri ?? entryUri, flavors = flavors ?? const <String>{};
1232+
List<AssetTransformerEntry>? transformers,
1233+
}) : originUri = originUri ?? entryUri,
1234+
flavors = flavors ?? const <String>{},
1235+
transformers = transformers ?? const <AssetTransformerEntry>[];
11971236

11981237
final String baseDir;
11991238

@@ -1214,6 +1253,8 @@ class _Asset {
12141253

12151254
final Set<String> flavors;
12161255

1256+
final List<AssetTransformerEntry> transformers;
1257+
12171258
File lookupAssetFile(FileSystem fileSystem) {
12181259
return fileSystem.file(fileSystem.path.join(baseDir, fileSystem.path.fromUri(relativeUri)));
12191260
}

packages/flutter_tools/lib/src/base/utils.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,3 +498,19 @@ bool setEquals<T>(Set<T>? a, Set<T>? b) {
498498
}
499499
return true;
500500
}
501+
502+
/// Tests for shallow equality on two lists.
503+
bool listEquals<T>(List<T> a, List<T> b) {
504+
if (identical(a, b)) {
505+
return true;
506+
}
507+
if (a.length != b.length) {
508+
return false;
509+
}
510+
for (int index = 0; index < a.length; index++) {
511+
if (a[index] != b[index]) {
512+
return false;
513+
}
514+
}
515+
return true;
516+
}

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

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44

55
import 'package:pool/pool.dart';
66

7+
import '../../artifacts.dart';
78
import '../../asset.dart';
9+
import '../../base/common.dart';
810
import '../../base/file_system.dart';
911
import '../../base/logger.dart';
1012
import '../../build_info.dart';
1113
import '../../convert.dart';
1214
import '../../devfs.dart';
15+
import '../../flutter_manifest.dart';
1316
import '../build_system.dart';
1417
import '../depfile.dart';
18+
import '../tools/asset_transformer.dart';
1519
import '../tools/scene_importer.dart';
1620
import '../tools/shader_compiler.dart';
1721
import 'common.dart';
@@ -93,19 +97,29 @@ Future<Depfile> copyAssets(
9397
fileSystem: environment.fileSystem,
9498
artifacts: environment.artifacts,
9599
);
100+
final AssetTransformer assetTransformer = AssetTransformer(
101+
processManager: environment.processManager,
102+
fileSystem: environment.fileSystem,
103+
dartBinaryPath: environment.artifacts.getArtifactPath(Artifact.engineDartBinary),
104+
);
96105

97106
final Map<String, AssetBundleEntry> assetEntries = <String, AssetBundleEntry>{
98107
...assetBundle.entries,
99108
...additionalContent.map((String key, DevFSContent value) {
100109
return MapEntry<String, AssetBundleEntry>(
101110
key,
102-
AssetBundleEntry(value, kind: AssetKind.regular),
111+
AssetBundleEntry(
112+
value,
113+
kind: AssetKind.regular,
114+
transformers: const <AssetTransformerEntry>[],
115+
),
103116
);
104117
}),
105118
if (skslBundle != null)
106119
kSkSLShaderBundlePath: AssetBundleEntry(
107120
skslBundle,
108121
kind: AssetKind.regular,
122+
transformers: const <AssetTransformerEntry>[],
109123
),
110124
};
111125

@@ -128,7 +142,18 @@ Future<Depfile> copyAssets(
128142
bool doCopy = true;
129143
switch (entry.value.kind) {
130144
case AssetKind.regular:
131-
break;
145+
if (entry.value.transformers.isNotEmpty) {
146+
final AssetTransformationFailure? failure = await assetTransformer.transformAsset(
147+
asset: content.file as File,
148+
outputPath: file.path,
149+
workingDirectory: environment.projectDir.path,
150+
transformerEntries: entry.value.transformers,
151+
);
152+
doCopy = false;
153+
if (failure != null) {
154+
throwToolExit(failure.message);
155+
}
156+
}
132157
case AssetKind.font:
133158
doCopy = !await iconTreeShaker.subsetFont(
134159
input: content.file as File,

0 commit comments

Comments
 (0)