Run more xcodebuild commands in native arm on Apple Silicon (#69837)
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
index 043179e..0a39a87 100644
--- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart
+++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -10,6 +10,7 @@
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
+import '../base/os.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../base/terminal.dart';
@@ -242,26 +243,32 @@
_terminal = terminal,
_logger = logger,
_processUtils = ProcessUtils(logger: logger, processManager: processManager),
+ _operatingSystemUtils = OperatingSystemUtils(
+ fileSystem: fileSystem,
+ logger: logger,
+ platform: platform,
+ processManager: processManager,
+ ),
_usage = usage;
final Platform _platform;
final FileSystem _fileSystem;
final ProcessUtils _processUtils;
+ final OperatingSystemUtils _operatingSystemUtils;
final Terminal _terminal;
final Logger _logger;
final Usage _usage;
- static const String _executable = '/usr/bin/xcodebuild';
static final RegExp _versionRegex = RegExp(r'Xcode ([0-9.]+)');
void _updateVersion() {
- if (!_platform.isMacOS || !_fileSystem.file(_executable).existsSync()) {
+ if (!_platform.isMacOS || !_fileSystem.file('/usr/bin/xcodebuild').existsSync()) {
return;
}
try {
if (_versionText == null) {
final RunResult result = _processUtils.runSync(
- <String>[_executable, '-version'],
+ <String>[...xcrunCommand(), 'xcodebuild', '-version'],
);
if (result.exitCode != 0) {
return;
@@ -316,6 +323,25 @@
return _patchVersion;
}
+ /// The `xcrun` Xcode command to run or locate development
+ /// tools and properties.
+ ///
+ /// Returns `xcrun` on x86 macOS.
+ /// Returns `/usr/bin/arch -arm64e xcrun` on ARM macOS to force Xcode commands
+ /// to run outside the x86 Rosetta translation, which may cause crashes.
+ List<String> xcrunCommand() {
+ final List<String> xcrunCommand = <String>[];
+ if (_operatingSystemUtils.hostPlatform == HostPlatform.darwin_arm) {
+ // Force Xcode commands to run outside Rosetta.
+ xcrunCommand.addAll(<String>[
+ '/usr/bin/arch',
+ '-arm64e',
+ ]);
+ }
+ xcrunCommand.add('xcrun');
+ return xcrunCommand;
+ }
+
/// Asynchronously retrieve xcode build settings. This one is preferred for
/// new call-sites.
///
@@ -331,7 +357,8 @@
terminal: _terminal,
);
final List<String> showBuildSettingsCommand = <String>[
- _executable,
+ ...xcrunCommand(),
+ 'xcodebuild',
'-project',
_fileSystem.path.absolute(projectPath),
if (scheme != null)
@@ -368,7 +395,8 @@
Future<void> cleanWorkspace(String workspacePath, String scheme, { bool verbose = false }) async {
await _processUtils.run(<String>[
- _executable,
+ ...xcrunCommand(),
+ 'xcodebuild',
'-workspace',
workspacePath,
'-scheme',
@@ -387,7 +415,8 @@
const int missingProjectExitCode = 66;
final RunResult result = await _processUtils.run(
<String>[
- _executable,
+ ...xcrunCommand(),
+ 'xcodebuild',
'-list',
if (projectFilename != null) ...<String>['-project', projectFilename],
],
diff --git a/packages/flutter_tools/lib/src/macos/xcode.dart b/packages/flutter_tools/lib/src/macos/xcode.dart
index 887a768..edc167b 100644
--- a/packages/flutter_tools/lib/src/macos/xcode.dart
+++ b/packages/flutter_tools/lib/src/macos/xcode.dart
@@ -12,7 +12,6 @@
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
-import '../base/os.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../build_info.dart';
@@ -66,18 +65,11 @@
}) : _platform = platform,
_fileSystem = fileSystem,
_xcodeProjectInterpreter = xcodeProjectInterpreter,
- _operatingSystemUtils = OperatingSystemUtils(
- fileSystem: fileSystem,
- logger: logger,
- platform: platform,
- processManager: processManager,
- ),
_processUtils =
ProcessUtils(logger: logger, processManager: processManager);
final Platform _platform;
final ProcessUtils _processUtils;
- final OperatingSystemUtils _operatingSystemUtils;
final FileSystem _fileSystem;
final XcodeProjectInterpreter _xcodeProjectInterpreter;
@@ -169,24 +161,8 @@
return false;
}
- /// The `xcrun` Xcode command to run or locate development
- /// tools and properties.
- ///
- /// Returns `xcrun` on x86 macOS.
- /// Returns `/usr/bin/arch -arm64e xcrun` on ARM macOS to force Xcode commands
- /// to run outside the x86 Rosetta translation, which may cause crashes.
- List<String> xcrunCommand() {
- final List<String> xcrunCommand = <String>[];
- if (_operatingSystemUtils.hostPlatform == HostPlatform.darwin_arm) {
- // Force Xcode commands to run outside Rosetta.
- xcrunCommand.addAll(<String>[
- '/usr/bin/arch',
- '-arm64e',
- ]);
- }
- xcrunCommand.add('xcrun');
- return xcrunCommand;
- }
+ /// See [XcodeProjectInterpreter.xcrunCommand].
+ List<String> xcrunCommand() => _xcodeProjectInterpreter.xcrunCommand();
Future<RunResult> cc(List<String> args) {
return _processUtils.run(
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart
index 0355ca5..a500e63 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart
@@ -77,14 +77,6 @@
'xattr', '-r', '-d', 'com.apple.FinderInfo', '/ios'
]);
- const FakeCommand armCheckCommand = FakeCommand(
- command: <String>[
- 'sysctl',
- 'hw.optional.arm64',
- ],
- exitCode: 1,
- );
-
// Creates a FakeCommand for the xcodebuild call to build the app
// in the given configuration.
FakeCommand setUpMockXcodeBuildHandler({ bool verbose = false, bool showBuildSettings = false, void Function() onRun }) {
@@ -215,7 +207,6 @@
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
xattrCommand,
- armCheckCommand,
setUpMockXcodeBuildHandler(),
setUpMockXcodeBuildHandler(showBuildSettings: true),
]),
@@ -234,7 +225,6 @@
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
xattrCommand,
- armCheckCommand,
setUpMockXcodeBuildHandler(verbose: true),
setUpMockXcodeBuildHandler(verbose: true, showBuildSettings: true),
]),
@@ -263,7 +253,6 @@
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
xattrCommand,
- armCheckCommand,
setUpMockXcodeBuildHandler(onRun: () {
fileSystem.file('build/flutter_size_01/snapshot.arm64.json')
..createSync(recursive: true)
@@ -311,7 +300,6 @@
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
xattrCommand,
- armCheckCommand,
setUpMockXcodeBuildHandler(),
setUpMockXcodeBuildHandler(showBuildSettings: true),
exportArchiveCommand,
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/common_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/common_test.dart
index 59c640b..772a1cf 100644
--- a/packages/flutter_tools/test/general.shard/build_system/targets/common_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/targets/common_test.dart
@@ -478,13 +478,6 @@
'--lazy-async-stacks',
'$build/app.dill',
]),
- const FakeCommand(
- command: <String>[
- 'sysctl',
- 'hw.optional.arm64',
- ],
- exitCode: 1,
- ),
FakeCommand(command: <String>[
'xcrun',
'cc',
@@ -593,13 +586,6 @@
'--lazy-async-stacks',
'$build/app.dill',
]),
- const FakeCommand(
- command: <String>[
- 'sysctl',
- 'hw.optional.arm64',
- ],
- exitCode: 1,
- ),
FakeCommand(command: <String>[
'xcrun',
'cc',
@@ -677,13 +663,6 @@
'--lazy-async-stacks',
'$build/app.dill',
]),
- const FakeCommand(
- command: <String>[
- 'sysctl',
- 'hw.optional.arm64',
- ],
- exitCode: 1,
- ),
FakeCommand(command: <String>[
'xcrun',
'cc',
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart
index e953ffa..5b4f1dc 100644
--- a/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart
@@ -71,14 +71,6 @@
testUsingContext('DebugUniveralFramework creates expected binary with arm64 only arch', () async {
environment.defines[kIosArchs] = 'arm64';
processManager.addCommands(<FakeCommand>[
- // Create iphone stub.
- const FakeCommand(
- command: <String>[
- 'sysctl',
- 'hw.optional.arm64',
- ],
- exitCode: 1,
- ),
const FakeCommand(command: <String>['xcrun', '--sdk', 'iphoneos', '--show-sdk-path']),
FakeCommand(command: <String>[
'xcrun',
diff --git a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
index c324482..d81fa7d 100644
--- a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
@@ -51,7 +51,9 @@
// Work around https://github.com/flutter/flutter/issues/56415.
testWithoutContext('xcodebuild versionText returns null when xcodebuild is not installed', () {
- when(processManager.runSync(<String>[xcodebuild, '-version']))
+ when(processManager.runSync(<String>['sysctl', 'hw.optional.arm64']))
+ .thenReturn(ProcessResult(0, 1, '', ''));
+ when(processManager.runSync(<String>['xcrun', 'xcodebuild', '-version']))
.thenThrow(const ProcessException(xcodebuild, <String>['-version']));
expect(xcodeProjectInterpreter.versionText, isNull);
@@ -65,6 +67,9 @@
);
platform.environment = const <String, String>{};
+ when(processManager.runSync(<String>['sysctl', 'hw.optional.arm64']))
+ .thenReturn(ProcessResult(0, 1, '', ''));
+
expect(await xcodeProjectInterpreter.getBuildSettings(
'', scheme: 'Runner', timeout: delay),
const <String, String>{});
@@ -75,6 +80,14 @@
});
});
+ const FakeCommand kARMCheckCommand = FakeCommand(
+ command: <String>[
+ 'sysctl',
+ 'hw.optional.arm64',
+ ],
+ exitCode: 1,
+ );
+
FakeProcessManager fakeProcessManager;
XcodeProjectInterpreter xcodeProjectInterpreter;
FakePlatform platform;
@@ -102,43 +115,55 @@
});
testWithoutContext('xcodebuild versionText returns null when xcodebuild is not fully installed', () {
- fakeProcessManager.addCommand(const FakeCommand(
- command: <String>[xcodebuild, '-version'],
- stdout: "xcode-select: error: tool 'xcodebuild' requires Xcode, "
- "but active developer directory '/Library/Developer/CommandLineTools' "
- 'is a command line tools instance',
- exitCode: 1,
- ));
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ kARMCheckCommand,
+ FakeCommand(
+ command: <String>['xcrun', 'xcodebuild', '-version'],
+ stdout: "xcode-select: error: tool 'xcodebuild' requires Xcode, "
+ "but active developer directory '/Library/Developer/CommandLineTools' "
+ 'is a command line tools instance',
+ exitCode: 1,
+ ),
+ ]);
expect(xcodeProjectInterpreter.versionText, isNull);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('xcodebuild versionText returns formatted version text', () {
- fakeProcessManager.addCommand(const FakeCommand(
- command: <String>[xcodebuild, '-version'],
- stdout: 'Xcode 8.3.3\nBuild version 8E3004b',
- ));
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ kARMCheckCommand,
+ FakeCommand(
+ command: <String>['xcrun', 'xcodebuild', '-version'],
+ stdout: 'Xcode 8.3.3\nBuild version 8E3004b',
+ ),
+ ]);
expect(xcodeProjectInterpreter.versionText, 'Xcode 8.3.3, Build version 8E3004b');
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('xcodebuild versionText handles Xcode version string with unexpected format', () {
- fakeProcessManager.addCommand(const FakeCommand(
- command: <String>[xcodebuild, '-version'],
- stdout: 'Xcode Ultra5000\nBuild version 8E3004b',
- ));
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ kARMCheckCommand,
+ FakeCommand(
+ command: <String>['xcrun', 'xcodebuild', '-version'],
+ stdout: 'Xcode Ultra5000\nBuild version 8E3004b',
+ ),
+ ]);
expect(xcodeProjectInterpreter.versionText, 'Xcode Ultra5000, Build version 8E3004b');
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('xcodebuild version parts can be parsed', () {
- fakeProcessManager.addCommand(const FakeCommand(
- command: <String>[xcodebuild, '-version'],
- stdout: 'Xcode 11.4.1\nBuild version 11N111s',
- ));
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ kARMCheckCommand,
+ FakeCommand(
+ command: <String>['xcrun', 'xcodebuild', '-version'],
+ stdout: 'Xcode 11.4.1\nBuild version 11N111s',
+ ),
+ ]);
expect(xcodeProjectInterpreter.majorVersion, 11);
expect(xcodeProjectInterpreter.minorVersion, 4);
@@ -147,10 +172,13 @@
});
testWithoutContext('xcodebuild minor and patch version default to 0', () {
- fakeProcessManager.addCommand(const FakeCommand(
- command: <String>[xcodebuild, '-version'],
- stdout: 'Xcode 11\nBuild version 11N111s',
- ));
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ kARMCheckCommand,
+ FakeCommand(
+ command: <String>['xcrun', 'xcodebuild', '-version'],
+ stdout: 'Xcode 11\nBuild version 11N111s',
+ ),
+ ]);
expect(xcodeProjectInterpreter.majorVersion, 11);
expect(xcodeProjectInterpreter.minorVersion, 0);
@@ -159,10 +187,13 @@
});
testWithoutContext('xcodebuild version parts is null when version has unexpected format', () {
- fakeProcessManager.addCommand(const FakeCommand(
- command: <String>[xcodebuild, '-version'],
- stdout: 'Xcode Ultra5000\nBuild version 8E3004b',
- ));
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ kARMCheckCommand,
+ FakeCommand(
+ command: <String>['xcrun', 'xcodebuild', '-version'],
+ stdout: 'Xcode Ultra5000\nBuild version 8E3004b',
+ ),
+ ]);
expect(xcodeProjectInterpreter.majorVersion, isNull);
expect(xcodeProjectInterpreter.minorVersion, isNull);
expect(xcodeProjectInterpreter.patchVersion, isNull);
@@ -192,53 +223,92 @@
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
- testWithoutContext('xcodebuild isInstalled is false when Xcode is not fully installed', () {
- fakeProcessManager.addCommand(const FakeCommand(
- command: <String>[xcodebuild, '-version'],
- stdout: "xcode-select: error: tool 'xcodebuild' requires Xcode, "
- "but active developer directory '/Library/Developer/CommandLineTools' "
- 'is a command line tools instance',
- exitCode: 1,
- ));
+ testWithoutContext(
+ 'xcodebuild isInstalled is false when Xcode is not fully installed', () {
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ kARMCheckCommand,
+ FakeCommand(
+ command: <String>['xcrun', 'xcodebuild', '-version'],
+ stdout: "xcode-select: error: tool 'xcodebuild' requires Xcode, "
+ "but active developer directory '/Library/Developer/CommandLineTools' "
+ 'is a command line tools instance',
+ exitCode: 1,
+ ),
+ ]);
expect(xcodeProjectInterpreter.isInstalled, isFalse);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('xcodebuild isInstalled is false when version has unexpected format', () {
- fakeProcessManager.addCommand(const FakeCommand(
- command: <String>[xcodebuild, '-version'],
- stdout: 'Xcode Ultra5000\nBuild version 8E3004b',
- ));
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ kARMCheckCommand,
+ FakeCommand(
+ command: <String>['xcrun', 'xcodebuild', '-version'],
+ stdout: 'Xcode Ultra5000\nBuild version 8E3004b',
+ ),
+ ]);
expect(xcodeProjectInterpreter.isInstalled, isFalse);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('xcodebuild isInstalled is true when version has expected format', () {
- fakeProcessManager.addCommand(const FakeCommand(
- command: <String>[xcodebuild, '-version'],
- stdout: 'Xcode 8.3.3\nBuild version 8E3004b',
- ));
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ kARMCheckCommand,
+ FakeCommand(
+ command: <String>['xcrun', 'xcodebuild', '-version'],
+ stdout: 'Xcode 8.3.3\nBuild version 8E3004b',
+ ),
+ ]);
expect(xcodeProjectInterpreter.isInstalled, isTrue);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
+ testWithoutContext('xcrun runs natively on arm64', () {
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ FakeCommand(
+ command: <String>[
+ 'sysctl',
+ 'hw.optional.arm64',
+ ],
+ stdout: 'hw.optional.arm64: 1',
+ ),
+ ]);
+
+ expect(xcodeProjectInterpreter.xcrunCommand(), <String>[
+ '/usr/bin/arch',
+ '-arm64e',
+ 'xcrun',
+ ]);
+ expect(fakeProcessManager.hasRemainingExpectations, isFalse);
+ });
+
testWithoutContext('xcodebuild build settings is empty when xcodebuild failed to get the build settings', () async {
platform.environment = const <String, String>{};
- fakeProcessManager.addCommand(const FakeCommand(
- command: <String>[
- '/usr/bin/xcodebuild',
- '-project',
- '/',
- '-scheme',
- 'Free',
- '-showBuildSettings'
- ],
- exitCode: 1,
- ));
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ FakeCommand(
+ command: <String>[
+ 'sysctl',
+ 'hw.optional.arm64',
+ ],
+ exitCode: 1,
+ ),
+ FakeCommand(
+ command: <String>[
+ 'xcrun',
+ 'xcodebuild',
+ '-project',
+ '/',
+ '-scheme',
+ 'Free',
+ '-showBuildSettings'
+ ],
+ exitCode: 1,
+ ),
+ ]);
expect(await xcodeProjectInterpreter.getBuildSettings('', scheme: 'Free'), const <String, String>{});
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
@@ -247,15 +317,19 @@
testWithoutContext('build settings accepts an empty scheme', () async {
platform.environment = const <String, String>{};
- fakeProcessManager.addCommand(const FakeCommand(
- command: <String>[
- '/usr/bin/xcodebuild',
- '-project',
- '/',
- '-showBuildSettings'
- ],
- exitCode: 1,
- ));
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ kARMCheckCommand,
+ FakeCommand(
+ command: <String>[
+ 'xcrun',
+ 'xcodebuild',
+ '-project',
+ '/',
+ '-showBuildSettings'
+ ],
+ exitCode: 1,
+ ),
+ ]);
expect(await xcodeProjectInterpreter.getBuildSettings(''), const <String, String>{});
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
@@ -266,18 +340,22 @@
'FLUTTER_XCODE_CODE_SIGN_STYLE': 'Manual',
'FLUTTER_XCODE_ARCHS': 'arm64'
};
- fakeProcessManager.addCommand(FakeCommand(
- command: <String>[
- xcodebuild,
- '-project',
- fileSystem.path.separator,
- '-scheme',
- 'Free',
- '-showBuildSettings',
- 'CODE_SIGN_STYLE=Manual',
- 'ARCHS=arm64'
- ],
- ));
+ fakeProcessManager.addCommands(<FakeCommand>[
+ kARMCheckCommand,
+ FakeCommand(
+ command: <String>[
+ 'xcrun',
+ 'xcodebuild',
+ '-project',
+ fileSystem.path.separator,
+ '-scheme',
+ 'Free',
+ '-showBuildSettings',
+ 'CODE_SIGN_STYLE=Manual',
+ 'ARCHS=arm64'
+ ],
+ ),
+ ]);
expect(await xcodeProjectInterpreter.getBuildSettings('', scheme: 'Free'), const <String, String>{});
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
@@ -288,19 +366,23 @@
'FLUTTER_XCODE_ARCHS': 'arm64'
};
- fakeProcessManager.addCommand(const FakeCommand(
- command: <String>[
- xcodebuild,
- '-workspace',
- 'workspace_path',
- '-scheme',
- 'Free',
- '-quiet',
- 'clean',
- 'CODE_SIGN_STYLE=Manual',
- 'ARCHS=arm64'
- ],
- ));
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ kARMCheckCommand,
+ FakeCommand(
+ command: <String>[
+ 'xcrun',
+ 'xcodebuild',
+ '-workspace',
+ 'workspace_path',
+ '-scheme',
+ 'Free',
+ '-quiet',
+ 'clean',
+ 'CODE_SIGN_STYLE=Manual',
+ 'ARCHS=arm64'
+ ],
+ ),
+ ]);
await xcodeProjectInterpreter.cleanWorkspace('workspace_path', 'Free');
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
@@ -308,9 +390,12 @@
testWithoutContext('xcodebuild -list getInfo returns something when xcodebuild -list succeeds', () async {
const String workingDirectory = '/';
- fakeProcessManager.addCommand(const FakeCommand(
- command: <String>[xcodebuild, '-list'],
- ));
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ kARMCheckCommand,
+ FakeCommand(
+ command: <String>['xcrun', 'xcodebuild', '-list'],
+ ),
+ ]);
final XcodeProjectInterpreter xcodeProjectInterpreter = XcodeProjectInterpreter(
logger: logger,
@@ -329,11 +414,14 @@
const String workingDirectory = '/';
const String stderr = 'Useful Xcode failure message about missing project.';
- fakeProcessManager.addCommand(const FakeCommand(
- command: <String>[xcodebuild, '-list'],
- exitCode: 66,
- stderr: stderr,
- ));
+ fakeProcessManager.addCommands(const <FakeCommand>[
+ kARMCheckCommand,
+ FakeCommand(
+ command: <String>['xcrun', 'xcodebuild', '-list'],
+ exitCode: 66,
+ stderr: stderr,
+ ),
+ ]);
final XcodeProjectInterpreter xcodeProjectInterpreter = XcodeProjectInterpreter(
logger: logger,
diff --git a/packages/flutter_tools/test/general.shard/macos/xcode_test.dart b/packages/flutter_tools/test/general.shard/macos/xcode_test.dart
index badb15e..71b429a 100644
--- a/packages/flutter_tools/test/general.shard/macos/xcode_test.dart
+++ b/packages/flutter_tools/test/general.shard/macos/xcode_test.dart
@@ -39,14 +39,16 @@
group('Xcode', () {
Xcode xcode;
+ MockXcodeProjectInterpreter mockXcodeProjectInterpreter;
setUp(() {
+ mockXcodeProjectInterpreter = MockXcodeProjectInterpreter();
xcode = Xcode(
logger: logger,
platform: FakePlatform(operatingSystem: 'macos'),
fileSystem: MemoryFileSystem.test(),
processManager: processManager,
- xcodeProjectInterpreter: MockXcodeProjectInterpreter(),
+ xcodeProjectInterpreter: mockXcodeProjectInterpreter,
);
});
@@ -61,6 +63,8 @@
});
testWithoutContext('eulaSigned is false when clang is not installed', () {
+ when(mockXcodeProjectInterpreter.xcrunCommand()).thenReturn(<String>['xcrun']);
+
when(processManager.runSync(<String>['sysctl', 'hw.optional.arm64']))
.thenReturn(ProcessResult(123, 1, '', ''));
when(processManager.runSync(<String>['xcrun', 'clang']))
@@ -140,6 +144,7 @@
setUp(() {
mockXcodeProjectInterpreter = MockXcodeProjectInterpreter();
+ when(mockXcodeProjectInterpreter.xcrunCommand()).thenReturn(<String>['xcrun']);
platform = FakePlatform(operatingSystem: 'macos');
xcode = Xcode(
logger: logger,
@@ -252,25 +257,6 @@
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
- testWithoutContext('xcrun runs natively on arm64', () {
- fakeProcessManager.addCommands(const <FakeCommand>[
- FakeCommand(
- command: <String>[
- 'sysctl',
- 'hw.optional.arm64',
- ],
- stdout: 'hw.optional.arm64: 1',
- ),
- ]);
-
- expect(xcode.xcrunCommand(), <String>[
- '/usr/bin/arch',
- '-arm64e',
- 'xcrun',
- ]);
- expect(fakeProcessManager.hasRemainingExpectations, isFalse);
- });
-
testWithoutContext('isInstalledAndMeetsVersionCheck is true when macOS and installed and version is satisfied', () {
fakeProcessManager.addCommand(const FakeCommand(
command: <String>['/usr/bin/xcode-select', '--print-path'],
@@ -288,13 +274,6 @@
testWithoutContext('eulaSigned is false when clang output indicates EULA not yet accepted', () {
fakeProcessManager.addCommands(const <FakeCommand>[
FakeCommand(
- command: <String>[
- 'sysctl',
- 'hw.optional.arm64',
- ],
- exitCode: 1,
- ),
- FakeCommand(
command: <String>['xcrun', 'clang'],
exitCode: 1,
stderr:
@@ -310,13 +289,6 @@
fakeProcessManager.addCommands(
const <FakeCommand>[
FakeCommand(
- command: <String>[
- 'sysctl',
- 'hw.optional.arm64',
- ],
- exitCode: 1,
- ),
- FakeCommand(
command: <String>['xcrun', 'clang'],
exitCode: 1,
stderr: 'clang: error: no input files',
@@ -334,18 +306,6 @@
});
group('SDK location', () {
- setUp(() {
- fakeProcessManager.addCommand(
- const FakeCommand(
- command: <String>[
- 'sysctl',
- 'hw.optional.arm64',
- ],
- exitCode: 1,
- ),
- );
- });
-
const String sdkroot = 'Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk';
testWithoutContext('--show-sdk-path iphoneos', () async {
diff --git a/packages/flutter_tools/test/src/context.dart b/packages/flutter_tools/test/src/context.dart
index 6adb7dc..0813ecc 100644
--- a/packages/flutter_tools/test/src/context.dart
+++ b/packages/flutter_tools/test/src/context.dart
@@ -414,6 +414,9 @@
BufferLogger.test(),
);
}
+
+ @override
+ List<String> xcrunCommand() => <String>['xcrun'];
}
class MockFlutterVersion extends Mock implements FlutterVersion {