diff --git a/dev/devicelab/bin/tasks/build_ios_framework_module_test.dart b/dev/devicelab/bin/tasks/build_ios_framework_module_test.dart index 0c03fe769b4..eb433c46fb3 100644 --- a/dev/devicelab/bin/tasks/build_ios_framework_module_test.dart +++ b/dev/devicelab/bin/tasks/build_ios_framework_module_test.dart @@ -493,6 +493,12 @@ Future _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); } @@ -816,6 +822,83 @@ Future _testBuildMacOSFramework(Directory projectDir) async { outputPath, 'GeneratedPluginRegistrant.swift', )); + + section('Build frameworks without plugins'); + await _testBuildFrameworksWithoutPlugins(projectDir, platform: 'macos'); +} + +Future _testBuildFrameworksWithoutPlugins(Directory projectDir, { required String platform}) async { + const String noPluginsOutputDir = 'flutter-frameworks-no-plugins'; + + await inDirectory(projectDir, () async { + await flutter( + 'build', + options: [ + '$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 ['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 _testStaticAndNoPlugins(Directory projectDir) async { + const String noPluginsOutputDir = 'flutter-frameworks-no-plugins-static'; + final ProcessResult result = await inDirectory(projectDir, () async { + return executeFlutter( + 'build', + options: [ + '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 _checkDylib(String pathToLibrary) async { diff --git a/packages/flutter_tools/lib/src/commands/build_ios_framework.dart b/packages/flutter_tools/lib/src/commands/build_ios_framework.dart index 43d17e150aa..5d58a0390e6 100644 --- a/packages/flutter_tools/lib/src/commands/build_ios_framework.dart +++ b/packages/flutter_tools/lib/src/commands/build_ios_framework.dart @@ -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.', ) @@ -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 produceXCFramework( @@ -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); } diff --git a/packages/flutter_tools/lib/src/commands/build_macos_framework.dart b/packages/flutter_tools/lib/src/commands/build_macos_framework.dart index 754dcb4997d..7d6c1fee266 100644 --- a/packages/flutter_tools/lib/src/commands/build_macos_framework.dart +++ b/packages/flutter_tools/lib/src/commands/build_macos_framework.dart @@ -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); }