Run more xcodebuild commands in native arm on Apple Silicon (#69837)
This commit is contained in:
parent
4eabee888c
commit
2f3cccc4f5
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user