ios_workflow.dart 4.3 KB
Newer Older
1 2 3 4
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'dart:async';
6

7
import '../base/io.dart';
8
import '../base/os.dart';
9
import '../base/platform.dart';
10 11
import '../base/process.dart';
import '../doctor.dart';
12
import 'mac.dart';
13

14 15 16 17
XCode get xcode => XCode.instance;

class IOSWorkflow extends DoctorValidator implements Workflow {
  IOSWorkflow() : super('iOS toolchain - develop for iOS devices');
18

19
  @override
20
  bool get appliesToHostPlatform => platform.isMacOS;
21 22

  // We need xcode (+simctl) to list simulator devices, and idevice_id to list real devices.
23
  @override
24
  bool get canListDevices => xcode.isInstalledAndMeetsVersionCheck;
25 26 27

  // We need xcode to launch simulator devices, and ideviceinstaller and ios-deploy
  // for real devices.
28
  @override
29 30 31
  bool get canLaunchDevices => xcode.isInstalledAndMeetsVersionCheck;

  bool get hasIDeviceId => exitsHappy(<String>['idevice_id', '-h']);
32

33
  @override
34
  Future<ValidationResult> validate() async {
35
    List<ValidationMessage> messages = <ValidationMessage>[];
36 37
    ValidationType xcodeStatus = ValidationType.missing;
    ValidationType brewStatus = ValidationType.missing;
38 39 40
    String xcodeVersionInfo;

    if (xcode.isInstalled) {
41
      xcodeStatus = ValidationType.installed;
42

43 44
      messages.add(new ValidationMessage('XCode at ${xcode.xcodeSelectPath}'));

45 46 47 48 49 50
      xcodeVersionInfo = xcode.xcodeVersionText;
      if (xcodeVersionInfo.contains(','))
        xcodeVersionInfo = xcodeVersionInfo.substring(0, xcodeVersionInfo.indexOf(','));
      messages.add(new ValidationMessage(xcode.xcodeVersionText));

      if (!xcode.isInstalledAndMeetsVersionCheck) {
51
        xcodeStatus = ValidationType.partial;
52 53 54 55 56 57 58
        messages.add(new ValidationMessage.error(
          'Flutter requires a minimum XCode version of $kXcodeRequiredVersionMajor.$kXcodeRequiredVersionMinor.0.\n'
          'Download the latest version or update via the Mac App Store.'
        ));
      }

      if (!xcode.eulaSigned) {
59
        xcodeStatus = ValidationType.partial;
60 61 62 63 64
        messages.add(new ValidationMessage.error(
          'XCode end user license agreement not signed; open XCode or run the command \'sudo xcodebuild -license\'.'
        ));
      }
    } else {
65
      xcodeStatus = ValidationType.missing;
66 67 68 69 70 71 72
      messages.add(new ValidationMessage.error(
        'XCode not installed; this is necessary for iOS development.\n'
        'Download at https://developer.apple.com/xcode/download/.'
      ));
    }

    // brew installed
73
    if (os.which('brew') != null) {
74
      brewStatus = ValidationType.installed;
75 76

      if (!exitsHappy(<String>['ideviceinstaller', '-h'])) {
77
        brewStatus = ValidationType.partial;
78 79 80 81 82 83 84
        messages.add(new ValidationMessage.error(
          'ideviceinstaller not available; this is used to discover connected iOS devices.\n'
          'Install via \'brew install ideviceinstaller\'.'
        ));
      }

      if (!hasIDeviceId) {
85
        brewStatus = ValidationType.partial;
86 87 88 89
        messages.add(new ValidationMessage.error(
          'ios-deploy not available; this is used to deploy to connected iOS devices.\n'
          'Install via \'brew install ios-deploy\'.'
        ));
90 91 92 93 94
      } else {
        // Check for compatibility between libimobiledevice and Xcode.
        // TODO(cbracken) remove this check once libimobiledevice > 1.2.0 is released.
        ProcessResult result = (await runAsync(<String>['idevice_id', '-l'])).processResult;
        if (result.exitCode == 0 && result.stdout.isNotEmpty && !exitsHappy(<String>['ideviceName'])) {
95
          brewStatus = ValidationType.partial;
96 97 98 99 100 101
          messages.add(new ValidationMessage.error(
            'libimobiledevice is incompatible with the installed XCode version. To update, run:\n'
            'brew uninstall libimobiledevice\n'
            'brew install --HEAD libimobiledevice'
          ));
        }
102 103
      }
    } else {
104
      brewStatus = ValidationType.missing;
105 106 107 108 109 110 111
      messages.add(new ValidationMessage.error(
        'Brew not installed; use this to install tools for iOS device development.\n'
        'Download brew at http://brew.sh/.'
      ));
    }

    return new ValidationResult(
112
      xcodeStatus == brewStatus ? xcodeStatus : ValidationType.partial,
113 114
      messages,
      statusInfo: xcodeVersionInfo
115
    );
116 117
  }
}