[SwiftPM] Update .flutter-plugin-dependencies format (#158138)

In the future, it will be possible for Swift Package Manager to be enabled on one but not all platforms (see https://github.com/flutter/flutter/issues/151567#issuecomment-2455941279).

This updates the `.flutter-plugin-dependencies` file format to separate iOS's and macOS's SwiftPM enablement. For now, these platforms will always have the same value.

This `.flutter-plugin-dependencies` file is read by our CocoaPods scripts to determine whether we should use CocoaPods or not to inject plugins.

Part of https://github.com/flutter/flutter/issues/151567
This commit is contained in:
Loïc Sharma 2024-11-12 12:01:26 -08:00 committed by GitHub
parent 37d80ce25f
commit 003135e2d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 63 additions and 18 deletions

View File

@ -210,7 +210,7 @@ public class DummyPluginAClass {
final String flutterPluginsDependenciesFileContent = flutterPluginsDependenciesFile.readAsStringSync(); final String flutterPluginsDependenciesFileContent = flutterPluginsDependenciesFile.readAsStringSync();
final Map<String, dynamic> jsonContent = json.decode(flutterPluginsDependenciesFileContent) as Map<String, dynamic>; final Map<String, dynamic> jsonContent = json.decode(flutterPluginsDependenciesFileContent) as Map<String, dynamic>;
final bool swiftPackageManagerEnabled = jsonContent['swift_package_manager_enabled'] as bool? ?? false; final Map<String, dynamic>? swiftPackageManagerJson = jsonContent['swift_package_manager_enabled'] as Map<String, dynamic>?;
// Verify the dependencyGraph object is valid. The rest of the contents of this file are not relevant to the // Verify the dependencyGraph object is valid. The rest of the contents of this file are not relevant to the
// dependency graph and are tested by unit tests. // dependency graph and are tested by unit tests.
@ -304,6 +304,18 @@ public class DummyPluginAClass {
return TaskResult.failure('Failed to build plugin A example iOS app'); return TaskResult.failure('Failed to build plugin A example iOS app');
} }
final bool? swiftPackageManagerEnabled = swiftPackageManagerJson?['ios'] as bool?;
if (swiftPackageManagerEnabled == null) {
return TaskResult.failure(
'${flutterPluginsDependenciesFile.path} is missing the '
'"swift_package_manager_enabled" > "ios" property.\n'
'\n'
'.flutter_plugin_dependencies content:\n'
'\n'
'$flutterPluginsDependenciesFileContent',
);
}
if (swiftPackageManagerEnabled) { if (swiftPackageManagerEnabled) {
// Check plugins are built statically if using SwiftPM. // Check plugins are built statically if using SwiftPM.
final String executable = path.join(appBundle.path, 'Runner'); final String executable = path.join(appBundle.path, 'Runner');

View File

@ -304,7 +304,7 @@ def flutter_install_plugin_pods(application_path = nil, relative_symlink_dir, pl
plugins_file = File.join(application_path, '..', '.flutter-plugins-dependencies') plugins_file = File.join(application_path, '..', '.flutter-plugins-dependencies')
dependencies_hash = flutter_parse_plugins_file(plugins_file) dependencies_hash = flutter_parse_plugins_file(plugins_file)
plugin_pods = flutter_get_plugins_list(dependencies_hash, platform) plugin_pods = flutter_get_plugins_list(dependencies_hash, platform)
swift_package_manager_enabled = flutter_get_swift_package_manager_enabled(dependencies_hash) swift_package_manager_enabled = flutter_get_swift_package_manager_enabled(dependencies_hash, platform)
plugin_pods.each do |plugin_hash| plugin_pods.each do |plugin_hash|
plugin_name = plugin_hash['name'] plugin_name = plugin_hash['name']
@ -353,10 +353,12 @@ def flutter_get_plugins_list(dependencies_hash, platform)
dependencies_hash['plugins'][platform] || [] dependencies_hash['plugins'][platform] || []
end end
def flutter_get_swift_package_manager_enabled(dependencies_hash) def flutter_get_swift_package_manager_enabled(dependencies_hash, platform)
return false unless dependencies_hash.any? return false unless dependencies_hash.any?
return false unless dependencies_hash.has_key?('swift_package_manager_enabled') return false unless dependencies_hash.has_key?('swift_package_manager_enabled')
dependencies_hash['swift_package_manager_enabled'] == true return false unless dependencies_hash['swift_package_manager_enabled'].has_key?(platform)
dependencies_hash['swift_package_manager_enabled'][platform] == true
end end
def flutter_relative_path_from_podfile(path) def flutter_relative_path_from_podfile(path)

View File

@ -214,7 +214,8 @@ const String _kFlutterPluginsSharedDarwinSource = 'shared_darwin_source';
bool _writeFlutterPluginsList( bool _writeFlutterPluginsList(
FlutterProject project, FlutterProject project,
List<Plugin> plugins, { List<Plugin> plugins, {
bool forceCocoaPodsOnly = false, required bool swiftPackageManagerEnabledIos,
required bool swiftPackageManagerEnabledMacos,
}) { }) {
final File pluginsFile = project.flutterPluginsDependenciesFile; final File pluginsFile = project.flutterPluginsDependenciesFile;
if (plugins.isEmpty) { if (plugins.isEmpty) {
@ -250,7 +251,11 @@ bool _writeFlutterPluginsList(
result['dependencyGraph'] = _createPluginLegacyDependencyGraph(plugins); result['dependencyGraph'] = _createPluginLegacyDependencyGraph(plugins);
result['date_created'] = globals.systemClock.now().toString(); result['date_created'] = globals.systemClock.now().toString();
result['version'] = globals.flutterVersion.frameworkVersion; result['version'] = globals.flutterVersion.frameworkVersion;
result['swift_package_manager_enabled'] = !forceCocoaPodsOnly && project.usesSwiftPackageManager;
result['swift_package_manager_enabled'] = <String, bool>{
'ios': swiftPackageManagerEnabledIos,
'macos': swiftPackageManagerEnabledMacos,
};
// Only notify if the plugins list has changed. [date_created] will always be different, // Only notify if the plugins list has changed. [date_created] will always be different,
// [version] is not relevant for this check. // [version] is not relevant for this check.
@ -1065,10 +1070,12 @@ Future<void> refreshPluginsList(
// Write the legacy plugin files to avoid breaking existing apps. // Write the legacy plugin files to avoid breaking existing apps.
final bool legacyChanged = useImplicitPubspecResolution && _writeFlutterPluginsListLegacy(project, plugins); final bool legacyChanged = useImplicitPubspecResolution && _writeFlutterPluginsListLegacy(project, plugins);
final bool swiftPackageManagerEnabled = !forceCocoaPodsOnly && project.usesSwiftPackageManager;
final bool changed = _writeFlutterPluginsList( final bool changed = _writeFlutterPluginsList(
project, project,
plugins, plugins,
forceCocoaPodsOnly: forceCocoaPodsOnly, swiftPackageManagerEnabledIos: swiftPackageManagerEnabled,
swiftPackageManagerEnabledMacos: swiftPackageManagerEnabled,
); );
if (changed || legacyChanged || forceCocoaPodsOnly) { if (changed || legacyChanged || forceCocoaPodsOnly) {
createPluginSymlinks(project, force: true); createPluginSymlinks(project, force: true);

View File

@ -548,7 +548,15 @@ dependencies:
expect(jsonContent['dependencyGraph'], expectedDependencyGraph); expect(jsonContent['dependencyGraph'], expectedDependencyGraph);
expect(jsonContent['date_created'], dateCreated.toString()); expect(jsonContent['date_created'], dateCreated.toString());
expect(jsonContent['version'], '1.0.0'); expect(jsonContent['version'], '1.0.0');
expect(jsonContent['swift_package_manager_enabled'], false);
final Map<String, dynamic> expectedSwiftPackageManagerEnabled = <String, bool>{
'ios': false,
'macos': false,
};
expect(
jsonContent['swift_package_manager_enabled'],
expectedSwiftPackageManagerEnabled,
);
// Make sure tests are updated if a new object is added/removed. // Make sure tests are updated if a new object is added/removed.
final List<String> expectedKeys = <String>[ final List<String> expectedKeys = <String>[
@ -665,7 +673,14 @@ dependencies:
.readAsStringSync(); .readAsStringSync();
final Map<String, dynamic> jsonContent = json.decode(pluginsString) as Map<String, dynamic>; final Map<String, dynamic> jsonContent = json.decode(pluginsString) as Map<String, dynamic>;
expect(jsonContent['swift_package_manager_enabled'], true); final Map<String, dynamic> expectedSwiftPackageManagerEnabled = <String, dynamic>{
'ios': true,
'macos': true,
};
expect(
jsonContent['swift_package_manager_enabled'],
expectedSwiftPackageManagerEnabled,
);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fs, FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
@ -702,7 +717,14 @@ dependencies:
.readAsStringSync(); .readAsStringSync();
final Map<String, dynamic> jsonContent = json.decode(pluginsString) as Map<String, dynamic>; final Map<String, dynamic> jsonContent = json.decode(pluginsString) as Map<String, dynamic>;
expect(jsonContent['swift_package_manager_enabled'], false); final Map<String, dynamic> expectedSwiftPackageManagerEnabled = <String, dynamic>{
'ios': false,
'macos': false,
};
expect(
jsonContent['swift_package_manager_enabled'],
expectedSwiftPackageManagerEnabled,
);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fs, FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:convert';
import 'package:file_testing/file_testing.dart'; import 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/base/error_handling_io.dart'; import 'package:flutter_tools/src/base/error_handling_io.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
@ -553,14 +555,14 @@ void main() {
.childFile('.flutter-plugins-dependencies'); .childFile('.flutter-plugins-dependencies');
expect(flutterPluginsDependenciesFile, exists); expect(flutterPluginsDependenciesFile, exists);
expect(
flutterPluginsDependenciesFile.readAsStringSync(), final String dependenciesString = flutterPluginsDependenciesFile.readAsStringSync();
isNot(contains('"swift_package_manager_enabled":true')), final Map<String, dynamic>? dependenciesJson = json.decode(dependenciesString) as Map<String, dynamic>?;
); final Map<String, dynamic>? swiftPackageManagerEnabled =
expect( dependenciesJson?['swift_package_manager_enabled'] as Map<String, dynamic>?;
flutterPluginsDependenciesFile.readAsStringSync(), final bool? swiftPackageManagerEnabledIos = swiftPackageManagerEnabled?['ios'] as bool?;
contains('"swift_package_manager_enabled":false'),
); expect(swiftPackageManagerEnabledIos, isFalse);
}, skip: !platform.isMacOS); // [intended] Swift Package Manager only works on macos. }, skip: !platform.isMacOS); // [intended] Swift Package Manager only works on macos.
test("Generated Swift package uses iOS's project minimum deployment", () async { test("Generated Swift package uses iOS's project minimum deployment", () async {