Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/video_player/video_player_avfoundation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.9.6

* Adds a Swift version to fix a potential build issue when using CocoaPods.

## 2.9.5

* Converts portions of the native code to Swift for improved maintainability.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Downloaded by pub (not CocoaPods).
s.ios.deployment_target = '13.0'
s.osx.deployment_target = '10.15'
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
s.swift_version = '5.0'
s.xcconfig = {
'LIBRARY_SEARCH_PATHS' => '$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)/ $(SDKROOT)/usr/lib/swift',
'LD_RUNPATH_SEARCH_PATHS' => '/usr/lib/swift',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: video_player_avfoundation
description: iOS and macOS implementation of the video_player plugin.
repository: https://github.com/flutter/packages/tree/main/packages/video_player/video_player_avfoundation
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22
version: 2.9.5
version: 2.9.6

environment:
sdk: ^3.10.0
Expand Down
32 changes: 31 additions & 1 deletion script/tool/lib/src/podspec_check_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ class PodspecCheckCommand extends PackageLoopingCommand {
}

if (await _hasIOSSwiftCode(package)) {
print('iOS Swift code found, checking for search paths settings...');
print(
'iOS Swift code found, checking for search paths settings and Swift version...',
);
for (final podspec in podspecs) {
if (_isPodspecMissingSearchPaths(podspec)) {
const workaroundBlock = r'''
Expand All @@ -97,6 +99,20 @@ class PodspecCheckCommand extends PackageLoopingCommand {
);
errors.add(podspec.basename);
}

if (_isPodspecMissingSwiftVersion(podspec)) {
final String path = getRelativePosixPath(
podspec,
from: package.directory,
);
printError(
'$path is missing Swift version configuration. Any iOS '
'plugin implementation that contains Swift implementation code '
'needs to contain a Swift version. For example:\n\n'
"s.swift_version = '5.0'",
);
errors.add(podspec.basename);
}
}
}

Expand All @@ -121,9 +137,15 @@ class PodspecCheckCommand extends PackageLoopingCommand {
File entity,
) {
final String filename = entity.basename;
final String relativePath = getRelativePosixPath(
entity,
from: package.directory,
);
return path.extension(filename) == '.podspec' &&
filename != 'Flutter.podspec' &&
filename != 'FlutterMacOS.podspec' &&
// Ignore build intermediates, such as transitive pod dependencies.
!relativePath.split('/').contains('build') &&
!entity.path.contains('packages/pigeon/platform_tests/');
}).toList();

Expand Down Expand Up @@ -177,6 +199,10 @@ class PodspecCheckCommand extends PackageLoopingCommand {
if (relativePath.startsWith('example/')) {
return false;
}
// Ignore build intermediates.
if (relativePath.split('/').contains('build')) {
return false;
}
// Ignore test code.
if (relativePath.contains('/Tests/') ||
relativePath.contains('/RunnerTests/') ||
Expand Down Expand Up @@ -226,4 +252,8 @@ class PodspecCheckCommand extends PackageLoopingCommand {
);
return manifestBundling.hasMatch(podspec.readAsStringSync());
}

bool _isPodspecMissingSwiftVersion(File podspec) {
return !RegExp(r'\bswift_version\s*=').hasMatch(podspec.readAsStringSync());
}
}
93 changes: 89 additions & 4 deletions script/tool/test/podspec_check_command_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,22 @@ import 'package:test/test.dart';
import 'mocks.dart';
import 'util.dart';

/// Adds a fake podspec to [plugin]'s [platform] directory.
/// Adds a fake podspec to [plugin]'s [subdirectory] directory.
///
/// If [includeSwiftWorkaround] is set, the xcconfig additions to make Swift
/// libraries work in apps that have no Swift will be included. If
/// [scopeSwiftWorkaround] is set, it will be specific to the iOS configuration.
void _writeFakePodspec(
RepositoryPackage plugin,
String platform, {
String subdirectory, {
bool includeSwiftWorkaround = false,
bool scopeSwiftWorkaround = false,
bool includePrivacyManifest = false,
bool includeSwiftVersion = true,
}) {
final String pluginName = plugin.directory.basename;
final File file = plugin.directory
.childDirectory(platform)
.childDirectory(subdirectory)
.childFile('$pluginName.podspec');
final swiftWorkaround = includeSwiftWorkaround
? '''
Expand All @@ -43,6 +44,7 @@ void _writeFakePodspec(
s.resource_bundles = {'$pluginName' => ['Resources/PrivacyInfo.xcprivacy']}
'''
: '';
final swiftVersion = includeSwiftVersion ? "s.swift_version = '5.0'" : '';
file.createSync(recursive: true);
file.writeAsStringSync('''
#
Expand All @@ -66,7 +68,7 @@ Wraps NSUserDefaults, providing a persistent store for simple key-value pairs.
s.osx.deployment_target = '10.11'
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
$swiftWorkaround
s.swift_version = '5.0'
$swiftVersion
$privacyManifest

end
Expand Down Expand Up @@ -452,6 +454,54 @@ void main() {
},
);

test(
'ignores Swift files in the build directory when determining whether the plugin uses Swift',
() async {
final RepositoryPackage plugin = createFakePlugin(
'plugin1',
packagesDir,
extraFiles: <String>[
'ios/Classes/SomeObjC.h',
'ios/Classes/SomeObjC.m',
'build/SomeSwiftFile.swift',
'ios/build/AnotherSwiftFile.swift',
],
);
_writeFakePodspec(plugin, 'ios');

final List<String> output = await runCapturingPrint(runner, <String>[
'podspec-check',
]);

expect(
output,
containsAllInOrder(<Matcher>[contains('Ran for 1 package(s)')]),
);
},
);

test('does not check for search paths in build output', () async {
final RepositoryPackage plugin = createFakePlugin(
'plugin1',
packagesDir,
extraFiles: <String>[
'ios/Classes/SomeSwift.swift',
'ios/plugin1/Package.swift',
],
);
_writeFakePodspec(plugin, 'ios', includeSwiftWorkaround: true);
_writeFakePodspec(plugin, 'ios/build/some_pod');

final List<String> output = await runCapturingPrint(runner, <String>[
'podspec-check',
]);

expect(
output,
containsAllInOrder(<Matcher>[contains('Ran for 1 package(s)')]),
);
});

test('passes if the search paths workaround is present', () async {
final RepositoryPackage plugin = createFakePlugin(
'plugin1',
Expand Down Expand Up @@ -629,5 +679,40 @@ void main() {
containsAllInOrder(<Matcher>[contains('Ran for 1 package(s)')]),
);
});

test('fails when a Swift plugin is missing a Swift version', () async {
final RepositoryPackage plugin = createFakePlugin(
'plugin1',
packagesDir,
platformSupport: <String, PlatformDetails>{
Platform.iOS: const PlatformDetails(PlatformSupport.inline),
},
extraFiles: <String>['ios/Classes/SomeSwift.swift'],
);
_writeFakePodspec(
plugin,
'ios',
includeSwiftVersion: false,
includeSwiftWorkaround: true,
includePrivacyManifest: true,
);

Error? commandError;
final List<String> output = await runCapturingPrint(
runner,
<String>['podspec-check'],
errorHandler: (Error e) {
commandError = e;
},
);

expect(commandError, isA<ToolExit>());
expect(
output,
containsAllInOrder(<Matcher>[
contains('missing Swift version configuration'),
]),
);
});
});
}
Loading