Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit e2d174c

Browse files
[tool] Check for search paths in Swift plugins (#6954)
* Rename command, bump version * Update tests to write actual podspecs * Add new check * Analyzer fix * Unhdo file move
1 parent d607cd9 commit e2d174c

File tree

8 files changed

+513
-235
lines changed

8 files changed

+513
-235
lines changed

.ci.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ targets:
4343
# TODO(stuartmorgan): Move this to ARM once google_maps_flutter has ARM
4444
# support. `pod lint` makes a synthetic target that doesn't respect the
4545
# pod's arch exclusions, so fails to build.
46+
# When moving it, rename the task and file to check_podspecs
4647
- name: Mac_x64 lint_podspecs
4748
recipe: plugins/plugins
4849
timeout: 30

.ci/targets/mac_lint_podspecs.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
tasks:
22
- name: prepare tool
33
script: .ci/scripts/prepare_tool.sh
4-
- name: lint iOS and macOS podspecs
4+
- name: validate iOS and macOS podspecs
55
script: script/tool_runner.sh
6-
args: ["podspecs"]
6+
args: ["podspec-check"]

script/tool/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 0.13.3
2+
3+
* Renames `podspecs` to `podspec-check`. The old name will continue to work.
4+
* Adds validation of the Swift-in-Obj-C-projects workaround in the podspecs of
5+
iOS plugin implementations that use Swift.
6+
17
## 0.13.2+1
28

39
* Replaces deprecated `flutter format` with `dart format` in `format`

script/tool/lib/src/main.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ import 'fix_command.dart';
2121
import 'format_command.dart';
2222
import 'license_check_command.dart';
2323
import 'lint_android_command.dart';
24-
import 'lint_podspecs_command.dart';
2524
import 'list_command.dart';
2625
import 'make_deps_path_based_command.dart';
2726
import 'native_test_command.dart';
27+
import 'podspec_check_command.dart';
2828
import 'publish_check_command.dart';
2929
import 'publish_command.dart';
3030
import 'pubspec_check_command.dart';
@@ -66,7 +66,7 @@ void main(List<String> args) {
6666
..addCommand(FormatCommand(packagesDir))
6767
..addCommand(LicenseCheckCommand(packagesDir))
6868
..addCommand(LintAndroidCommand(packagesDir))
69-
..addCommand(LintPodspecsCommand(packagesDir))
69+
..addCommand(PodspecCheckCommand(packagesDir))
7070
..addCommand(ListCommand(packagesDir))
7171
..addCommand(NativeTestCommand(packagesDir))
7272
..addCommand(MakeDepsPathBasedCommand(packagesDir))

script/tool/lib/src/lint_podspecs_command.dart renamed to script/tool/lib/src/podspec_check_command.dart

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import 'dart:convert';
66
import 'dart:io';
77

88
import 'package:file/file.dart';
9-
import 'package:path/path.dart' as p;
109
import 'package:platform/platform.dart';
1110

1211
import 'common/core.dart';
@@ -20,23 +19,24 @@ const int _exitPodNotInstalled = 3;
2019
/// Lint the CocoaPod podspecs and run unit tests.
2120
///
2221
/// See https://guides.cocoapods.org/terminal/commands.html#pod_lib_lint.
23-
class LintPodspecsCommand extends PackageLoopingCommand {
22+
class PodspecCheckCommand extends PackageLoopingCommand {
2423
/// Creates an instance of the linter command.
25-
LintPodspecsCommand(
24+
PodspecCheckCommand(
2625
Directory packagesDir, {
2726
ProcessRunner processRunner = const ProcessRunner(),
2827
Platform platform = const LocalPlatform(),
2928
}) : super(packagesDir, processRunner: processRunner, platform: platform);
3029

3130
@override
32-
final String name = 'podspecs';
31+
final String name = 'podspec-check';
3332

3433
@override
35-
List<String> get aliases => <String>['podspec'];
34+
List<String> get aliases => <String>['podspec', 'podspecs'];
3635

3736
@override
3837
final String description =
39-
'Runs "pod lib lint" on all iOS and macOS plugin podspecs.\n\n'
38+
'Runs "pod lib lint" on all iOS and macOS plugin podspecs, as well as '
39+
'making sure the podspecs follow repository standards.\n\n'
4040
'This command requires "pod" and "flutter" to be in your path. Runs on macOS only.';
4141

4242
@override
@@ -69,9 +69,32 @@ class LintPodspecsCommand extends PackageLoopingCommand {
6969

7070
for (final File podspec in podspecs) {
7171
if (!await _lintPodspec(podspec)) {
72-
errors.add(p.basename(podspec.path));
72+
errors.add(podspec.basename);
7373
}
7474
}
75+
76+
if (await _hasIOSSwiftCode(package)) {
77+
print('iOS Swift code found, checking for search paths settings...');
78+
for (final File podspec in podspecs) {
79+
if (_isPodspecMissingSearchPaths(podspec)) {
80+
const String workaroundBlock = r'''
81+
s.xcconfig = {
82+
'LIBRARY_SEARCH_PATHS' => '$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)/ $(SDKROOT)/usr/lib/swift',
83+
'LD_RUNPATH_SEARCH_PATHS' => '/usr/lib/swift',
84+
}
85+
''';
86+
final String path =
87+
getRelativePosixPath(podspec, from: package.directory);
88+
printError('$path is missing seach path configuration. Any iOS '
89+
'plugin implementation that contains Swift implementation code '
90+
'needs to contain the following:\n\n'
91+
'$workaroundBlock\n'
92+
'For more details, see https://github.com/flutter/flutter/issues/118418.');
93+
errors.add(podspec.basename);
94+
}
95+
}
96+
}
97+
7598
return errors.isEmpty
7699
? PackageResult.success()
77100
: PackageResult.fail(errors);
@@ -92,7 +115,7 @@ class LintPodspecsCommand extends PackageLoopingCommand {
92115
// Do not run the static analyzer on plugins with known analyzer issues.
93116
final String podspecPath = podspec.path;
94117

95-
final String podspecBasename = p.basename(podspecPath);
118+
final String podspecBasename = podspec.basename;
96119
print('Linting $podspecBasename');
97120

98121
// Lint plugin as framework (use_frameworks!).
@@ -126,4 +149,46 @@ class LintPodspecsCommand extends PackageLoopingCommand {
126149
return processRunner.run('pod', arguments,
127150
workingDir: packagesDir, stdoutEncoding: utf8, stderrEncoding: utf8);
128151
}
152+
153+
/// Returns true if there is any iOS plugin implementation code written in
154+
/// Swift.
155+
Future<bool> _hasIOSSwiftCode(RepositoryPackage package) async {
156+
return getFilesForPackage(package).any((File entity) {
157+
final String relativePath =
158+
getRelativePosixPath(entity, from: package.directory);
159+
// Ignore example code.
160+
if (relativePath.startsWith('example/')) {
161+
return false;
162+
}
163+
final String filePath = entity.path;
164+
return path.extension(filePath) == '.swift';
165+
});
166+
}
167+
168+
/// Returns true if [podspec] could apply to iOS, but does not have the
169+
/// workaround for search paths that makes Swift plugins build correctly in
170+
/// Objective-C applications. See
171+
/// https://github.com/flutter/flutter/issues/118418 for context and details.
172+
///
173+
/// This does not check that the plugin has Swift code, and thus whether the
174+
/// workaround is needed, only whether or not it is there.
175+
bool _isPodspecMissingSearchPaths(File podspec) {
176+
final String directory = podspec.parent.basename;
177+
// All macOS Flutter apps are Swift, so macOS-only podspecs don't need the
178+
// workaround. If it's anywhere other than macos/, err or the side of
179+
// assuming it's required.
180+
if (directory == 'macos') {
181+
return false;
182+
}
183+
184+
// This errs on the side of being too strict, to minimize the chance of
185+
// accidental incorrect configuration. If we ever need more flexibility
186+
// due to a false negative we can adjust this as necessary.
187+
final RegExp workaround = RegExp(r'''
188+
\s*s\.(?:ios\.)?xcconfig = {[^}]*
189+
\s*'LIBRARY_SEARCH_PATHS' => '\$\(TOOLCHAIN_DIR\)/usr/lib/swift/\$\(PLATFORM_NAME\)/ \$\(SDKROOT\)/usr/lib/swift',
190+
\s*'LD_RUNPATH_SEARCH_PATHS' => '/usr/lib/swift',[^}]*
191+
\s*}''', dotAll: true);
192+
return !workaround.hasMatch(podspec.readAsStringSync());
193+
}
129194
}

script/tool/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: flutter_plugin_tools
22
description: Productivity utils for flutter/plugins and flutter/packages
33
repository: https://github.com/flutter/plugins/tree/main/script/tool
4-
version: 0.13.2+1
4+
version: 0.13.3
55

66
dependencies:
77
args: ^2.1.0

0 commit comments

Comments
 (0)