mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This auto-formats all *.dart files in the repository outside of the `engine` subdirectory and enforces that these files stay formatted with a presubmit check. **Reviewers:** Please carefully review all the commits except for the one titled "formatted". The "formatted" commit was auto-generated by running `dev/tools/format.sh -a -f`. The other commits were hand-crafted to prepare the repo for the formatting change. I recommend reviewing the commits one-by-one via the "Commits" tab and avoiding Github's "Files changed" tab as it will likely slow down your browser because of the size of this PR. --------- Co-authored-by: Kate Lovett <katelovett@google.com> Co-authored-by: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com>
297 lines
9.4 KiB
Dart
297 lines
9.4 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:async';
|
|
|
|
import 'package:file/memory.dart';
|
|
import 'package:meta/meta.dart';
|
|
import 'package:process/process.dart';
|
|
|
|
import '../base/common.dart';
|
|
import '../base/file_system.dart';
|
|
import '../base/io.dart';
|
|
import '../base/logger.dart';
|
|
import '../base/platform.dart';
|
|
import '../base/process.dart';
|
|
import '../base/user_messages.dart';
|
|
import '../base/version.dart';
|
|
import '../build_info.dart';
|
|
import '../cache.dart';
|
|
import '../ios/xcodeproj.dart';
|
|
|
|
Version get xcodeRequiredVersion => Version(14, null, null);
|
|
|
|
/// Diverging this number from the minimum required version will provide a doctor
|
|
/// warning, not error, that users should upgrade Xcode.
|
|
Version get xcodeRecommendedVersion => Version(15, null, null);
|
|
|
|
/// SDK name passed to `xcrun --sdk`. Corresponds to undocumented Xcode
|
|
/// SUPPORTED_PLATFORMS values.
|
|
///
|
|
/// Usage: xcrun [options] <tool name> ... arguments ...
|
|
/// ...
|
|
/// --sdk <sdk name> find the tool for the given SDK name.
|
|
String getSDKNameForIOSEnvironmentType(EnvironmentType environmentType) {
|
|
return (environmentType == EnvironmentType.simulator) ? 'iphonesimulator' : 'iphoneos';
|
|
}
|
|
|
|
/// A utility class for interacting with Xcode command line tools.
|
|
class Xcode {
|
|
Xcode({
|
|
required Platform platform,
|
|
required ProcessManager processManager,
|
|
required Logger logger,
|
|
required FileSystem fileSystem,
|
|
required XcodeProjectInterpreter xcodeProjectInterpreter,
|
|
required UserMessages userMessages,
|
|
String? flutterRoot,
|
|
}) : _platform = platform,
|
|
_fileSystem = fileSystem,
|
|
_xcodeProjectInterpreter = xcodeProjectInterpreter,
|
|
_userMessage = userMessages,
|
|
_flutterRoot = flutterRoot,
|
|
_processUtils = ProcessUtils(logger: logger, processManager: processManager),
|
|
_logger = logger;
|
|
|
|
/// Create an [Xcode] for testing.
|
|
///
|
|
/// Defaults to a memory file system, fake platform,
|
|
/// buffer logger, and test [XcodeProjectInterpreter].
|
|
@visibleForTesting
|
|
factory Xcode.test({
|
|
required ProcessManager processManager,
|
|
XcodeProjectInterpreter? xcodeProjectInterpreter,
|
|
Platform? platform,
|
|
FileSystem? fileSystem,
|
|
String? flutterRoot,
|
|
Logger? logger,
|
|
}) {
|
|
platform ??= FakePlatform(operatingSystem: 'macos', environment: <String, String>{});
|
|
logger ??= BufferLogger.test();
|
|
return Xcode(
|
|
platform: platform,
|
|
processManager: processManager,
|
|
fileSystem: fileSystem ?? MemoryFileSystem.test(),
|
|
userMessages: UserMessages(),
|
|
flutterRoot: flutterRoot,
|
|
logger: logger,
|
|
xcodeProjectInterpreter:
|
|
xcodeProjectInterpreter ?? XcodeProjectInterpreter.test(processManager: processManager),
|
|
);
|
|
}
|
|
|
|
final Platform _platform;
|
|
final ProcessUtils _processUtils;
|
|
final FileSystem _fileSystem;
|
|
final XcodeProjectInterpreter _xcodeProjectInterpreter;
|
|
final UserMessages _userMessage;
|
|
final String? _flutterRoot;
|
|
final Logger _logger;
|
|
|
|
bool get isInstalledAndMeetsVersionCheck =>
|
|
_platform.isMacOS && isInstalled && isRequiredVersionSatisfactory;
|
|
|
|
String? _xcodeSelectPath;
|
|
String? get xcodeSelectPath {
|
|
if (_xcodeSelectPath == null) {
|
|
try {
|
|
_xcodeSelectPath =
|
|
_processUtils.runSync(<String>['/usr/bin/xcode-select', '--print-path']).stdout.trim();
|
|
} on ProcessException {
|
|
// Ignored, return null below.
|
|
} on ArgumentError {
|
|
// Ignored, return null below.
|
|
}
|
|
}
|
|
return _xcodeSelectPath;
|
|
}
|
|
|
|
String get xcodeAppPath {
|
|
// If the Xcode Select Path is /Applications/Xcode.app/Contents/Developer,
|
|
// the path to Xcode App is /Applications/Xcode.app
|
|
|
|
final String? pathToXcode = xcodeSelectPath;
|
|
if (pathToXcode == null || pathToXcode.isEmpty) {
|
|
throwToolExit(_userMessage.xcodeMissing);
|
|
}
|
|
final int index = pathToXcode.indexOf('.app');
|
|
if (index == -1) {
|
|
throwToolExit(_userMessage.xcodeMissing);
|
|
}
|
|
return pathToXcode.substring(0, index + 4);
|
|
}
|
|
|
|
/// Path to script to automate debugging through Xcode. Used in xcode_debug.dart.
|
|
/// Located in this file to make it easily overrideable in google3.
|
|
String get xcodeAutomationScriptPath {
|
|
final String flutterRoot = _flutterRoot ?? Cache.flutterRoot!;
|
|
final String flutterToolsAbsolutePath = _fileSystem.path.join(
|
|
flutterRoot,
|
|
'packages',
|
|
'flutter_tools',
|
|
);
|
|
|
|
final String filePath = '$flutterToolsAbsolutePath/bin/xcode_debug.js';
|
|
if (!_fileSystem.file(filePath).existsSync()) {
|
|
throwToolExit('Unable to find Xcode automation script at $filePath');
|
|
}
|
|
return filePath;
|
|
}
|
|
|
|
bool get isInstalled => _xcodeProjectInterpreter.isInstalled;
|
|
|
|
Version? get currentVersion => _xcodeProjectInterpreter.version;
|
|
|
|
String? get buildVersion => _xcodeProjectInterpreter.build;
|
|
|
|
String? get versionText => _xcodeProjectInterpreter.versionText;
|
|
|
|
bool? _eulaSigned;
|
|
|
|
/// Has the EULA been signed?
|
|
bool get eulaSigned {
|
|
if (_eulaSigned == null) {
|
|
try {
|
|
final RunResult result = _processUtils.runSync(<String>[...xcrunCommand(), 'clang']);
|
|
if (result.stdout.contains('license')) {
|
|
_eulaSigned = false;
|
|
} else if (result.stderr.contains('license')) {
|
|
_eulaSigned = false;
|
|
} else {
|
|
_eulaSigned = true;
|
|
}
|
|
} on ProcessException {
|
|
_eulaSigned = false;
|
|
}
|
|
}
|
|
return _eulaSigned ?? false;
|
|
}
|
|
|
|
bool? _isSimctlInstalled;
|
|
|
|
/// Verifies that simctl is installed by trying to run it.
|
|
bool get isSimctlInstalled {
|
|
if (_isSimctlInstalled == null) {
|
|
try {
|
|
// This command will error if additional components need to be installed in
|
|
// xcode 9.2 and above.
|
|
final RunResult result = _processUtils.runSync(<String>[
|
|
...xcrunCommand(),
|
|
'simctl',
|
|
'list',
|
|
'devices',
|
|
'booted',
|
|
]);
|
|
_isSimctlInstalled = result.exitCode == 0;
|
|
} on ProcessException {
|
|
_isSimctlInstalled = false;
|
|
}
|
|
}
|
|
return _isSimctlInstalled ?? false;
|
|
}
|
|
|
|
bool? _isDevicectlInstalled;
|
|
|
|
/// Verifies that `devicectl` is installed by checking Xcode version and trying
|
|
/// to run it. `devicectl` is made available in Xcode 15.
|
|
bool get isDevicectlInstalled {
|
|
if (_isDevicectlInstalled == null) {
|
|
try {
|
|
if (currentVersion == null || currentVersion!.major < 15) {
|
|
_isDevicectlInstalled = false;
|
|
return _isDevicectlInstalled!;
|
|
}
|
|
final RunResult result = _processUtils.runSync(<String>[
|
|
...xcrunCommand(),
|
|
'devicectl',
|
|
'--version',
|
|
]);
|
|
_isDevicectlInstalled = result.exitCode == 0;
|
|
} on ProcessException {
|
|
_isDevicectlInstalled = false;
|
|
}
|
|
}
|
|
return _isDevicectlInstalled ?? false;
|
|
}
|
|
|
|
bool get isRequiredVersionSatisfactory {
|
|
final Version? version = currentVersion;
|
|
if (version == null) {
|
|
return false;
|
|
}
|
|
return version >= xcodeRequiredVersion;
|
|
}
|
|
|
|
bool get isRecommendedVersionSatisfactory {
|
|
final Version? version = currentVersion;
|
|
if (version == null) {
|
|
return false;
|
|
}
|
|
return version >= xcodeRecommendedVersion;
|
|
}
|
|
|
|
/// See [XcodeProjectInterpreter.xcrunCommand].
|
|
List<String> xcrunCommand() => _xcodeProjectInterpreter.xcrunCommand();
|
|
|
|
Future<RunResult> cc(List<String> args) => _run('cc', args);
|
|
|
|
Future<RunResult> clang(List<String> args) => _run('clang', args);
|
|
|
|
Future<RunResult> dsymutil(List<String> args) => _run('dsymutil', args);
|
|
|
|
Future<RunResult> strip(List<String> args) => _run('strip', args);
|
|
|
|
Future<RunResult> _run(String command, List<String> args) {
|
|
return _processUtils.run(<String>[...xcrunCommand(), command, ...args], throwOnError: true);
|
|
}
|
|
|
|
Future<String> sdkLocation(EnvironmentType environmentType) async {
|
|
final RunResult runResult = await _processUtils.run(<String>[
|
|
...xcrunCommand(),
|
|
'--sdk',
|
|
getSDKNameForIOSEnvironmentType(environmentType),
|
|
'--show-sdk-path',
|
|
]);
|
|
if (runResult.exitCode != 0) {
|
|
throwToolExit('Could not find SDK location: ${runResult.stderr}');
|
|
}
|
|
return runResult.stdout.trim();
|
|
}
|
|
|
|
String? getSimulatorPath() {
|
|
final String? selectPath = xcodeSelectPath;
|
|
if (selectPath == null) {
|
|
return null;
|
|
}
|
|
final String appPath = _fileSystem.path.join(selectPath, 'Applications', 'Simulator.app');
|
|
return _fileSystem.directory(appPath).existsSync() ? appPath : null;
|
|
}
|
|
|
|
/// Gets the version number of the platform for the selected SDK.
|
|
Future<Version?> sdkPlatformVersion(EnvironmentType environmentType) async {
|
|
final RunResult runResult = await _processUtils.run(<String>[
|
|
...xcrunCommand(),
|
|
'--sdk',
|
|
getSDKNameForIOSEnvironmentType(environmentType),
|
|
'--show-sdk-platform-version',
|
|
]);
|
|
if (runResult.exitCode != 0) {
|
|
_logger.printError('Could not find SDK Platform Version: ${runResult.stderr}');
|
|
return null;
|
|
}
|
|
final String versionString = runResult.stdout.trim();
|
|
return Version.parse(versionString);
|
|
}
|
|
}
|
|
|
|
EnvironmentType? environmentTypeFromSdkroot(String sdkroot, FileSystem fileSystem) {
|
|
// iPhoneSimulator.sdk or iPhoneOS.sdk
|
|
final String sdkName = fileSystem.path.basename(sdkroot).toLowerCase();
|
|
if (sdkName.contains('iphone')) {
|
|
return sdkName.contains('simulator') ? EnvironmentType.simulator : EnvironmentType.physical;
|
|
}
|
|
assert(false);
|
|
return null;
|
|
}
|