Add doctor command support (#11)
This commit is contained in:
+159
-53
@@ -7,16 +7,15 @@
|
|||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter_tools/src/android/android_workflow.dart';
|
|
||||||
import 'package:flutter_tools/src/base/context.dart';
|
import 'package:flutter_tools/src/base/context.dart';
|
||||||
import 'package:flutter_tools/src/base/os.dart';
|
import 'package:flutter_tools/src/base/os.dart';
|
||||||
|
import 'package:flutter_tools/src/base/user_messages.dart';
|
||||||
|
import 'package:flutter_tools/src/base/version.dart';
|
||||||
import 'package:flutter_tools/src/doctor.dart';
|
import 'package:flutter_tools/src/doctor.dart';
|
||||||
import 'package:flutter_tools/src/doctor_validator.dart';
|
import 'package:flutter_tools/src/doctor_validator.dart';
|
||||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
|
||||||
import 'package:flutter_tools/src/version.dart';
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
import 'executable.dart';
|
import 'package:process/process.dart';
|
||||||
|
|
||||||
ELinuxWorkflow get eLinuxWorkflow => context.get<ELinuxWorkflow>();
|
ELinuxWorkflow get eLinuxWorkflow => context.get<ELinuxWorkflow>();
|
||||||
ELinuxValidator get eLinuxValidator => context.get<ELinuxValidator>();
|
ELinuxValidator get eLinuxValidator => context.get<ELinuxValidator>();
|
||||||
@@ -41,32 +40,170 @@ class ELinuxDoctorValidatorsProvider extends DoctorValidatorsProvider {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A validator that checks for eLinux SDK installation.
|
/// See: [_VersionInfo] in `linux_doctor.dart`
|
||||||
class ELinuxValidator extends DoctorValidator {
|
class _VersionInfo {
|
||||||
ELinuxValidator() : super('eLinux toolchain - develop for eLinux devices');
|
_VersionInfo(this.description) {
|
||||||
|
final String versionString = RegExp(r'[0-9]+\.[0-9]+(?:\.[0-9]+)?')
|
||||||
bool _validatePackages(List<ValidationMessage> messages) {
|
.firstMatch(description)
|
||||||
return true;
|
?.group(0);
|
||||||
|
number = Version.parse(versionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See: [AndroidValidator.validate] in `android_workflow.dart`
|
String description;
|
||||||
|
Version number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See: [LinuxDoctorValidator] in `linux_doctor.dart`
|
||||||
|
class ELinuxValidator extends DoctorValidator {
|
||||||
|
ELinuxValidator({
|
||||||
|
@required ProcessManager processManager,
|
||||||
|
@required UserMessages userMessages,
|
||||||
|
}) : _processManager = processManager,
|
||||||
|
_userMessages = userMessages,
|
||||||
|
super('eLinux toolchain - develop for embedded Linux devices');
|
||||||
|
|
||||||
|
final ProcessManager _processManager;
|
||||||
|
final UserMessages _userMessages;
|
||||||
|
|
||||||
|
static const String kClangBinary = 'clang++';
|
||||||
|
static const String kCmakeBinary = 'cmake';
|
||||||
|
static const String kPkgConfigBinary = 'pkg-config';
|
||||||
|
|
||||||
|
final Map<String, Version> _requiredBinaryVersions = <String, Version>{
|
||||||
|
kClangBinary: Version(3, 4, 0),
|
||||||
|
kCmakeBinary: Version(3, 10, 0),
|
||||||
|
kPkgConfigBinary: Version(0, 29, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
final List<String> _requiredCommonLibraries = <String>[
|
||||||
|
'glesv2',
|
||||||
|
'egl',
|
||||||
|
];
|
||||||
|
static const String kRequredCommonLibrariesErrorMessage =
|
||||||
|
'OpenGL ES/EGL libraries are required for Embedded Linux development. '
|
||||||
|
'They are likely available from your distribution (e.g.: apt install libegl1-mesa libgles2-mesa)';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<ValidationResult> validate() async {
|
Future<ValidationResult> validate() async {
|
||||||
|
ValidationType validationType = ValidationType.installed;
|
||||||
final List<ValidationMessage> messages = <ValidationMessage>[];
|
final List<ValidationMessage> messages = <ValidationMessage>[];
|
||||||
|
|
||||||
final FlutterVersion version = _FlutterELinuxVersion();
|
final Map<String, _VersionInfo> installedVersions = <String, _VersionInfo>{
|
||||||
messages.add(ValidationMessage(globals.userMessages.flutterRevision(
|
// Sort the check to make the call order predictable for unit tests.
|
||||||
version.frameworkRevisionShort,
|
for (String binary in _requiredBinaryVersions.keys.toList()..sort())
|
||||||
version.frameworkAge,
|
binary: await _getBinaryVersion(binary)
|
||||||
version.frameworkCommitDate,
|
};
|
||||||
)));
|
|
||||||
messages.add(ValidationMessage(
|
|
||||||
globals.userMessages.engineRevision(version.engineRevisionShort)));
|
|
||||||
|
|
||||||
if (!_validatePackages(messages)) {
|
// Determine overall validation level.
|
||||||
return ValidationResult(ValidationType.partial, messages);
|
if (installedVersions.values
|
||||||
|
.any((_VersionInfo versionInfo) => versionInfo?.number == null)) {
|
||||||
|
validationType = ValidationType.missing;
|
||||||
|
} else if (installedVersions.keys.any((String binary) =>
|
||||||
|
installedVersions[binary].number < _requiredBinaryVersions[binary])) {
|
||||||
|
validationType = ValidationType.partial;
|
||||||
}
|
}
|
||||||
return ValidationResult(ValidationType.installed, messages);
|
|
||||||
|
// Message for Clang.
|
||||||
|
{
|
||||||
|
final _VersionInfo version = installedVersions[kClangBinary];
|
||||||
|
if (version == null || version.number == null) {
|
||||||
|
messages.add(ValidationMessage.error(_userMessages.clangMissing));
|
||||||
|
} else {
|
||||||
|
assert(_requiredBinaryVersions.containsKey(kClangBinary));
|
||||||
|
messages.add(ValidationMessage(version.description));
|
||||||
|
final Version requiredVersion = _requiredBinaryVersions[kClangBinary];
|
||||||
|
if (version.number < requiredVersion) {
|
||||||
|
messages.add(ValidationMessage.error(
|
||||||
|
_userMessages.clangTooOld(requiredVersion.toString())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Message for CMake.
|
||||||
|
{
|
||||||
|
final _VersionInfo version = installedVersions[kCmakeBinary];
|
||||||
|
if (version == null || version.number == null) {
|
||||||
|
messages.add(ValidationMessage.error(_userMessages.cmakeMissing));
|
||||||
|
} else {
|
||||||
|
assert(_requiredBinaryVersions.containsKey(kCmakeBinary));
|
||||||
|
messages.add(ValidationMessage(version.description));
|
||||||
|
final Version requiredVersion = _requiredBinaryVersions[kCmakeBinary];
|
||||||
|
if (version.number < requiredVersion) {
|
||||||
|
messages.add(ValidationMessage.error(
|
||||||
|
_userMessages.cmakeTooOld(requiredVersion.toString())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Message for pkg-config.
|
||||||
|
{
|
||||||
|
final _VersionInfo version = installedVersions[kPkgConfigBinary];
|
||||||
|
if (version == null || version.number == null) {
|
||||||
|
messages.add(ValidationMessage.error(_userMessages.pkgConfigMissing));
|
||||||
|
} else {
|
||||||
|
assert(_requiredBinaryVersions.containsKey(kPkgConfigBinary));
|
||||||
|
// The full version description is just the number, so add context.
|
||||||
|
messages.add(ValidationMessage(
|
||||||
|
_userMessages.pkgConfigVersion(version.description)));
|
||||||
|
final Version requiredVersion =
|
||||||
|
_requiredBinaryVersions[kPkgConfigBinary];
|
||||||
|
if (version.number < requiredVersion) {
|
||||||
|
messages.add(ValidationMessage.error(
|
||||||
|
_userMessages.pkgConfigTooOld(requiredVersion.toString())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Messages for libraries.
|
||||||
|
{
|
||||||
|
bool libraryMissing = false;
|
||||||
|
for (final String library in _requiredCommonLibraries) {
|
||||||
|
if (!await _libraryIsPresent(library)) {
|
||||||
|
libraryMissing = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (libraryMissing) {
|
||||||
|
validationType = ValidationType.missing;
|
||||||
|
messages.add(
|
||||||
|
const ValidationMessage.error(kRequredCommonLibrariesErrorMessage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ValidationResult(validationType, messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See: [_getBinaryVersion] in `linux_doctor.dart`
|
||||||
|
Future<_VersionInfo> _getBinaryVersion(String binary) async {
|
||||||
|
ProcessResult result;
|
||||||
|
try {
|
||||||
|
result = await _processManager.run(<String>[
|
||||||
|
binary,
|
||||||
|
'--version',
|
||||||
|
]);
|
||||||
|
} on ArgumentError {
|
||||||
|
// ignore error.
|
||||||
|
}
|
||||||
|
if (result == null || result.exitCode != 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final String firstLine = (result.stdout as String).split('\n').first.trim();
|
||||||
|
return _VersionInfo(firstLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See: [_libraryIsPresent] in `linux_doctor.dart`
|
||||||
|
Future<bool> _libraryIsPresent(String library) async {
|
||||||
|
ProcessResult result;
|
||||||
|
try {
|
||||||
|
result = await _processManager.run(<String>[
|
||||||
|
'pkg-config',
|
||||||
|
'--exists',
|
||||||
|
library,
|
||||||
|
]);
|
||||||
|
} on ArgumentError {
|
||||||
|
// ignore error.
|
||||||
|
}
|
||||||
|
return (result?.exitCode ?? 1) == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,34 +230,3 @@ class ELinuxWorkflow extends Workflow {
|
|||||||
@override
|
@override
|
||||||
bool get canListEmulators => false;
|
bool get canListEmulators => false;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _FlutterELinuxVersion extends FlutterVersion {
|
|
||||||
_FlutterELinuxVersion() : super(workingDirectory: rootPath);
|
|
||||||
|
|
||||||
/// See: [Cache.getVersionFor] in `cache.dart`
|
|
||||||
String _getVersionFor(String artifactName) {
|
|
||||||
final File versionFile = globals.fs
|
|
||||||
.directory(rootPath)
|
|
||||||
.childDirectory('bin')
|
|
||||||
.childDirectory('internal')
|
|
||||||
.childFile('$artifactName.version');
|
|
||||||
return versionFile.existsSync()
|
|
||||||
? versionFile.readAsStringSync().trim()
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get engineRevision => _getVersionFor('engine');
|
|
||||||
|
|
||||||
/// See: [_runGit] in `version.dart`
|
|
||||||
String _runGit(String command) => globals.processUtils
|
|
||||||
.runSync(command.split(' '), workingDirectory: rootPath)
|
|
||||||
.stdout
|
|
||||||
.trim();
|
|
||||||
|
|
||||||
/// This should be overriden because [FlutterVersion._latestGitCommitDate]
|
|
||||||
/// runs the git log command in the `Cache.flutterRoot` directory.
|
|
||||||
@override
|
|
||||||
String get frameworkCommitDate => _runGit(
|
|
||||||
'git -c log.showSignature=false log -n 1 --pretty=format:%ad --date=iso');
|
|
||||||
}
|
|
||||||
|
|||||||
+4
-1
@@ -129,7 +129,10 @@ Future<void> main(List<String> args) async {
|
|||||||
ELinuxWorkflow: () => ELinuxWorkflow(
|
ELinuxWorkflow: () => ELinuxWorkflow(
|
||||||
operatingSystemUtils: globals.os,
|
operatingSystemUtils: globals.os,
|
||||||
),
|
),
|
||||||
ELinuxValidator: () => ELinuxValidator(),
|
ELinuxValidator: () => ELinuxValidator(
|
||||||
|
processManager: globals.processManager,
|
||||||
|
userMessages: globals.userMessages,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user