Unverified Commit 6ab00756 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Build Flutter iOS plugins with all valid architectures (#95293)

parent 22edbc56
...@@ -33,9 +33,6 @@ end ...@@ -33,9 +33,6 @@ end
def flutter_additional_ios_build_settings(target) def flutter_additional_ios_build_settings(target)
return unless target.platform_name == :ios return unless target.platform_name == :ios
# Return if it's not a Flutter plugin (transitive dependency).
return unless target.dependencies.any? { |dependency| dependency.name == 'Flutter' }
# [target.deployment_target] is a [String] formatted as "8.0". # [target.deployment_target] is a [String] formatted as "8.0".
inherit_deployment_target = target.deployment_target[/\d+/].to_i < 9 inherit_deployment_target = target.deployment_target[/\d+/].to_i < 9
...@@ -52,6 +49,14 @@ def flutter_additional_ios_build_settings(target) ...@@ -52,6 +49,14 @@ def flutter_additional_ios_build_settings(target)
release_framework_dir = File.expand_path(File.join(artifacts_dir, 'ios-release', 'Flutter.xcframework'), __FILE__) release_framework_dir = File.expand_path(File.join(artifacts_dir, 'ios-release', 'Flutter.xcframework'), __FILE__)
target.build_configurations.each do |build_configuration| target.build_configurations.each do |build_configuration|
# Build both x86_64 and arm64 simulator archs for all dependencies. If a single plugin does not support arm64 simulators,
# the app and all frameworks will fall back to x86_64. Unfortunately that case is not detectable in this script.
# Therefore all pods must have a x86_64 slice available, or linking a x86_64 app will fail.
build_configuration.build_settings['ONLY_ACTIVE_ARCH'] = 'NO' if build_configuration.type == :debug
# Skip other updates if it's not a Flutter plugin (transitive dependency).
next unless target.dependencies.any? { |dependency| dependency.name == 'Flutter' }
# 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 = build_configuration.type == :debug ? debug_framework_dir : release_framework_dir configuration_engine_dir = build_configuration.type == :debug ? debug_framework_dir : release_framework_dir
Dir.new(configuration_engine_dir).each_child do |xcframework_file| Dir.new(configuration_engine_dir).each_child do |xcframework_file|
......
...@@ -16,6 +16,7 @@ import 'test_utils.dart'; ...@@ -16,6 +16,7 @@ import 'test_utils.dart';
void main() { void main() {
group('iOS app validation', () { group('iOS app validation', () {
String flutterRoot; String flutterRoot;
Directory pluginRoot;
String projectRoot; String projectRoot;
String flutterBin; String flutterBin;
Directory tempDir; Directory tempDir;
...@@ -29,18 +30,20 @@ void main() { ...@@ -29,18 +30,20 @@ void main() {
'flutter', 'flutter',
); );
// Test a plugin example app to allow plugins validation.
processManager.runSync(<String>[ processManager.runSync(<String>[
flutterBin, flutterBin,
...getLocalEngineArguments(), ...getLocalEngineArguments(),
'create', 'create',
'--verbose', '--verbose',
'--platforms=ios', '--platforms=ios',
'-i', '-t',
'objc', 'plugin',
'hello', 'hello',
], workingDirectory: tempDir.path); ], workingDirectory: tempDir.path);
projectRoot = tempDir.childDirectory('hello').path; pluginRoot = tempDir.childDirectory('hello');
projectRoot = pluginRoot.childDirectory('example').path;
}); });
tearDownAll(() { tearDownAll(() {
...@@ -56,6 +59,7 @@ void main() { ...@@ -56,6 +59,7 @@ void main() {
File outputFlutterFrameworkBinary; File outputFlutterFrameworkBinary;
Directory outputAppFramework; Directory outputAppFramework;
File outputAppFrameworkBinary; File outputAppFrameworkBinary;
File outputPluginFrameworkBinary;
setUpAll(() { setUpAll(() {
processManager.runSync(<String>[ processManager.runSync(<String>[
...@@ -85,11 +89,13 @@ void main() { ...@@ -85,11 +89,13 @@ void main() {
outputAppFramework = frameworkDirectory.childDirectory('App.framework'); outputAppFramework = frameworkDirectory.childDirectory('App.framework');
outputAppFrameworkBinary = outputAppFramework.childFile('App'); outputAppFrameworkBinary = outputAppFramework.childFile('App');
outputPluginFrameworkBinary = frameworkDirectory.childDirectory('hello.framework').childFile('hello');
}); });
testWithoutContext('flutter build ios builds a valid app', () { testWithoutContext('flutter build ios builds a valid app', () {
// Should only contain Flutter.framework and App.framework. expect(outputPluginFrameworkBinary, exists);
expect(frameworkDirectory.listSync().length, 2);
expect(outputAppFrameworkBinary, exists); expect(outputAppFrameworkBinary, exists);
expect(outputAppFramework.childFile('Info.plist'), exists); expect(outputAppFramework.childFile('Info.plist'), exists);
...@@ -202,17 +208,61 @@ void main() { ...@@ -202,17 +208,61 @@ void main() {
}, skip: !platform.isMacOS || buildMode != BuildMode.release); // [intended] only makes sense on macos. }, skip: !platform.isMacOS || buildMode != BuildMode.release); // [intended] only makes sense on macos.
testWithoutContext('validate obfuscation', () { testWithoutContext('validate obfuscation', () {
final ProcessResult grepResult = processManager.runSync(<String>[ // HelloPlugin class is present in project.
ProcessResult grepResult = processManager.runSync(<String>[
'grep',
'-r',
'HelloPlugin',
pluginRoot.path,
]);
// Matches exits 0.
expect(grepResult.exitCode, 0);
// Not present in binary.
grepResult = processManager.runSync(<String>[
'grep', 'grep',
'-i', 'HelloPlugin',
'hello',
outputAppFrameworkBinary.path, outputAppFrameworkBinary.path,
]); ]);
expect(grepResult.stdout, isNot(contains('matches'))); // Does not match exits 1.
expect(grepResult.exitCode, 1);
}); });
}); });
} }
testWithoutContext('builds all plugin architectures for simulator', () {
final ProcessResult buildSimulator = processManager.runSync(
<String>[
flutterBin,
...getLocalEngineArguments(),
'build',
'ios',
'--simulator',
'--verbose',
'--no-codesign',
],
workingDirectory: projectRoot,
);
expect(buildSimulator.exitCode, 0);
final File pluginFrameworkBinary = fileSystem.file(fileSystem.path.join(
projectRoot,
'build',
'ios',
'iphonesimulator',
'Runner.app',
'Frameworks',
'hello.framework',
'hello',
));
expect(pluginFrameworkBinary, exists);
final ProcessResult archs = processManager.runSync(
<String>['file', pluginFrameworkBinary.path],
);
expect(archs.stdout, contains('Mach-O 64-bit dynamically linked shared library x86_64'));
expect(archs.stdout, contains('Mach-O 64-bit dynamically linked shared library arm64'));
});
testWithoutContext('build for simulator with all available architectures', () { testWithoutContext('build for simulator with all available architectures', () {
final ProcessResult buildSimulator = processManager.runSync( final ProcessResult buildSimulator = processManager.runSync(
<String>[ <String>[
...@@ -250,6 +300,6 @@ void main() { ...@@ -250,6 +300,6 @@ void main() {
expect(archs.stdout, contains('Mach-O 64-bit dynamically linked shared library arm64')); expect(archs.stdout, contains('Mach-O 64-bit dynamically linked shared library arm64'));
}); });
}, skip: !platform.isMacOS, // [intended] only makes sense for macos platform. }, skip: !platform.isMacOS, // [intended] only makes sense for macos platform.
timeout: const Timeout(Duration(minutes: 5)) timeout: const Timeout(Duration(minutes: 7))
); );
} }
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