Unverified Commit 2f3cccc4 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Run more xcodebuild commands in native arm on Apple Silicon (#69837)

parent 4eabee88
......@@ -10,6 +10,7 @@ import '../base/common.dart';
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 @@ class XcodeProjectInterpreter {
_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 @@ class XcodeProjectInterpreter {
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 @@ class XcodeProjectInterpreter {
terminal: _terminal,
);
final List<String> showBuildSettingsCommand = <String>[
_executable,
...xcrunCommand(),
'xcodebuild',
'-project',
_fileSystem.path.absolute(projectPath),
if (scheme != null)
......@@ -368,7 +395,8 @@ class XcodeProjectInterpreter {
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 @@ class XcodeProjectInterpreter {
const int missingProjectExitCode = 66;
final RunResult result = await _processUtils.run(
<String>[
_executable,
...xcrunCommand(),
'xcodebuild',
'-list',
if (projectFilename != null) ...<String>['-project', projectFilename],
],
......
......@@ -12,7 +12,6 @@ import '../base/common.dart';
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 @@ class Xcode {
}) : _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 @@ class Xcode {
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(
......
......@@ -77,14 +77,6 @@ void main() {
'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 @@ void main() {
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
xattrCommand,
armCheckCommand,
setUpMockXcodeBuildHandler(),
setUpMockXcodeBuildHandler(showBuildSettings: true),
]),
......@@ -234,7 +225,6 @@ void main() {
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
xattrCommand,
armCheckCommand,
setUpMockXcodeBuildHandler(verbose: true),
setUpMockXcodeBuildHandler(verbose: true, showBuildSettings: true),
]),
......@@ -263,7 +253,6 @@ void main() {
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 @@ void main() {
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
xattrCommand,
armCheckCommand,
setUpMockXcodeBuildHandler(),
setUpMockXcodeBuildHandler(showBuildSettings: true),
exportArchiveCommand,
......
......@@ -478,13 +478,6 @@ void main() {
'--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 @@ void main() {
'--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 @@ void main() {
'--lazy-async-stacks',
'$build/app.dill',
]),
const FakeCommand(
command: <String>[
'sysctl',
'hw.optional.arm64',
],
exitCode: 1,
),
FakeCommand(command: <String>[
'xcrun',
'cc',
......
......@@ -71,14 +71,6 @@ void main() {
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',
......
......@@ -51,7 +51,9 @@ void main() {
// 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 @@ void main() {
);
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 @@ void main() {
});
});
const FakeCommand kARMCheckCommand = FakeCommand(
command: <String>[
'sysctl',
'hw.optional.arm64',
],
exitCode: 1,
);
FakeProcessManager fakeProcessManager;
XcodeProjectInterpreter xcodeProjectInterpreter;
FakePlatform platform;
......@@ -102,43 +115,55 @@ void main() {
});
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 @@ void main() {
});
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 @@ void main() {
});
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 @@ void main() {
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 @@ void main() {
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 @@ void main() {
'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 @@ void main() {
'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 @@ void main() {
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 @@ void main() {
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,
......
......@@ -39,14 +39,16 @@ void main() {
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 @@ void main() {
});
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 @@ void main() {
setUp(() {
mockXcodeProjectInterpreter = MockXcodeProjectInterpreter();
when(mockXcodeProjectInterpreter.xcrunCommand()).thenReturn(<String>['xcrun']);
platform = FakePlatform(operatingSystem: 'macos');
xcode = Xcode(
logger: logger,
......@@ -252,25 +257,6 @@ void main() {
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'],
......@@ -287,13 +273,6 @@ void main() {
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,
......@@ -309,13 +288,6 @@ void main() {
testWithoutContext('eulaSigned is true when clang output indicates EULA has been accepted', () {
fakeProcessManager.addCommands(
const <FakeCommand>[
FakeCommand(
command: <String>[
'sysctl',
'hw.optional.arm64',
],
exitCode: 1,
),
FakeCommand(
command: <String>['xcrun', 'clang'],
exitCode: 1,
......@@ -334,18 +306,6 @@ void main() {
});
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 {
......
......@@ -414,6 +414,9 @@ class FakeXcodeProjectInterpreter implements XcodeProjectInterpreter {
BufferLogger.test(),
);
}
@override
List<String> xcrunCommand() => <String>['xcrun'];
}
class MockFlutterVersion extends Mock implements FlutterVersion {
......
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