Skip to content

Commit

Permalink
[flutter_tools] build ios-frameworks: option to exclude plugin framew…
Browse files Browse the repository at this point in the history
…orks from the build (#129739)

A lot of details are written in the feature request: #114692.

tl;dr: Options B & C from the add2app iOS guide have a limitation (build error) in case the Flutter plugin and native iOS app have a shared dependency. We can use a workaround to avoid the issue, but in this case we don't need to build frameworks for plugins.

Closes #114692
Part of #130220
  • Loading branch information
p-mazhnik committed Dec 4, 2023
1 parent f387b77 commit 0f67c99
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 2 deletions.
83 changes: 83 additions & 0 deletions dev/devicelab/bin/tasks/build_ios_framework_module_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,12 @@ Future<void> _testBuildIosFramework(Directory projectDir, { bool isModule = fals
isModule) {
throw TaskResult.failure('Unexpected GeneratedPluginRegistrant.m.');
}

section('Build frameworks without plugins');
await _testBuildFrameworksWithoutPlugins(projectDir, platform: 'ios');

section('check --static cannot be used with the --no-plugins flag');
await _testStaticAndNoPlugins(projectDir);
}


Expand Down Expand Up @@ -816,6 +822,83 @@ Future<void> _testBuildMacOSFramework(Directory projectDir) async {
outputPath,
'GeneratedPluginRegistrant.swift',
));

section('Build frameworks without plugins');
await _testBuildFrameworksWithoutPlugins(projectDir, platform: 'macos');
}

Future<void> _testBuildFrameworksWithoutPlugins(Directory projectDir, { required String platform}) async {
const String noPluginsOutputDir = 'flutter-frameworks-no-plugins';

await inDirectory(projectDir, () async {
await flutter(
'build',
options: <String>[
'$platform-framework',
'--cocoapods',
'--force', // Allow podspec creation on master.
'--output=$noPluginsOutputDir',
'--no-plugins',
],
);
});

final String noPluginsOutputPath = path.join(projectDir.path, noPluginsOutputDir);
for (final String mode in <String>['Debug', 'Profile', 'Release']) {
checkFileExists(path.join(
noPluginsOutputPath,
mode,
'Flutter${platform == 'macos' ? 'MacOS' : ''}.podspec',
));
checkDirectoryExists(path.join(
noPluginsOutputPath,
mode,
'App.xcframework',
));

checkDirectoryNotExists(path.join(
noPluginsOutputPath,
mode,
'package_info.xcframework',
));

checkDirectoryNotExists(path.join(
noPluginsOutputPath,
mode,
'connectivity.xcframework',
));

checkDirectoryNotExists(path.join(
noPluginsOutputPath,
mode,
'Reachability.xcframework',
));
}
}

Future<void> _testStaticAndNoPlugins(Directory projectDir) async {
const String noPluginsOutputDir = 'flutter-frameworks-no-plugins-static';
final ProcessResult result = await inDirectory(projectDir, () async {
return executeFlutter(
'build',
options: <String>[
'ios-framework',
'--cocoapods',
'--force', // Allow podspec creation on master.
'--output=$noPluginsOutputDir',
'--no-plugins',
'--static'
],
canFail: true
);
});
if (result.exitCode == 0) {
throw TaskResult.failure('Build framework command did not exit with error as expected');
}
final String output = '${result.stdout}\n${result.stderr}';
if (!output.contains('--static cannot be used with the --no-plugins flag')) {
throw TaskResult.failure(output);
}
}

Future<void> _checkDylib(String pathToLibrary) async {
Expand Down
11 changes: 10 additions & 1 deletion packages/flutter_tools/lib/src/commands/build_ios_framework.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ abstract class BuildFrameworkCommand extends BuildSubCommand {
..addFlag('cocoapods',
help: 'Produce a Flutter.podspec instead of an engine Flutter.xcframework (recommended if host app uses CocoaPods).',
)
..addFlag('plugins',
defaultsTo: true,
help: 'Whether to produce frameworks for the plugins. '
'This is intended for cases where plugins are already being built separately.',
)
..addFlag('static',
help: 'Build plugins as static frameworks. Link on, but do not embed these frameworks in the existing Xcode project.',
)
Expand Down Expand Up @@ -135,6 +140,10 @@ abstract class BuildFrameworkCommand extends BuildSubCommand {
if ((await getBuildInfos()).isEmpty) {
throwToolExit('At least one of "--debug" or "--profile", or "--release" is required.');
}

if (!boolArg('plugins') && boolArg('static')) {
throwToolExit('--static cannot be used with the --no-plugins flag');
}
}

static Future<void> produceXCFramework(
Expand Down Expand Up @@ -264,7 +273,7 @@ class BuildIOSFrameworkCommand extends BuildFrameworkCommand {

// Build and copy plugins.
await processPodsIfNeeded(project.ios, getIosBuildDirectory(), buildInfo.mode);
if (hasPlugins(project)) {
if (boolArg('plugins') && hasPlugins(project)) {
await _producePlugins(buildInfo.mode, xcodeBuildConfiguration, iPhoneBuildOutput, simulatorBuildOutput, modeDirectory);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class BuildMacOSFrameworkCommand extends BuildFrameworkCommand {
// Build and copy plugins.
final Directory buildOutput = modeDirectory.childDirectory('macos');
await processPodsIfNeeded(project.macos, getMacOSBuildDirectory(), buildInfo.mode);
if (hasPlugins(project)) {
if (boolArg('plugins') && hasPlugins(project)) {
await _producePlugins(xcodeBuildConfiguration, buildOutput, modeDirectory);
}

Expand Down

0 comments on commit 0f67c99

Please sign in to comment.