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 @@ ...@@ -4,6 +4,7 @@
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/os.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../cache.dart'; import '../cache.dart';
import '../flutter_manifest.dart'; import '../flutter_manifest.dart';
...@@ -35,7 +36,7 @@ Future<void> updateGeneratedXcodeProperties({ ...@@ -35,7 +36,7 @@ Future<void> updateGeneratedXcodeProperties({
bool useMacOSConfig = false, bool useMacOSConfig = false,
String? buildDirOverride, String? buildDirOverride,
}) async { }) async {
final List<String> xcodeBuildSettings = _xcodeBuildSettingsLines( final List<String> xcodeBuildSettings = await _xcodeBuildSettingsLines(
project: project, project: project,
buildInfo: buildInfo, buildInfo: buildInfo,
targetOverride: targetOverride, targetOverride: targetOverride,
...@@ -136,13 +137,13 @@ String? parsedBuildNumber({ ...@@ -136,13 +137,13 @@ String? parsedBuildNumber({
} }
/// List of lines of build settings. Example: 'FLUTTER_BUILD_DIR=build' /// List of lines of build settings. Example: 'FLUTTER_BUILD_DIR=build'
List<String> _xcodeBuildSettingsLines({ Future<List<String>> _xcodeBuildSettingsLines({
required FlutterProject project, required FlutterProject project,
required BuildInfo buildInfo, required BuildInfo buildInfo,
String? targetOverride, String? targetOverride,
bool useMacOSConfig = false, bool useMacOSConfig = false,
String? buildDirOverride, String? buildDirOverride,
}) { }) async {
final List<String> xcodeBuildSettings = <String>[]; final List<String> xcodeBuildSettings = <String>[];
final String flutterRoot = globals.fs.path.normalize(Cache.flutterRoot!); final String flutterRoot = globals.fs.path.normalize(Cache.flutterRoot!);
...@@ -204,7 +205,15 @@ List<String> _xcodeBuildSettingsLines({ ...@@ -204,7 +205,15 @@ List<String> _xcodeBuildSettingsLines({
// ARM not yet supported https://github.com/flutter/flutter/issues/69221 // ARM not yet supported https://github.com/flutter/flutter/issues/69221
xcodeBuildSettings.add('EXCLUDED_ARCHS=arm64'); xcodeBuildSettings.add('EXCLUDED_ARCHS=arm64');
} else { } 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) { for (final MapEntry<String, String> config in buildInfo.toEnvironmentConfig().entries) {
......
...@@ -215,6 +215,58 @@ class XcodeProjectInterpreter { ...@@ -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 { Future<void> cleanWorkspace(String workspacePath, String scheme, { bool verbose = false }) async {
await _processUtils.run(<String>[ await _processUtils.run(<String>[
...xcrunCommand(), ...xcrunCommand(),
......
...@@ -146,6 +146,30 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject { ...@@ -146,6 +146,30 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
/// Xcode workspace shared workspace settings file for the host app. /// Xcode workspace shared workspace settings file for the host app.
File get xcodeWorkspaceSharedSettings => xcodeWorkspaceSharedData.childFile('WorkspaceSettings.xcsettings'); 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 @override
bool existsSync() { bool existsSync() {
return parent.isModule || _editableDirectory.existsSync(); return parent.isModule || _editableDirectory.existsSync();
......
...@@ -9,6 +9,7 @@ import 'package:flutter_tools/src/artifacts.dart'; ...@@ -9,6 +9,7 @@ import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/version.dart'; import 'package:flutter_tools/src/base/version.dart';
import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_info.dart';
...@@ -20,6 +21,7 @@ import 'package:flutter_tools/src/reporting/reporting.dart'; ...@@ -20,6 +21,7 @@ import 'package:flutter_tools/src/reporting/reporting.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/context.dart'; import '../../src/context.dart';
import '../../src/fake_process_manager.dart'; import '../../src/fake_process_manager.dart';
import '../../src/fakes.dart';
const String xcodebuild = '/usr/bin/xcodebuild'; const String xcodebuild = '/usr/bin/xcodebuild';
...@@ -38,7 +40,8 @@ void main() { ...@@ -38,7 +40,8 @@ void main() {
], ],
); );
const FakeCommand kARMCheckCommand = FakeCommand( // x64 host.
const FakeCommand kx64CheckCommand = FakeCommand(
command: <String>[ command: <String>[
'sysctl', 'sysctl',
'hw.optional.arm64', 'hw.optional.arm64',
...@@ -46,6 +49,15 @@ void main() { ...@@ -46,6 +49,15 @@ void main() {
exitCode: 1, exitCode: 1,
); );
// ARM host.
const FakeCommand kARMCheckCommand = FakeCommand(
command: <String>[
'sysctl',
'hw.optional.arm64',
],
stdout: 'hw.optional.arm64: 1',
);
FakeProcessManager fakeProcessManager; FakeProcessManager fakeProcessManager;
XcodeProjectInterpreter xcodeProjectInterpreter; XcodeProjectInterpreter xcodeProjectInterpreter;
FakePlatform platform; FakePlatform platform;
...@@ -70,7 +82,7 @@ void main() { ...@@ -70,7 +82,7 @@ void main() {
testWithoutContext('xcodebuild versionText returns null when xcodebuild is not fully installed', () { testWithoutContext('xcodebuild versionText returns null when xcodebuild is not fully installed', () {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>['xcrun', 'xcodebuild', '-version'], command: <String>['xcrun', 'xcodebuild', '-version'],
stdout: "xcode-select: error: tool 'xcodebuild' requires Xcode, " stdout: "xcode-select: error: tool 'xcodebuild' requires Xcode, "
...@@ -87,7 +99,7 @@ void main() { ...@@ -87,7 +99,7 @@ void main() {
testWithoutContext('xcodebuild versionText returns null when xcodebuild is not installed', () { testWithoutContext('xcodebuild versionText returns null when xcodebuild is not installed', () {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>['xcrun', 'xcodebuild', '-version'], command: <String>['xcrun', 'xcodebuild', '-version'],
exception: ProcessException(xcodebuild, <String>['-version']), exception: ProcessException(xcodebuild, <String>['-version']),
...@@ -100,7 +112,7 @@ void main() { ...@@ -100,7 +112,7 @@ void main() {
testWithoutContext('xcodebuild versionText returns formatted version text', () { testWithoutContext('xcodebuild versionText returns formatted version text', () {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>['xcrun', 'xcodebuild', '-version'], command: <String>['xcrun', 'xcodebuild', '-version'],
stdout: 'Xcode 8.3.3\nBuild version 8E3004b', stdout: 'Xcode 8.3.3\nBuild version 8E3004b',
...@@ -114,7 +126,7 @@ void main() { ...@@ -114,7 +126,7 @@ void main() {
testWithoutContext('xcodebuild versionText handles Xcode version string with unexpected format', () { testWithoutContext('xcodebuild versionText handles Xcode version string with unexpected format', () {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>['xcrun', 'xcodebuild', '-version'], command: <String>['xcrun', 'xcodebuild', '-version'],
stdout: 'Xcode Ultra5000\nBuild version 8E3004b', stdout: 'Xcode Ultra5000\nBuild version 8E3004b',
...@@ -128,7 +140,7 @@ void main() { ...@@ -128,7 +140,7 @@ void main() {
testWithoutContext('xcodebuild version parts can be parsed', () { testWithoutContext('xcodebuild version parts can be parsed', () {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>['xcrun', 'xcodebuild', '-version'], command: <String>['xcrun', 'xcodebuild', '-version'],
stdout: 'Xcode 11.4.1\nBuild version 11N111s', stdout: 'Xcode 11.4.1\nBuild version 11N111s',
...@@ -142,7 +154,7 @@ void main() { ...@@ -142,7 +154,7 @@ void main() {
testWithoutContext('xcodebuild minor and patch version default to 0', () { testWithoutContext('xcodebuild minor and patch version default to 0', () {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>['xcrun', 'xcodebuild', '-version'], command: <String>['xcrun', 'xcodebuild', '-version'],
stdout: 'Xcode 11\nBuild version 11N111s', stdout: 'Xcode 11\nBuild version 11N111s',
...@@ -156,7 +168,7 @@ void main() { ...@@ -156,7 +168,7 @@ void main() {
testWithoutContext('xcodebuild version parts is null when version has unexpected format', () { testWithoutContext('xcodebuild version parts is null when version has unexpected format', () {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>['xcrun', 'xcodebuild', '-version'], command: <String>['xcrun', 'xcodebuild', '-version'],
stdout: 'Xcode Ultra5000\nBuild version 8E3004b', stdout: 'Xcode Ultra5000\nBuild version 8E3004b',
...@@ -192,7 +204,7 @@ void main() { ...@@ -192,7 +204,7 @@ void main() {
'xcodebuild isInstalled is false when Xcode is not fully installed', () { 'xcodebuild isInstalled is false when Xcode is not fully installed', () {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>['xcrun', 'xcodebuild', '-version'], command: <String>['xcrun', 'xcodebuild', '-version'],
stdout: "xcode-select: error: tool 'xcodebuild' requires Xcode, " stdout: "xcode-select: error: tool 'xcodebuild' requires Xcode, "
...@@ -209,7 +221,7 @@ void main() { ...@@ -209,7 +221,7 @@ void main() {
testWithoutContext('xcodebuild isInstalled is false when version has unexpected format', () { testWithoutContext('xcodebuild isInstalled is false when version has unexpected format', () {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>['xcrun', 'xcodebuild', '-version'], command: <String>['xcrun', 'xcodebuild', '-version'],
stdout: 'Xcode Ultra5000\nBuild version 8E3004b', stdout: 'Xcode Ultra5000\nBuild version 8E3004b',
...@@ -223,7 +235,7 @@ void main() { ...@@ -223,7 +235,7 @@ void main() {
testWithoutContext('xcodebuild isInstalled is true when version has expected format', () { testWithoutContext('xcodebuild isInstalled is true when version has expected format', () {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>['xcrun', 'xcodebuild', '-version'], command: <String>['xcrun', 'xcodebuild', '-version'],
stdout: 'Xcode 8.3.3\nBuild version 8E3004b', stdout: 'Xcode 8.3.3\nBuild version 8E3004b',
...@@ -237,13 +249,7 @@ void main() { ...@@ -237,13 +249,7 @@ void main() {
testWithoutContext('xcrun runs natively on arm64', () { testWithoutContext('xcrun runs natively on arm64', () {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
FakeCommand( kARMCheckCommand,
command: <String>[
'sysctl',
'hw.optional.arm64',
],
stdout: 'hw.optional.arm64: 1',
),
]); ]);
expect(xcodeProjectInterpreter.xcrunCommand(), <String>[ expect(xcodeProjectInterpreter.xcrunCommand(), <String>[
...@@ -295,7 +301,7 @@ void main() { ...@@ -295,7 +301,7 @@ void main() {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>[ command: <String>[
'xcrun', 'xcrun',
...@@ -329,7 +335,7 @@ void main() { ...@@ -329,7 +335,7 @@ void main() {
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>[ command: <String>[
'xcrun', 'xcrun',
...@@ -358,7 +364,7 @@ void main() { ...@@ -358,7 +364,7 @@ void main() {
}; };
fakeProcessManager.addCommands(<FakeCommand>[ fakeProcessManager.addCommands(<FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>[ command: <String>[
'xcrun', 'xcrun',
...@@ -391,7 +397,7 @@ void main() { ...@@ -391,7 +397,7 @@ void main() {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>[ command: <String>[
'xcrun', 'xcrun',
...@@ -416,7 +422,7 @@ void main() { ...@@ -416,7 +422,7 @@ void main() {
const String workingDirectory = '/'; const String workingDirectory = '/';
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>['xcrun', 'xcodebuild', '-list'], command: <String>['xcrun', 'xcodebuild', '-list'],
), ),
...@@ -440,7 +446,7 @@ void main() { ...@@ -440,7 +446,7 @@ void main() {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>['xcrun', 'xcodebuild', '-list'], command: <String>['xcrun', 'xcodebuild', '-list'],
exitCode: 66, exitCode: 66,
...@@ -466,7 +472,7 @@ void main() { ...@@ -466,7 +472,7 @@ void main() {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand, kWhichSysctlCommand,
kARMCheckCommand, kx64CheckCommand,
FakeCommand( FakeCommand(
command: <String>['xcrun', 'xcodebuild', '-list'], command: <String>['xcrun', 'xcodebuild', '-list'],
exitCode: 74, exitCode: 74,
...@@ -676,10 +682,171 @@ Information about project "Runner": ...@@ -676,10 +682,171 @@ Information about project "Runner":
fs.file(xcodebuild).createSync(recursive: true); fs.file(xcodebuild).createSync(recursive: true);
}); });
group('arm simulator', () {
FakeProcessManager fakeProcessManager;
XcodeProjectInterpreter xcodeProjectInterpreter;
setUp(() {
fakeProcessManager = FakeProcessManager.empty();
xcodeProjectInterpreter = XcodeProjectInterpreter.test(processManager: fakeProcessManager);
});
testUsingContext('does not exclude arm64 simulator when supported by all plugins', () async {
const BuildInfo buildInfo = BuildInfo.debug;
final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project'));
final Directory podXcodeProject = project.ios.hostAppRoot.childDirectory('Pods').childDirectory('Pods.xcodeproj')
..createSync(recursive: true);
fakeProcessManager.addCommands(<FakeCommand>[
kWhichSysctlCommand,
kARMCheckCommand,
FakeCommand(
command: <String>[
'/usr/bin/arch',
'-arm64e',
'xcrun',
'xcodebuild',
'-alltargets',
'-sdk',
'iphonesimulator',
'-project',
podXcodeProject.path,
'-showBuildSettings',
],
stdout: '''
Build settings for action build and target plugin1:
ENABLE_BITCODE = NO;
EXCLUDED_ARCHS = i386;
INFOPLIST_FILE = Runner/Info.plist;
UNRELATED_BUILD_SETTING = arm64;
Build settings for action build and target plugin2:
ENABLE_BITCODE = NO;
EXCLUDED_ARCHS = i386;
INFOPLIST_FILE = Runner/Info.plist;
UNRELATED_BUILD_SETTING = arm64;
'''
),
]);
await updateGeneratedXcodeProperties(
project: project,
buildInfo: buildInfo,
);
final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig');
expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386\n'));
expect(fakeProcessManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{
Artifacts: () => localArtifacts,
Platform: () => macOS,
OperatingSystemUtils: () => FakeOperatingSystemUtils(hostPlatform: HostPlatform.darwin_arm),
FileSystem: () => fs,
ProcessManager: () => fakeProcessManager,
XcodeProjectInterpreter: () => xcodeProjectInterpreter,
});
testUsingContext('excludes arm64 simulator when build setting fetch fails', () async {
const BuildInfo buildInfo = BuildInfo.debug;
final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project'));
final Directory podXcodeProject = project.ios.hostAppRoot.childDirectory('Pods').childDirectory('Pods.xcodeproj')
..createSync(recursive: true);
fakeProcessManager.addCommands(<FakeCommand>[
kWhichSysctlCommand,
kARMCheckCommand,
FakeCommand(
command: <String>[
'/usr/bin/arch',
'-arm64e',
'xcrun',
'xcodebuild',
'-alltargets',
'-sdk',
'iphonesimulator',
'-project',
podXcodeProject.path,
'-showBuildSettings',
],
exitCode: 1,
),
]);
await updateGeneratedXcodeProperties(
project: project,
buildInfo: buildInfo,
);
final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig');
expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386 arm64\n'));
expect(fakeProcessManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{
Artifacts: () => localArtifacts,
Platform: () => macOS,
OperatingSystemUtils: () => FakeOperatingSystemUtils(hostPlatform: HostPlatform.darwin_arm),
FileSystem: () => fs,
ProcessManager: () => fakeProcessManager,
XcodeProjectInterpreter: () => xcodeProjectInterpreter,
});
testUsingContext('excludes arm64 simulator when unsupported by plugins', () async {
const BuildInfo buildInfo = BuildInfo.debug;
final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project'));
final Directory podXcodeProject = project.ios.hostAppRoot.childDirectory('Pods').childDirectory('Pods.xcodeproj')
..createSync(recursive: true);
fakeProcessManager.addCommands(<FakeCommand>[
kWhichSysctlCommand,
kARMCheckCommand,
FakeCommand(
command: <String>[
'/usr/bin/arch',
'-arm64e',
'xcrun',
'xcodebuild',
'-alltargets',
'-sdk',
'iphonesimulator',
'-project',
podXcodeProject.path,
'-showBuildSettings',
],
stdout: '''
Build settings for action build and target plugin1:
ENABLE_BITCODE = NO;
EXCLUDED_ARCHS = i386;
INFOPLIST_FILE = Runner/Info.plist;
UNRELATED_BUILD_SETTING = arm64;
Build settings for action build and target plugin2:
ENABLE_BITCODE = NO;
EXCLUDED_ARCHS = i386 arm64;
INFOPLIST_FILE = Runner/Info.plist;
UNRELATED_BUILD_SETTING = arm64;
'''
),
]);
await updateGeneratedXcodeProperties(
project: project,
buildInfo: buildInfo,
);
final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig');
expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386 arm64\n'));
expect(fakeProcessManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{
Artifacts: () => localArtifacts,
Platform: () => macOS,
OperatingSystemUtils: () => FakeOperatingSystemUtils(hostPlatform: HostPlatform.darwin_arm),
FileSystem: () => fs,
ProcessManager: () => fakeProcessManager,
XcodeProjectInterpreter: () => xcodeProjectInterpreter,
});
});
void testUsingOsxContext(String description, dynamic Function() testMethod) { void testUsingOsxContext(String description, dynamic Function() testMethod) {
testUsingContext(description, testMethod, overrides: <Type, Generator>{ testUsingContext(description, testMethod, overrides: <Type, Generator>{
Artifacts: () => localArtifacts, Artifacts: () => localArtifacts,
Platform: () => macOS, Platform: () => macOS,
OperatingSystemUtils: () => FakeOperatingSystemUtils(hostPlatform: HostPlatform.darwin_x64),
FileSystem: () => fs, FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
}); });
...@@ -708,6 +875,21 @@ Information about project "Runner": ...@@ -708,6 +875,21 @@ Information about project "Runner":
expect(buildPhaseScriptContents.contains('EXCLUDED_ARCHS'), isFalse); expect(buildPhaseScriptContents.contains('EXCLUDED_ARCHS'), isFalse);
}); });
testUsingOsxContext('excludes i386 simulator', () async {
const BuildInfo buildInfo = BuildInfo.debug;
final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project'));
await updateGeneratedXcodeProperties(
project: project,
buildInfo: buildInfo,
);
final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig');
expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386\n'));
final File buildPhaseScript = fs.file('path/to/project/ios/Flutter/flutter_export_environment.sh');
expect(buildPhaseScript.readAsStringSync(), isNot(contains('EXCLUDED_ARCHS')));
});
testUsingOsxContext('sets TRACK_WIDGET_CREATION=true when trackWidgetCreation is true', () async { testUsingOsxContext('sets TRACK_WIDGET_CREATION=true when trackWidgetCreation is true', () async {
const BuildInfo buildInfo = BuildInfo(BuildMode.debug, null, trackWidgetCreation: true, treeShakeIcons: false); const BuildInfo buildInfo = BuildInfo(BuildMode.debug, null, trackWidgetCreation: true, treeShakeIcons: false);
final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project')); final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project'));
......
...@@ -306,6 +306,14 @@ class FakeXcodeProjectInterpreter implements XcodeProjectInterpreter { ...@@ -306,6 +306,14 @@ class FakeXcodeProjectInterpreter implements XcodeProjectInterpreter {
return <String, String>{}; return <String, String>{};
} }
@override
Future<String> pluginsBuildSettingsOutput(
Directory podXcodeProject, {
Duration timeout = const Duration(minutes: 1),
}) async {
return null;
}
@override @override
Future<void> cleanWorkspace(String workspacePath, String scheme, { bool verbose = false }) { Future<void> cleanWorkspace(String workspacePath, String scheme, { bool verbose = false }) {
return null; 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