Unverified Commit 3d112429 authored by Spt's avatar Spt Committed by GitHub

Solve the problem that <Flutter/Flutter.h> cannot be imported when a pod...

Solve the problem that <Flutter/Flutter.h> cannot be imported when a pod transitive depends on Flutter (#125610)

![image](https://user-images.githubusercontent.com/8318578/234780282-89b18d27-df49-4b4e-88b5-c9d17cf3334f.png)
![image](https://user-images.githubusercontent.com/8318578/234780668-901ab816-5b6b-4d87-a6f4-120b5852580c.png)
If a pod transitive depends on a pod containing a framework, cocoapods will add the path of the framework to its FRAMEWORK_SEARCH_PATHS.
So I modified the relevant logic in podhelper, hoping to be consistent with the behavior of cocoapods.

Fixes https://github.com/flutter/flutter/issues/126251.
parent a9f91366
...@@ -9,6 +9,8 @@ Future<void> main() async { ...@@ -9,6 +9,8 @@ Future<void> main() async {
await task(combine(<TaskFunction>[ await task(combine(<TaskFunction>[
PluginTest('ios', <String>['-i', 'objc', '--platforms=ios']).call, PluginTest('ios', <String>['-i', 'objc', '--platforms=ios']).call,
PluginTest('ios', <String>['-i', 'swift', '--platforms=ios']).call, PluginTest('ios', <String>['-i', 'swift', '--platforms=ios']).call,
// Test that app builds with Flutter as a transitive dependency.
PluginTest('ios', <String>['-i', 'objc', '--platforms=ios'], cocoapodsTransitiveFlutterDependency: true).call,
// Test that Dart-only plugins are supported. // Test that Dart-only plugins are supported.
PluginTest('ios', <String>['--platforms=ios'], dartOnlyPlugin: true).call, PluginTest('ios', <String>['--platforms=ios'], dartOnlyPlugin: true).call,
// Test that shared darwin directories are supported. // Test that shared darwin directories are supported.
......
...@@ -35,6 +35,7 @@ class PluginTest { ...@@ -35,6 +35,7 @@ class PluginTest {
this.dartOnlyPlugin = false, this.dartOnlyPlugin = false,
this.sharedDarwinSource = false, this.sharedDarwinSource = false,
this.template = 'plugin', this.template = 'plugin',
this.cocoapodsTransitiveFlutterDependency = false,
}); });
final String buildTarget; final String buildTarget;
...@@ -44,6 +45,7 @@ class PluginTest { ...@@ -44,6 +45,7 @@ class PluginTest {
final bool dartOnlyPlugin; final bool dartOnlyPlugin;
final bool sharedDarwinSource; final bool sharedDarwinSource;
final String template; final String template;
final bool cocoapodsTransitiveFlutterDependency;
Future<TaskResult> call() async { Future<TaskResult> call() async {
final Directory tempDir = final Directory tempDir =
...@@ -80,6 +82,11 @@ class PluginTest { ...@@ -80,6 +82,11 @@ class PluginTest {
await app.addPlugin('path_provider'); await app.addPlugin('path_provider');
section('Build app'); section('Build app');
await app.build(buildTarget, validateNativeBuildProject: !dartOnlyPlugin); await app.build(buildTarget, validateNativeBuildProject: !dartOnlyPlugin);
if (cocoapodsTransitiveFlutterDependency) {
section('Test app with Flutter as a transitive CocoaPods dependency');
await app.addCocoapodsTransitiveFlutterDependency();
await app.build(buildTarget, validateNativeBuildProject: !dartOnlyPlugin);
}
if (runFlutterTest) { if (runFlutterTest) {
section('Test app'); section('Test app');
await app.runFlutterTest(); await app.runFlutterTest();
...@@ -361,6 +368,57 @@ public class $pluginClass: NSObject, FlutterPlugin { ...@@ -361,6 +368,57 @@ public class $pluginClass: NSObject, FlutterPlugin {
return project; return project;
} }
/// Creates a Pod that uses a Flutter plugin as a dependency and therefore
/// Flutter as a transitive dependency.
Future<void> addCocoapodsTransitiveFlutterDependency() async {
final String iosDirectoryPath = path.join(rootPath, 'ios');
final File nativePod = File(path.join(
iosDirectoryPath,
'NativePod',
'NativePod.podspec',
));
nativePod.createSync(recursive: true);
nativePod.writeAsStringSync('''
Pod::Spec.new do |s|
s.name = 'NativePod'
s.version = '1.0.0'
s.summary = 'A pod to test Flutter as a transitive dependency.'
s.homepage = 'https://flutter.dev'
s.license = { :type => 'BSD' }
s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
s.source = { :path => '.' }
s.source_files = "Classes", "Classes/**/*.{h,m}"
s.dependency 'plugintest'
end
''');
final File nativePodClass = File(path.join(
iosDirectoryPath,
'NativePod',
'Classes',
'NativePodTest.m',
));
nativePodClass.createSync(recursive: true);
nativePodClass.writeAsStringSync('''
#import <Flutter/Flutter.h>
@interface NativePodTest : NSObject
@end
@implementation NativePodTest
@end
''');
final File podfileFile = File(path.join(iosDirectoryPath, 'Podfile'));
final List<String> podfileContents = podfileFile.readAsLinesSync();
final int index = podfileContents.indexWhere((String line) => line.contains('flutter_install_all_ios_pods'));
podfileContents.insert(index, "pod 'NativePod', :path => 'NativePod'");
podfileFile.writeAsStringSync(podfileContents.join('\n'));
}
// Make the platform version artificially low to test that the "deployment // Make the platform version artificially low to test that the "deployment
// version too low" warning is never emitted. // version too low" warning is never emitted.
void _reduceDarwinPluginMinimumVersion(String plugin, String target) { void _reduceDarwinPluginMinimumVersion(String plugin, String target) {
......
...@@ -19,6 +19,20 @@ def flutter_ios_podfile_setup; end ...@@ -19,6 +19,20 @@ def flutter_ios_podfile_setup; end
# Same as flutter_ios_podfile_setup for macOS. # Same as flutter_ios_podfile_setup for macOS.
def flutter_macos_podfile_setup; end def flutter_macos_podfile_setup; end
# Determine whether the target depends on Flutter (including transitive dependency)
def depends_on_flutter(target, engine_pod_name)
target.dependencies.any? do |dependency|
if dependency.name == engine_pod_name
return true
end
if depends_on_flutter(dependency.target, engine_pod_name)
return true
end
end
return false
end
# Add iOS build settings to pod targets. # Add iOS build settings to pod targets.
# #
# @example # @example
...@@ -68,8 +82,8 @@ def flutter_additional_ios_build_settings(target) ...@@ -68,8 +82,8 @@ def flutter_additional_ios_build_settings(target)
# ARC code targeting iOS 8 does not build on Xcode 14.3. Force to at least iOS 9. # ARC code targeting iOS 8 does not build on Xcode 14.3. Force to at least iOS 9.
build_configuration.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0' if force_to_arc_supported_min build_configuration.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0' if force_to_arc_supported_min
# Skip other updates if it's not a Flutter plugin (transitive dependency). # Skip other updates if it does not depend on Flutter (including transitive dependency)
next unless target.dependencies.any? { |dependency| dependency.name == 'Flutter' } next unless depends_on_flutter(target, 'Flutter')
# Bitcode is deprecated, Flutter.framework bitcode blob will have been stripped. # Bitcode is deprecated, Flutter.framework bitcode blob will have been stripped.
build_configuration.build_settings['ENABLE_BITCODE'] = 'NO' build_configuration.build_settings['ENABLE_BITCODE'] = 'NO'
...@@ -139,8 +153,8 @@ def flutter_additional_macos_build_settings(target) ...@@ -139,8 +153,8 @@ def flutter_additional_macos_build_settings(target)
# ARC code targeting macOS 10.10 does not build on Xcode 14.3. Force to at least macOS 10.11. # ARC code targeting macOS 10.10 does not build on Xcode 14.3. Force to at least macOS 10.11.
build_configuration.build_settings['MACOSX_DEPLOYMENT_TARGET'] = '10.11' if force_to_arc_supported_min build_configuration.build_settings['MACOSX_DEPLOYMENT_TARGET'] = '10.11' if force_to_arc_supported_min
# Skip other updates if it's not a Flutter plugin (transitive dependency). # Skip other updates if it does not depend on Flutter (including transitive dependency)
next unless target.dependencies.any? { |dependency| dependency.name == 'FlutterMacOS' } next unless depends_on_flutter(target, 'FlutterMacOS')
# Profile can't be derived from the CocoaPods build configuration. Use release framework (for linking only). # Profile can't be derived from the CocoaPods build configuration. Use release framework (for linking only).
configuration_engine_dir = local_engine || (build_configuration.type == :debug ? debug_framework_dir : release_framework_dir) configuration_engine_dir = local_engine || (build_configuration.type == :debug ? debug_framework_dir : release_framework_dir)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment