diff --git a/.ci/targets/ios_platform_tests.yaml b/.ci/targets/ios_platform_tests.yaml index b961b675d6b..e679834961f 100644 --- a/.ci/targets/ios_platform_tests.yaml +++ b/.ci/targets/ios_platform_tests.yaml @@ -11,7 +11,7 @@ tasks: infra_step: true - name: build examples script: .ci/scripts/tool_runner.sh - args: ["build-examples", "--ios"] + args: ["build-examples", "--ios", "--swift-package-manager"] - name: xcode analyze script: .ci/scripts/tool_runner.sh args: ["xcode-analyze", "--ios"] diff --git a/.ci/targets/macos_platform_tests.yaml b/.ci/targets/macos_platform_tests.yaml index bc1b915e561..1dd105f109f 100644 --- a/.ci/targets/macos_platform_tests.yaml +++ b/.ci/targets/macos_platform_tests.yaml @@ -8,7 +8,7 @@ tasks: infra_step: true - name: build examples script: .ci/scripts/tool_runner.sh - args: ["build-examples", "--macos"] + args: ["build-examples", "--macos", "--swift-package-manager"] - name: xcode analyze script: .ci/scripts/tool_runner.sh args: ["xcode-analyze", "--macos"] diff --git a/script/tool/lib/src/build_examples_command.dart b/script/tool/lib/src/build_examples_command.dart index 0f78d39114f..d8d1613e06d 100644 --- a/script/tool/lib/src/build_examples_command.dart +++ b/script/tool/lib/src/build_examples_command.dart @@ -38,6 +38,9 @@ const String _flutterBuildTypeWindows = 'windows'; const String _flutterBuildTypeAndroidAlias = 'android'; +/// Key for Swift Package Manager. +const String _swiftPackageManagerFlag = 'swift-package-manager'; + /// A command to build the example applications for packages. class BuildExamplesCommand extends PackageLoopingCommand { /// Creates an instance of the build command. @@ -58,6 +61,7 @@ class BuildExamplesCommand extends PackageLoopingCommand { defaultsTo: '', help: 'Enables the given Dart SDK experiments.', ); + argParser.addFlag(_swiftPackageManagerFlag); } // Maps the switch this command uses to identify a platform to information @@ -111,6 +115,15 @@ class BuildExamplesCommand extends PackageLoopingCommand { 'single key "$_pluginToolsConfigGlobalKey" containing a list of build ' 'arguments.'; + /// Returns true if `--swift-package-manager` flag was passed along with + /// either `--ios` or `--macos`. + bool get usingSwiftPackageManager { + final List platformFlags = _platforms.keys.toList(); + return getBoolArg(_swiftPackageManagerFlag) && + (platformFlags.contains(platformIOS) || + platformFlags.contains(platformMacOS)); + } + @override Future initializeRun() async { final List platformFlags = _platforms.keys.toList(); @@ -121,6 +134,17 @@ class BuildExamplesCommand extends PackageLoopingCommand { 'were specified. At least one platform must be provided.'); throw ToolExit(_exitNoPlatformFlags); } + + // TODO(vashworth): Enable on stable once Swift Package Manager feature is + // available on stable. + if (usingSwiftPackageManager && + platform.environment['CHANNEL'] != 'stable') { + await processRunner.runAndStream( + flutterCommand, + ['config', '--enable-swift-package-manager'], + exitOnError: true, + ); + } } @override diff --git a/script/tool/test/build_examples_command_test.dart b/script/tool/test/build_examples_command_test.dart index 2f58dac87c8..0c99bfb9ba3 100644 --- a/script/tool/test/build_examples_command_test.dart +++ b/script/tool/test/build_examples_command_test.dart @@ -164,6 +164,98 @@ void main() { ])); }); + test('building for iOS with Swift Package Manager on master channel', + () async { + mockPlatform.isMacOS = true; + mockPlatform.environment['CHANNEL'] = 'master'; + + final RepositoryPackage plugin = createFakePlugin('plugin', packagesDir, + platformSupport: { + platformIOS: const PlatformDetails(PlatformSupport.inline), + }); + + final Directory pluginExampleDirectory = getExampleDir(plugin); + + final List output = await runCapturingPrint(runner, [ + 'build-examples', + '--ios', + '--enable-experiment=exp1', + '--swift-package-manager', + ]); + + expect( + output, + containsAllInOrder([ + '\nBUILDING plugin/example for iOS', + ]), + ); + + expect( + processRunner.recordedCalls, + orderedEquals([ + ProcessCall( + getFlutterCommand(mockPlatform), + const ['config', '--enable-swift-package-manager'], + null, + ), + ProcessCall( + getFlutterCommand(mockPlatform), + const [ + 'build', + 'ios', + '--no-codesign', + '--enable-experiment=exp1' + ], + pluginExampleDirectory.path, + ), + ]), + ); + }); + + test( + 'building for iOS with Swift Package Manager on stable channel does not enable SPM', + () async { + mockPlatform.isMacOS = true; + mockPlatform.environment['CHANNEL'] = 'stable'; + + final RepositoryPackage plugin = createFakePlugin('plugin', packagesDir, + platformSupport: { + platformIOS: const PlatformDetails(PlatformSupport.inline), + }); + + final Directory pluginExampleDirectory = getExampleDir(plugin); + + final List output = await runCapturingPrint(runner, [ + 'build-examples', + '--ios', + '--enable-experiment=exp1', + '--swift-package-manager', + ]); + + expect( + output, + containsAllInOrder([ + '\nBUILDING plugin/example for iOS', + ]), + ); + + expect( + processRunner.recordedCalls, + orderedEquals([ + ProcessCall( + getFlutterCommand(mockPlatform), + const [ + 'build', + 'ios', + '--no-codesign', + '--enable-experiment=exp1' + ], + pluginExampleDirectory.path, + ), + ]), + ); + }); + test( 'building for Linux when plugin is not set up for Linux results in no-op', () async { @@ -261,6 +353,86 @@ void main() { ])); }); + test('building for macOS with Swift Package Manager on master channel', + () async { + mockPlatform.isMacOS = true; + mockPlatform.environment['CHANNEL'] = 'master'; + + final RepositoryPackage plugin = createFakePlugin('plugin', packagesDir, + platformSupport: { + platformMacOS: const PlatformDetails(PlatformSupport.inline), + }); + + final Directory pluginExampleDirectory = getExampleDir(plugin); + + final List output = await runCapturingPrint(runner, + ['build-examples', '--macos', '--swift-package-manager']); + + expect( + output, + containsAllInOrder([ + '\nBUILDING plugin/example for macOS', + ]), + ); + + expect( + processRunner.recordedCalls, + orderedEquals([ + ProcessCall( + getFlutterCommand(mockPlatform), + const ['config', '--enable-swift-package-manager'], + null, + ), + ProcessCall( + getFlutterCommand(mockPlatform), + const [ + 'build', + 'macos', + ], + pluginExampleDirectory.path, + ), + ]), + ); + }); + + test( + 'building for macOS with Swift Package Manager on stable channel does not enable SPM', + () async { + mockPlatform.isMacOS = true; + mockPlatform.environment['CHANNEL'] = 'stable'; + + final RepositoryPackage plugin = createFakePlugin('plugin', packagesDir, + platformSupport: { + platformMacOS: const PlatformDetails(PlatformSupport.inline), + }); + + final Directory pluginExampleDirectory = getExampleDir(plugin); + + final List output = await runCapturingPrint(runner, + ['build-examples', '--macos', '--swift-package-manager']); + + expect( + output, + containsAllInOrder([ + '\nBUILDING plugin/example for macOS', + ]), + ); + + expect( + processRunner.recordedCalls, + orderedEquals([ + ProcessCall( + getFlutterCommand(mockPlatform), + const [ + 'build', + 'macos', + ], + pluginExampleDirectory.path, + ), + ]), + ); + }); + test('building for web with no implementation results in no-op', () async { createFakePlugin('plugin', packagesDir);