Unverified Commit a69b3ca5 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Exclude arm64 from iOS app archs if unsupported by plugins (#87244)

parent 5b0fd2f3
......@@ -4,6 +4,7 @@
import '../artifacts.dart';
import '../base/file_system.dart';
import '../base/os.dart';
import '../build_info.dart';
import '../cache.dart';
import '../flutter_manifest.dart';
......@@ -35,7 +36,7 @@ Future<void> updateGeneratedXcodeProperties({
bool useMacOSConfig = false,
String? buildDirOverride,
}) async {
final List<String> xcodeBuildSettings = _xcodeBuildSettingsLines(
final List<String> xcodeBuildSettings = await _xcodeBuildSettingsLines(
project: project,
buildInfo: buildInfo,
targetOverride: targetOverride,
......@@ -136,13 +137,13 @@ String? parsedBuildNumber({
}
/// List of lines of build settings. Example: 'FLUTTER_BUILD_DIR=build'
List<String> _xcodeBuildSettingsLines({
Future<List<String>> _xcodeBuildSettingsLines({
required FlutterProject project,
required BuildInfo buildInfo,
String? targetOverride,
bool useMacOSConfig = false,
String? buildDirOverride,
}) {
}) async {
final List<String> xcodeBuildSettings = <String>[];
final String flutterRoot = globals.fs.path.normalize(Cache.flutterRoot!);
......@@ -204,7 +205,15 @@ List<String> _xcodeBuildSettingsLines({
// ARM not yet supported https://github.com/flutter/flutter/issues/69221
xcodeBuildSettings.add('EXCLUDED_ARCHS=arm64');
} else {
xcodeBuildSettings.add('EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386');
String excludedSimulatorArchs = 'i386';
// If any plugins or their dependencies do not support arm64 simulators
// (to run natively without Rosetta translation on an ARM Mac),
// the app will fail to build unless it also excludes arm64 simulators.
if (globals.os.hostPlatform == HostPlatform.darwin_arm && !(await project.ios.pluginsSupportArmSimulator())) {
excludedSimulatorArchs += ' arm64';
}
xcodeBuildSettings.add('EXCLUDED_ARCHS[sdk=iphonesimulator*]=$excludedSimulatorArchs');
}
for (final MapEntry<String, String> config in buildInfo.toEnvironmentConfig().entries) {
......
......@@ -215,6 +215,58 @@ class XcodeProjectInterpreter {
}
}
/// Asynchronously retrieve xcode build settings for the generated Pods.xcodeproj plugins project.
///
/// Returns the stdout of the Xcode command.
Future<String?> pluginsBuildSettingsOutput(
Directory podXcodeProject, {
Duration timeout = const Duration(minutes: 1),
}) async {
if (!podXcodeProject.existsSync()) {
// No plugins.
return null;
}
final Status status = _logger.startSpinner();
final List<String> showBuildSettingsCommand = <String>[
...xcrunCommand(),
'xcodebuild',
'-alltargets',
'-sdk',
'iphonesimulator',
'-project',
podXcodeProject.path,
'-showBuildSettings',
];
try {
// showBuildSettings is reported to occasionally timeout. Here, we give it
// a lot of wiggle room (locally on Flutter Gallery, this takes ~1s).
// When there is a timeout, we retry once.
final RunResult result = await _processUtils.run(
showBuildSettingsCommand,
throwOnError: true,
workingDirectory: podXcodeProject.path,
timeout: timeout,
timeoutRetries: 1,
);
// Return the stdout only. Do not parse with parseXcodeBuildSettings, `-alltargets` prints the build settings
// for all targets (one per plugin), so it would require a Map of Maps.
return result.stdout.trim();
} on Exception catch (error) {
if (error is ProcessException && error.toString().contains('timed out')) {
BuildEvent('xcode-show-build-settings-timeout',
type: 'ios',
command: showBuildSettingsCommand.join(' '),
flutterUsage: _usage,
).send();
}
_logger.printTrace('Unexpected failure to get Pod Xcode project build settings: $error.');
return null;
} finally {
status.stop();
}
}
Future<void> cleanWorkspace(String workspacePath, String scheme, { bool verbose = false }) async {
await _processUtils.run(<String>[
...xcrunCommand(),
......
......@@ -146,6 +146,30 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
/// Xcode workspace shared workspace settings file for the host app.
File get xcodeWorkspaceSharedSettings => xcodeWorkspaceSharedData.childFile('WorkspaceSettings.xcsettings');
/// Do all plugins support arm64 simulators to run natively on an ARM Mac?
Future<bool> pluginsSupportArmSimulator() async {
final Directory podXcodeProject = hostAppRoot
.childDirectory('Pods')
.childDirectory('Pods.xcodeproj');
if (!podXcodeProject.existsSync()) {
// No plugins.
return true;
}
final XcodeProjectInterpreter? xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
if (xcodeProjectInterpreter == null) {
// Xcode isn't installed, don't try to check.
return false;
}
final String? buildSettings = await xcodeProjectInterpreter.pluginsBuildSettingsOutput(podXcodeProject);
// See if any plugins or their dependencies exclude arm64 simulators
// as a valid architecture, usually because a binary is missing that slice.
// Example: EXCLUDED_ARCHS = arm64 i386
// NOT: EXCLUDED_ARCHS = i386
return buildSettings != null && !buildSettings.contains(RegExp('EXCLUDED_ARCHS.*arm64'));
}
@override
bool existsSync() {
return parent.isModule || _editableDirectory.existsSync();
......
......@@ -306,6 +306,14 @@ class FakeXcodeProjectInterpreter implements XcodeProjectInterpreter {
return <String, String>{};
}
@override
Future<String> pluginsBuildSettingsOutput(
Directory podXcodeProject, {
Duration timeout = const Duration(minutes: 1),
}) async {
return null;
}
@override
Future<void> cleanWorkspace(String workspacePath, String scheme, { bool verbose = false }) {
return null;
......
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