• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'dart:async';
6
7import '../base/context.dart';
8import '../base/file_system.dart';
9import '../base/io.dart';
10import '../base/process.dart';
11import '../base/process_manager.dart';
12import '../ios/xcodeproj.dart';
13
14const int kXcodeRequiredVersionMajor = 9;
15const int kXcodeRequiredVersionMinor = 0;
16
17Xcode get xcode => context.get<Xcode>();
18
19class Xcode {
20  bool get isInstalledAndMeetsVersionCheck => isInstalled && isVersionSatisfactory;
21
22  String _xcodeSelectPath;
23  String get xcodeSelectPath {
24    if (_xcodeSelectPath == null) {
25      try {
26        _xcodeSelectPath = processManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']).stdout.trim();
27      } on ProcessException {
28        // Ignored, return null below.
29      } on ArgumentError {
30        // Ignored, return null below.
31      }
32    }
33    return _xcodeSelectPath;
34  }
35
36  bool get isInstalled {
37    if (xcodeSelectPath == null || xcodeSelectPath.isEmpty)
38      return false;
39    return xcodeProjectInterpreter.isInstalled;
40  }
41
42  int get majorVersion => xcodeProjectInterpreter.majorVersion;
43
44  int get minorVersion => xcodeProjectInterpreter.minorVersion;
45
46  String get versionText => xcodeProjectInterpreter.versionText;
47
48  bool _eulaSigned;
49  /// Has the EULA been signed?
50  bool get eulaSigned {
51    if (_eulaSigned == null) {
52      try {
53        final ProcessResult result = processManager.runSync(<String>['/usr/bin/xcrun', 'clang']);
54        if (result.stdout != null && result.stdout.contains('license'))
55          _eulaSigned = false;
56        else if (result.stderr != null && result.stderr.contains('license'))
57          _eulaSigned = false;
58        else
59          _eulaSigned = true;
60      } on ProcessException {
61        _eulaSigned = false;
62      }
63    }
64    return _eulaSigned;
65  }
66
67  bool _isSimctlInstalled;
68
69  /// Verifies that simctl is installed by trying to run it.
70  bool get isSimctlInstalled {
71    if (_isSimctlInstalled == null) {
72      try {
73        // This command will error if additional components need to be installed in
74        // xcode 9.2 and above.
75        final ProcessResult result = processManager.runSync(<String>['/usr/bin/xcrun', 'simctl', 'list']);
76        _isSimctlInstalled = result.stderr == null || result.stderr == '';
77      } on ProcessException {
78        _isSimctlInstalled = false;
79      }
80    }
81    return _isSimctlInstalled;
82  }
83
84  bool get isVersionSatisfactory {
85    if (!xcodeProjectInterpreter.isInstalled)
86      return false;
87    if (majorVersion > kXcodeRequiredVersionMajor)
88      return true;
89    if (majorVersion == kXcodeRequiredVersionMajor)
90      return minorVersion >= kXcodeRequiredVersionMinor;
91    return false;
92  }
93
94  Future<RunResult> cc(List<String> args) {
95    return runCheckedAsync(<String>['xcrun', 'cc', ...args]);
96  }
97
98  Future<RunResult> clang(List<String> args) {
99    return runCheckedAsync(<String>['xcrun', 'clang', ...args]);
100  }
101
102  Future<RunResult> dsymutil(List<String> args) {
103    return runCheckedAsync(<String>['xcrun', 'dsymutil', ...args]);
104  }
105
106  Future<RunResult> strip(List<String> args) {
107    return runCheckedAsync(<String>['xcrun', 'strip', ...args]);
108  }
109
110  Future<RunResult> otool(List<String> args) {
111    return runCheckedAsync(<String>['xcrun', 'otool', ...args]);
112  }
113
114  String getSimulatorPath() {
115    if (xcodeSelectPath == null)
116      return null;
117    final List<String> searchPaths = <String>[
118      fs.path.join(xcodeSelectPath, 'Applications', 'Simulator.app'),
119    ];
120    return searchPaths.where((String p) => p != null).firstWhere(
121      (String p) => fs.directory(p).existsSync(),
122      orElse: () => null,
123    );
124  }
125}
126