diff --git a/packages/flutter_tools/lib/src/android/android_workflow.dart b/packages/flutter_tools/lib/src/android/android_workflow.dart index e2a65e72946..a9ea8b22a65 100644 --- a/packages/flutter_tools/lib/src/android/android_workflow.dart +++ b/packages/flutter_tools/lib/src/android/android_workflow.dart @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:io'; + +import '../base/os.dart'; import '../doctor.dart'; import '../globals.dart'; import 'android_sdk.dart'; @@ -37,14 +40,47 @@ class AndroidWorkflow extends DoctorValidator implements Workflow { if (androidSdk.latestVersion != null) { sdkVersionText = 'Android SDK ${androidSdk.latestVersion.buildToolsVersionName}'; - messages.add(new ValidationMessage('Platform ${androidSdk.latestVersion.platformVersionName}')); - messages.add(new ValidationMessage('Build-tools ${androidSdk.latestVersion.buildToolsVersionName}')); + messages.add(new ValidationMessage( + 'Platform ${androidSdk.latestVersion.platformVersionName}, ' + 'build-tools ${androidSdk.latestVersion.buildToolsVersionName}' + )); } List validationResult = androidSdk.validateSdkWellFormed(); if (validationResult.isEmpty) { - type = ValidationType.installed; + const String _kJdkDownload = 'https://www.oracle.com/technetwork/java/javase/downloads/'; + + String javaVersion; + + try { + printTrace('java -version'); + + ProcessResult result = Process.runSync('java', ['-version']); + if (result.exitCode == 0) { + javaVersion = result.stderr; + List versionLines = javaVersion.split('\n'); + javaVersion = versionLines.length >= 2 ? versionLines[1] : versionLines[0]; + } + } catch (error) { + } + + if (javaVersion != null) { + type = ValidationType.installed; + + messages.add(new ValidationMessage(javaVersion)); + + if (os.which('jarsigner') == null) { + messages.add(new ValidationMessage.error( + 'The jarsigner utility was not found; this is used to build Android APKs. You may need to install\n' + 'or re-install the Java JDK: $_kJdkDownload.' + )); + } + } else { + messages.add(new ValidationMessage.error( + 'No Java SDK found; you can download Java from $_kJdkDownload.' + )); + } } else { messages.addAll(validationResult.map((String message) { return new ValidationMessage.error(message); diff --git a/packages/flutter_tools/lib/src/doctor.dart b/packages/flutter_tools/lib/src/doctor.dart index 4748b769325..3d82ab5b066 100644 --- a/packages/flutter_tools/lib/src/doctor.dart +++ b/packages/flutter_tools/lib/src/doctor.dart @@ -189,12 +189,15 @@ class _FlutterValidator extends DoctorValidator { FlutterVersion version = FlutterVersion.getVersion(); - messages.add(new ValidationMessage('Flutter root at ${version.flutterRoot}')); - messages.add(new ValidationMessage('Framework revision ${version.frameworkRevisionShort} ' - '(${version.frameworkAge}, channel ${version.channel})')); - messages.add(new ValidationMessage('Engine revision ${version.engineRevisionShort}')); + messages.add(new ValidationMessage('Flutter at ${version.flutterRoot}')); + messages.add(new ValidationMessage( + 'Framework revision ${version.frameworkRevisionShort} ' + '(${version.frameworkAge}), ' + 'engine revision ${version.engineRevisionShort}' + )); - return new ValidationResult(ValidationType.installed, messages, statusInfo: osName()); + return new ValidationResult(ValidationType.installed, messages, + statusInfo: 'on ${osName()}, channel ${version.channel}'); } } @@ -238,7 +241,7 @@ class _AtomValidator extends DoctorValidator { File packageFile = new File(path.join(flutterPluginPath, 'package.json')); dynamic packageInfo = JSON.decode(packageFile.readAsStringSync()); String version = packageInfo['version']; - messages.add(new ValidationMessage('Atom installed; flutter plugin version $version')); + messages.add(new ValidationMessage('Atom installed; Flutter plugin version $version')); } catch (error) { printTrace('Unable to read flutter plugin version: $error'); } diff --git a/packages/flutter_tools/lib/src/ios/ios_workflow.dart b/packages/flutter_tools/lib/src/ios/ios_workflow.dart index 8df90c71e5c..337026a0dfc 100644 --- a/packages/flutter_tools/lib/src/ios/ios_workflow.dart +++ b/packages/flutter_tools/lib/src/ios/ios_workflow.dart @@ -4,6 +4,7 @@ import 'dart:io'; +import '../base/os.dart'; import '../base/process.dart'; import '../doctor.dart'; import 'mac.dart'; @@ -36,10 +37,11 @@ class IOSWorkflow extends DoctorValidator implements Workflow { if (xcode.isInstalled) { installCount++; + messages.add(new ValidationMessage('XCode at ${xcode.xcodeSelectPath}')); + xcodeVersionInfo = xcode.xcodeVersionText; if (xcodeVersionInfo.contains(',')) xcodeVersionInfo = xcodeVersionInfo.substring(0, xcodeVersionInfo.indexOf(',')); - messages.add(new ValidationMessage(xcode.xcodeVersionText)); if (!xcode.isInstalledAndMeetsVersionCheck) { @@ -62,18 +64,14 @@ class IOSWorkflow extends DoctorValidator implements Workflow { } // brew installed - if (exitsHappy(['brew', '-v'])) { + if (os.which('brew') != null) { installCount++; - List installed = []; - if (!exitsHappy(['ideviceinstaller', '-h'])) { messages.add(new ValidationMessage.error( 'ideviceinstaller not available; this is used to discover connected iOS devices.\n' 'Install via \'brew install ideviceinstaller\'.' )); - } else { - installed.add('ideviceinstaller'); } if (!hasIDeviceId) { @@ -81,12 +79,7 @@ class IOSWorkflow extends DoctorValidator implements Workflow { 'ios-deploy not available; this is used to deploy to connected iOS devices.\n' 'Install via \'brew install ios-deploy\'.' )); - } else { - installed.add('ios-deploy'); } - - if (installed.isNotEmpty) - messages.add(new ValidationMessage(installed.join(', ') + ' installed')); } else { messages.add(new ValidationMessage.error( 'Brew not installed; use this to install tools for iOS device development.\n' diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart index 388cc12cecf..fd1db37d45e 100644 --- a/packages/flutter_tools/lib/src/ios/mac.dart +++ b/packages/flutter_tools/lib/src/ios/mac.dart @@ -22,45 +22,49 @@ const int kXcodeRequiredVersionMajor = 7; const int kXcodeRequiredVersionMinor = 0; class XCode { + XCode() { + _eulaSigned = false; + + try { + _xcodeSelectPath = runSync(['xcode-select', '--print-path']); + _isInstalled = true; + + _xcodeVersionText = runSync(['xcodebuild', '-version']).replaceAll('\n', ', '); + + try { + printTrace('xcrun clang'); + + ProcessResult result = Process.runSync('/usr/bin/xcrun', ['clang']); + if (result.stdout != null && result.stdout.contains('license')) + _eulaSigned = false; + else if (result.stderr != null && result.stderr.contains('license')) + _eulaSigned = false; + else + _eulaSigned = true; + } catch (error) { + } + } catch (error) { + _isInstalled = false; + } + } + /// Returns [XCode] active in the current app context. static XCode get instance => context[XCode] ?? (context[XCode] = new XCode()); bool get isInstalledAndMeetsVersionCheck => isInstalled && xcodeVersionSatisfactory; + String _xcodeSelectPath; + String get xcodeSelectPath => _xcodeSelectPath; + bool _isInstalled; - bool get isInstalled { - if (_isInstalled != null) { - return _isInstalled; - } - - _isInstalled = exitsHappy(['xcode-select', '--print-path']); - return _isInstalled; - } + bool get isInstalled => _isInstalled; + bool _eulaSigned; /// Has the EULA been signed? - bool get eulaSigned { - if (!isInstalled) - return false; - - try { - ProcessResult result = Process.runSync('/usr/bin/xcrun', ['clang']); - if (result.stdout != null && result.stdout.contains('license')) - return false; - if (result.stderr != null && result.stderr.contains('license')) - return false; - return true; - } catch (error) { - return false; - } - } + bool get eulaSigned => _eulaSigned; String _xcodeVersionText; - - String get xcodeVersionText { - if (_xcodeVersionText == null) - _xcodeVersionText = runSync(['xcodebuild', '-version']).replaceAll('\n', ', '); - return _xcodeVersionText; - } + String get xcodeVersionText => _xcodeVersionText; bool get xcodeVersionSatisfactory { RegExp regex = new RegExp(r'Xcode ([0-9.]+)'); diff --git a/packages/flutter_tools/lib/src/runner/version.dart b/packages/flutter_tools/lib/src/runner/version.dart index e5dd189124a..eb0a53ba692 100644 --- a/packages/flutter_tools/lib/src/runner/version.dart +++ b/packages/flutter_tools/lib/src/runner/version.dart @@ -45,11 +45,10 @@ class FlutterVersion { @override String toString() { - String from = repositoryUrl == null ? 'Flutter from unknown source' : 'Flutter from $repositoryUrl (on channel $channel)'; - String flutterText = 'Framework: $frameworkRevisionShort ($frameworkAge)'; - String engineText = 'Engine: $engineRevisionShort'; + String from = 'Flutter on channel $channel (from ${repositoryUrl == null ? 'unknown source' : repositoryUrl})'; + String flutterText = 'Framework revision $frameworkRevisionShort ($frameworkAge); engine revision $engineRevisionShort'; - return '$from\n\n$flutterText\n$engineText'; + return '$from\n$flutterText'; } static FlutterVersion getVersion([String flutterRoot]) {