Make Flutter tooling work on Android without Xcode being installed (#15161)
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart index 9a50d30..e35d6aa 100644 --- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart +++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -7,7 +7,10 @@ import '../artifacts.dart'; import '../base/context.dart'; import '../base/file_system.dart'; +import '../base/io.dart'; +import '../base/platform.dart'; import '../base/process.dart'; +import '../base/process_manager.dart'; import '../base/utils.dart'; import '../build_info.dart'; import '../cache.dart'; @@ -84,16 +87,58 @@ XcodeProjectInterpreter get xcodeProjectInterpreter => context.putIfAbsent( XcodeProjectInterpreter, - () => const XcodeProjectInterpreter(), + () => new XcodeProjectInterpreter(), ); -/// Interpreter of Xcode projects settings. +/// Interpreter of Xcode projects. class XcodeProjectInterpreter { static const String _executable = '/usr/bin/xcodebuild'; + static final RegExp _versionRegex = new RegExp(r'Xcode ([0-9.]+)'); - const XcodeProjectInterpreter(); + void _updateVersion() { + if (!platform.isMacOS || !fs.file(_executable).existsSync()) { + return; + } + try { + final ProcessResult result = processManager.runSync(<String>[_executable, '-version']); + if (result.exitCode != 0) { + return; + } + _versionText = result.stdout.trim().replaceAll('\n', ', '); + final Match match = _versionRegex.firstMatch(versionText); + if (match == null) + return; + final String version = match.group(1); + final List<String> components = version.split('.'); + _majorVersion = int.parse(components[0]); + _minorVersion = components.length == 1 ? 0 : int.parse(components[1]); + } on ProcessException { + // Ignore: leave values null. + } + } - bool get canInterpretXcodeProjects => fs.isFileSync(_executable); + bool get isInstalled => majorVersion != null; + + String _versionText; + String get versionText { + if (_versionText == null) + _updateVersion(); + return _versionText; + } + + int _majorVersion; + int get majorVersion { + if (_majorVersion == null) + _updateVersion(); + return _majorVersion; + } + + int _minorVersion; + int get minorVersion { + if (_minorVersion == null) + _updateVersion(); + return _minorVersion; + } Map<String, String> getBuildSettings(String projectPath, String target) { final String out = runCheckedSync(<String>[