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 {