Skip to content

Commit c48558f

Browse files
authored
Build App and native asset frameworks for Add to App FlutterPluginRegistrant (flutter#183136)
Generates XCFrameworks for the App and any native assets and places them with the `FlutterPluginRegistrant` Swift package. ``` ├── FlutterPluginRegistrant │ ├── Debug/Profile/Release │ │ ├── Frameworks │ │ │ ├── App.xcframework │ │ │ ├── NativeAssets │ │ │ │ ├── my_native_asset.xcframework ``` Build artifacts are stored in a `.cache` directory to make incremental builds faster. Fixes flutter#181209. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
1 parent e529486 commit c48558f

10 files changed

Lines changed: 1511 additions & 48 deletions

File tree

packages/flutter_tools/lib/src/build_info.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,11 @@ const kXcodeBuildScriptValueBuild = 'build';
11401140
/// embedding.
11411141
const kXcodeBuildScriptValueEmbed = 'embed';
11421142

1143+
/// Whether the build is originating from the `flutter build swift-package` command.
1144+
///
1145+
/// Expects value of "true".
1146+
const kBuildSwiftPackage = 'BuildSwiftPackage';
1147+
11431148
final Converter<String, String> _defineEncoder = utf8.encoder.fuse(base64.encoder);
11441149
final Converter<String, String> _defineDecoder = base64.decoder.fuse(utf8.decoder);
11451150

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ Future<Depfile> copyAssets(
108108
}),
109109
};
110110

111+
// Suppress IconTreeShaker summary messages
112+
final quiet = environment.defines[kBuildSwiftPackage] == 'true';
113+
111114
await Future.wait<void>(
112115
assetEntries.entries.map<Future<void>>((MapEntry<String, AssetBundleEntry> entry) async {
113116
final PoolResource copyResource = await copyFilesPool.request();
@@ -152,6 +155,7 @@ Future<Depfile> copyAssets(
152155
input: content.file as File,
153156
outputPath: file.path,
154157
relativePath: entry.key,
158+
quiet: quiet,
155159
);
156160
case AssetKind.shader:
157161
doCopy = !await shaderCompiler.compileShader(
@@ -221,6 +225,7 @@ Future<Depfile> copyAssets(
221225
input: content.file as File,
222226
outputPath: file.path,
223227
relativePath: entry.key,
228+
quiet: quiet,
224229
)) {
225230
await (content.file as File).copy(file.path);
226231
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ abstract class UnpackDarwin extends Target {
1717
@visibleForOverriding
1818
FlutterDarwinPlatform get darwinPlatform;
1919

20+
@override
21+
Future<bool> canSkip(Environment environment) async {
22+
// The `build swift-package` command copies the Flutter.xcframework separately and therefore
23+
// does not need it to be done by the build system.
24+
return environment.defines[kBuildSwiftPackage] == 'true';
25+
}
26+
2027
/// Copies the [framework] artifact using `rsync` to the [Environment.outputDir].
2128
/// Throws an error if copy fails.
2229
@protected

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ class IconTreeShaker {
164164
required File input,
165165
required String outputPath,
166166
required String relativePath,
167+
bool quiet = false,
167168
}) async {
168169
if (!enabled) {
169170
return false;
@@ -223,7 +224,12 @@ class IconTreeShaker {
223224
_logger.printError(await utf8.decodeStream(fontSubsetProcess.stderr));
224225
throw IconTreeShakerException._('Font subsetting failed with exit code $code.');
225226
}
226-
_logger.printStatus(getSubsetSummaryMessage(input, _fs.file(outputPath)));
227+
final String message = getSubsetSummaryMessage(input, _fs.file(outputPath));
228+
if (quiet) {
229+
_logger.printTrace(message);
230+
} else {
231+
_logger.printStatus(message);
232+
}
227233
return true;
228234
}
229235

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,12 @@ class DebugIosLLDBInit extends Target {
519519
@override
520520
List<Target> get dependencies => <Target>[];
521521

522+
@override
523+
Future<bool> canSkip(Environment environment) async {
524+
// The `build swift-package` is not run on a device and therefore does not need an LLDB Init File.
525+
return environment.defines[kBuildSwiftPackage] == 'true';
526+
}
527+
522528
@override
523529
Future<void> build(Environment environment) async {
524530
final String? sdkRoot = environment.defines[kSdkRoot];

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ class CompileMacOSFramework extends Target {
313313
extraGenSnapshotOptions.add('--trace-precompiler-to=${precompilerTraceFile.path}');
314314
}
315315

316+
// Suppress AOTSnapshotter build status logs
317+
final quiet = environment.defines[kBuildSwiftPackage] == 'true';
318+
316319
pending.add(
317320
snapshotter.build(
318321
buildMode: buildMode,
@@ -323,6 +326,7 @@ class CompileMacOSFramework extends Target {
323326
splitDebugInfo: splitDebugInfo,
324327
dartObfuscation: dartObfuscation,
325328
extraGenSnapshotOptions: extraGenSnapshotOptions,
329+
quiet: quiet,
326330
),
327331
);
328332
}

packages/flutter_tools/lib/src/commands/build_ios_framework.dart

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,24 @@ abstract class BuildFrameworkCommand extends BuildSubCommand {
163163
/// Parses the NativeAssetsManifest.json in [outputDirectory] and returns a
164164
/// mapping from asset ID to the path of the code asset within the bundle
165165
/// (e.g., "MyFramework.framework/MyFramework").
166-
static Map<String, String> parseNativeAssetsManifest(Directory outputDirectory) {
167-
final File manifestFile = outputDirectory
168-
.childDirectory('App.framework')
169-
.childDirectory('flutter_assets')
170-
.childFile('NativeAssetsManifest.json');
166+
static Map<String, String> parseNativeAssetsManifest(
167+
Directory outputDirectory,
168+
FlutterDarwinPlatform platform,
169+
) {
170+
File manifestFile;
171+
switch (platform) {
172+
case FlutterDarwinPlatform.ios:
173+
manifestFile = outputDirectory
174+
.childDirectory('App.framework')
175+
.childDirectory('flutter_assets')
176+
.childFile('NativeAssetsManifest.json');
177+
case FlutterDarwinPlatform.macos:
178+
manifestFile = outputDirectory
179+
.childDirectory('App.framework')
180+
.childDirectory('Resources')
181+
.childDirectory('flutter_assets')
182+
.childFile('NativeAssetsManifest.json');
183+
}
171184
if (!manifestFile.existsSync()) {
172185
return const <String, String>{};
173186
}
@@ -205,9 +218,11 @@ abstract class BuildFrameworkCommand extends BuildSubCommand {
205218
) {
206219
final Map<String, String> deviceAssets = BuildFrameworkCommand.parseNativeAssetsManifest(
207220
iPhoneBuildOutput,
221+
FlutterDarwinPlatform.ios,
208222
);
209223
final Map<String, String> simulatorAssets = BuildFrameworkCommand.parseNativeAssetsManifest(
210224
simulatorBuildOutput,
225+
FlutterDarwinPlatform.ios,
211226
);
212227

213228
for (final String assetId in deviceAssets.keys) {

0 commit comments

Comments
 (0)