Repository navigation
[stable] [flutter_tools] Handle missing Xcode gracefully in getInfo and buildMacOS - #191902
Conversation
…acOS (flutter#191180) Fixes flutter#191176 In Flutter 3.47.0 telemetry, an unhandled `ProcessException` when invoking `xcodebuild` emerged as a top crash signature. When running `flutter build macos` on a machine where Xcode is not installed, incomplete, or misconfigured, `flutter_tools` crashes with an unhandled `ProcessException` instead of providing a graceful `ToolExit` error message. 1. `buildMacOS` in `packages/flutter_tools/lib/src/macos/build_macos.dart` lacked pre-flight toolchain validation (`globals.xcodeProjectInterpreter?.isInstalled != true`) before querying Xcode project information. 2. In `XcodeProjectInterpreter.getInfo` (`packages/flutter_tools/lib/src/ios/xcodeproj.dart`), `xcodebuild -list` is executed with `throwOnError: true` while only allowing exit codes 66 and 74. When `xcrun` returns exit code 72 (unable to find utility "xcodebuild"), `_processUtils.run` throws an uncaught `ProcessException`. 3. `buildMacOS` improperly used non-null assertions on `projectInfo!` when resolving build schemes. - Added pre-flight Xcode toolchain check in `buildMacOS` to exit early with `globals.userMessages.xcodeMissing`. - Wrapped `XcodeProjectInterpreter.getInfo` in a `try ... on ProcessException` block to convert unexpected process failures to user-friendly `ToolExit` messages. - Added safe null checks on `projectInfo` in `buildMacOS`.
|
This pull request was opened from and to a release candidate branch. This should only be done as part of the official Flutter release process. If you are attempting to make a regular contribution to the Flutter project, please close this PR and follow the instructions at Tree Hygiene for detailed instructions on contributing to Flutter. Reviewers: Use caution before merging pull requests to release branches. Ensure the proper procedure has been followed. |
There was a problem hiding this comment.
Code Review
This pull request improves error handling when Xcode is missing or when retrieving Xcode project information fails. It adds an early check for Xcode installation during macOS builds, wraps the xcodebuild -list process call in a try-catch block to handle ProcessException, and updates tests accordingly. The review feedback suggests that the null check on projectInfo in build_macos.dart is redundant due to the early check and recommends simplifying it using null assertions.
| if (projectInfo == null) { | ||
| throwToolExit('Unable to get Xcode project information.'); | ||
| } | ||
| final String? scheme = projectInfo.schemeFor(buildInfo); | ||
| if (scheme == null) { | ||
| projectInfo!.reportFlavorNotFoundAndExit(); | ||
| projectInfo.reportFlavorNotFoundAndExit(); | ||
| } | ||
| final String? configuration = projectInfo?.buildConfigurationFor(buildInfo, scheme); | ||
| final String? configuration = projectInfo.buildConfigurationFor(buildInfo, scheme); |
There was a problem hiding this comment.
Since globals.xcodeProjectInterpreter is guaranteed to be non-null and installed due to the early exit check at the beginning of buildMacOS (line 89), projectInfo will never be null here. The if (projectInfo == null) check is dead code.
We can safely remove this check and instead use the null assertion operator projectInfo! on the first access. Dart's flow analysis will automatically promote projectInfo to a non-nullable type for all subsequent lines, keeping the code clean and avoiding unreachable error handling.
final String? scheme = projectInfo!.schemeFor(buildInfo);
if (scheme == null) {
projectInfo.reportFlavorNotFoundAndExit();
}
final String? configuration = projectInfo.buildConfigurationFor(buildInfo, scheme);References
- Optimize for readability: Code is read more often than it is written. (link)
justinmc
left a comment
There was a problem hiding this comment.
LGTM 👍 . I re-ran some failed checks.
115c53d
into
flutter:flutter-3.47-candidate.0
This pull request is created by automatic cherry pick workflow
Please fill in the form below, and a flutter domain expert will evaluate this cherry pick request.
Issue Link:
#191176
Impact Description:
When running
flutter build macosorflutter build ioson systems where Xcode is uninstalled, incomplete (e.g. Command Line Tools only), or misconfigured,XcodeProjectInterpreter.getInfoinvokesxcrun xcodebuild -listwhich exits with code 72 (unable to find utility "xcodebuild"). Because code 72 was not in the allowed exit codes,flutter_toolscrashes with an unhandledProcessException. In Flutter 3.47.1 telemetry, this was a top crash with 320 crashes (15.2% share of top 10 crashes). This impacts development workflows on macOS.Conflict Resolution Note: Resolved a minor merge conflict in
packages/flutter_tools/lib/src/macos/build_macos.dartby ordering the Xcode installation pre-flight check ahead of workspace validation.Changelog Description:
[flutter/191176] When building for macOS or iOS on machines with missing or incomplete Xcode installations, flutter_tools displays an actionable error message instead of crashing with an unhandled ProcessException.
Workaround:
Install Xcode or configure the active developer directory via:
sudo xcode-select --switch /Applications/Xcode.app/Contents/DeveloperRisk:
Test Coverage:
Validation Steps:
xcode-selectto Command Line Tools:sudo xcode-select -s /Library/Developer/CommandLineTools.flutter build macosin a Flutter project.flutter_toolsdisplays a cleanToolExitinstructing the user to install or configure Xcode, rather than crashing with an unhandledProcessExceptionand stack trace.dart test test/general.shard/ios/xcodeproj_test.dartanddart test test/commands.shard/hermetic/build_macos_test.dart.