artifacts.dart 11.3 KB
Newer Older
1 2 3 4
// Copyright 2017 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 6
import 'package:meta/meta.dart';

7 8 9 10 11 12 13 14 15 16
import 'base/context.dart';
import 'base/file_system.dart';
import 'base/platform.dart';
import 'build_info.dart';
import 'globals.dart';

enum Artifact {
  dartIoEntriesTxt,
  dartVmEntryPointsTxt,
  genSnapshot,
17
  flutterTester,
18 19
  snapshotDart,
  flutterFramework,
20
  vmSnapshotData,
21 22 23 24 25 26
  isolateSnapshotData,
  platformKernelDill,
  platformLibrariesJson,
  flutterPatchedSdkPath,
  frontendServerSnapshotForEngineDartSdk,
  engineDartSdkPath,
27 28 29 30 31 32 33 34 35 36
}

String _artifactToFileName(Artifact artifact) {
  switch (artifact) {
    case Artifact.dartIoEntriesTxt:
      return 'dart_io_entries.txt';
    case Artifact.dartVmEntryPointsTxt:
      return 'dart_vm_entry_points.txt';
    case Artifact.genSnapshot:
      return 'gen_snapshot';
37
    case Artifact.flutterTester:
38
      return 'flutter_tester';
39 40 41 42
    case Artifact.snapshotDart:
      return 'snapshot.dart';
    case Artifact.flutterFramework:
      return 'Flutter.framework';
43 44 45 46
    case Artifact.vmSnapshotData:
      return 'vm_isolate_snapshot.bin';
    case Artifact.isolateSnapshotData:
      return 'isolate_snapshot.bin';
47 48 49 50 51 52 53 54 55 56 57
    case Artifact.platformKernelDill:
      return 'platform.dill';
    case Artifact.platformLibrariesJson:
      return 'libraries.json';
    case Artifact.flutterPatchedSdkPath:
      assert(false, 'No filename for sdk path, should not be invoked');
      return null;
    case Artifact.engineDartSdkPath:
      return 'dart-sdk';
    case Artifact.frontendServerSnapshotForEngineDartSdk:
      return 'frontend_server.dart.snapshot';
58 59 60 61 62
  }
  assert(false, 'Invalid artifact $artifact.');
  return null;
}

63 64 65 66 67 68 69 70 71
class EngineBuildPaths {
  const EngineBuildPaths({ @required this.targetEngine, @required this.hostEngine }):
      assert(targetEngine != null),
      assert(hostEngine != null);

  final String targetEngine;
  final String hostEngine;
}

72 73 74 75
// Manages the engine artifacts of Flutter.
abstract class Artifacts {
  static Artifacts get instance => context[Artifacts];

76 77
  static void useLocalEngine(String engineSrcPath, EngineBuildPaths engineBuildPaths) {
    context.setVariable(Artifacts, new LocalEngineArtifacts(engineSrcPath, engineBuildPaths.targetEngine, engineBuildPaths.hostEngine));
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
  }

  // Returns the requested [artifact] for the [platform] and [mode] combination.
  String getArtifactPath(Artifact artifact, [TargetPlatform platform, BuildMode mode]);

  // Returns which set of engine artifacts is currently used for the [platform]
  // and [mode] combination.
  String getEngineType(TargetPlatform platform, [BuildMode mode]);
}

/// Manages the engine artifacts downloaded to the local cache.
class CachedArtifacts extends Artifacts {

  @override
  String getArtifactPath(Artifact artifact, [TargetPlatform platform, BuildMode mode]) {
    platform ??= _currentHostPlatform;
    switch (platform) {
      case TargetPlatform.android_arm:
      case TargetPlatform.android_x64:
      case TargetPlatform.android_x86:
        return _getAndroidArtifactPath(artifact, platform, mode);
      case TargetPlatform.ios:
        return _getIosArtifactPath(artifact, platform, mode);
      case TargetPlatform.darwin_x64:
      case TargetPlatform.linux_x64:
103
      case TargetPlatform.windows_x64:
104
      case TargetPlatform.fuchsia:
105 106 107 108 109 110 111 112 113 114 115 116
        return _getHostArtifactPath(artifact, platform);
    }
    assert(false, 'Invalid platform $platform.');
    return null;
  }

  @override
  String getEngineType(TargetPlatform platform, [BuildMode mode]){
    return fs.path.basename(_getEngineArtifactsPath(platform, mode));
  }

  String _getAndroidArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) {
117
    final String engineDir = _getEngineArtifactsPath(platform, mode);
118 119 120
    switch (artifact) {
      case Artifact.dartIoEntriesTxt:
      case Artifact.dartVmEntryPointsTxt:
121
      case Artifact.frontendServerSnapshotForEngineDartSdk:
122 123 124 125
        assert(mode != BuildMode.debug, 'Artifact $artifact only available in non-debug mode.');
        return fs.path.join(engineDir, _artifactToFileName(artifact));
      case Artifact.genSnapshot:
        assert(mode != BuildMode.debug, 'Artifact $artifact only available in non-debug mode.');
126
        final String hostPlatform = getNameForHostPlatform(getCurrentHostPlatform());
127 128 129 130 131 132 133 134
        return fs.path.join(engineDir, hostPlatform, _artifactToFileName(artifact));
      default:
        assert(false, 'Artifact $artifact not available for platform $platform.');
        return null;
    }
  }

  String _getIosArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) {
135
    final String engineDir = _getEngineArtifactsPath(platform, mode);
136 137 138 139 140 141
    switch (artifact) {
      case Artifact.dartIoEntriesTxt:
      case Artifact.dartVmEntryPointsTxt:
      case Artifact.genSnapshot:
      case Artifact.snapshotDart:
      case Artifact.flutterFramework:
142
      case Artifact.frontendServerSnapshotForEngineDartSdk:
143 144 145 146 147 148 149
        return fs.path.join(engineDir, _artifactToFileName(artifact));
      default:
        assert(false, 'Artifact $artifact not available for platform $platform.');
        return null;
    }
  }

150 151 152 153 154
  String _getFlutterPatchedSdkPath() {
    final String engineArtifactsPath = cache.getArtifactDirectory('engine').path;
    return fs.path.join(engineArtifactsPath, 'common', 'flutter_patched_sdk');
  }

155 156
  String _getHostArtifactPath(Artifact artifact, TargetPlatform platform) {
    switch (artifact) {
157 158 159 160
      case Artifact.genSnapshot:
        // For script snapshots any gen_snapshot binary will do. Returning gen_snapshot for
        // android_arm in profile mode because it is available on all supported host platforms.
        return _getAndroidArtifactPath(artifact, TargetPlatform.android_arm, BuildMode.profile);
161
      case Artifact.flutterTester:
162 163
        if (platform == TargetPlatform.windows_x64)
          throw new UnimplementedError('Artifact $artifact not available on platfrom $platform.');
164 165
        continue fallThrough;
      fallThrough:
166 167
      case Artifact.vmSnapshotData:
      case Artifact.isolateSnapshotData:
168 169
      case Artifact.frontendServerSnapshotForEngineDartSdk:
      case Artifact.engineDartSdkPath:
170 171
        final String engineArtifactsPath = cache.getArtifactDirectory('engine').path;
        final String platformDirName = getNameForTargetPlatform(platform);
172
        return fs.path.join(engineArtifactsPath, platformDirName, _artifactToFileName(artifact));
173 174 175 176 177 178
      case Artifact.platformKernelDill:
        return fs.path.join(_getFlutterPatchedSdkPath(), _artifactToFileName(artifact));
      case Artifact.platformLibrariesJson:
        return fs.path.join(_getFlutterPatchedSdkPath(), 'lib', _artifactToFileName(artifact));
      case Artifact.flutterPatchedSdkPath:
        return _getFlutterPatchedSdkPath();
179 180 181 182
      default:
        assert(false, 'Artifact $artifact not available for platform $platform.');
        return null;
    }
183 184
    assert(false, 'Artifact $artifact not available for platform $platform.');
    return null;
185 186 187
  }

  String _getEngineArtifactsPath(TargetPlatform platform, [BuildMode mode]) {
188 189
    final String engineDir = cache.getArtifactDirectory('engine').path;
    final String platformName = getNameForTargetPlatform(platform);
190 191 192
    switch (platform) {
      case TargetPlatform.linux_x64:
      case TargetPlatform.darwin_x64:
193
      case TargetPlatform.windows_x64:
194
      case TargetPlatform.fuchsia:
195 196 197 198 199 200 201
        assert(mode == null, 'Platform $platform does not support different build modes.');
        return fs.path.join(engineDir, platformName);
      case TargetPlatform.ios:
      case TargetPlatform.android_arm:
      case TargetPlatform.android_x64:
      case TargetPlatform.android_x86:
        assert(mode != null, 'Need to specify a build mode for platform $platform.');
202
        final String suffix = mode != BuildMode.debug ? '-${getModeName(mode)}' : '';
203 204 205 206 207 208 209 210 211 212 213
        return fs.path.join(engineDir, platformName + suffix);
    }
    assert(false, 'Invalid platform $platform.');
    return null;
  }

  TargetPlatform get _currentHostPlatform {
    if (platform.isMacOS)
      return TargetPlatform.darwin_x64;
    if (platform.isLinux)
      return TargetPlatform.linux_x64;
214 215
    if (platform.isWindows)
      return TargetPlatform.windows_x64;
216 217 218 219 220 221 222 223
    throw new UnimplementedError('Host OS not supported.');
  }
}

/// Manages the artifacts of a locally built engine.
class LocalEngineArtifacts extends Artifacts {
  final String _engineSrcPath;
  final String engineOutPath; // TODO(goderbauer): This should be private.
224
  String _hostEngineOutPath;
225

226
  LocalEngineArtifacts(this._engineSrcPath, this.engineOutPath, this._hostEngineOutPath);
227 228 229 230 231 232 233 234 235 236 237

  @override
  String getArtifactPath(Artifact artifact, [TargetPlatform platform, BuildMode mode]) {
    switch (artifact) {
      case Artifact.dartIoEntriesTxt:
        return fs.path.join(_engineSrcPath, 'dart', 'runtime', 'bin', _artifactToFileName(artifact));
      case Artifact.dartVmEntryPointsTxt:
        return fs.path.join(_engineSrcPath, 'flutter', 'runtime', _artifactToFileName(artifact));
      case Artifact.snapshotDart:
        return fs.path.join(_engineSrcPath, 'flutter', 'lib', 'snapshot', _artifactToFileName(artifact));
      case Artifact.genSnapshot:
238
        return _genSnapshotPath();
239 240
      case Artifact.flutterTester:
        return _flutterTesterPath(platform);
241 242 243
      case Artifact.isolateSnapshotData:
      case Artifact.vmSnapshotData:
        return fs.path.join(engineOutPath, 'gen', 'flutter', 'lib', 'snapshot', _artifactToFileName(artifact));
244 245 246 247
      case Artifact.platformKernelDill:
        return fs.path.join(_getFlutterPatchedSdkPath(), _artifactToFileName(artifact));
      case Artifact.platformLibrariesJson:
        return fs.path.join(_getFlutterPatchedSdkPath(), 'lib', _artifactToFileName(artifact));
248 249
      case Artifact.flutterFramework:
        return fs.path.join(engineOutPath, _artifactToFileName(artifact));
250 251 252 253 254 255
      case Artifact.flutterPatchedSdkPath:
        return _getFlutterPatchedSdkPath();
      case Artifact.frontendServerSnapshotForEngineDartSdk:
        return fs.path.join(_hostEngineOutPath, 'gen', _artifactToFileName(artifact));
      case Artifact.engineDartSdkPath:
        return fs.path.join(_hostEngineOutPath, 'dart-sdk');
256 257 258 259 260 261 262 263 264 265
    }
    assert(false, 'Invalid artifact $artifact.');
    return null;
  }

  @override
  String getEngineType(TargetPlatform platform, [BuildMode mode]) {
    return fs.path.basename(engineOutPath);
  }

266 267 268 269
  String _getFlutterPatchedSdkPath() {
    return fs.path.join(engineOutPath, 'flutter_patched_sdk');
  }

270 271 272 273 274 275 276
  String _genSnapshotPath() {
    const List<String> clangDirs = const <String>['clang_x86', 'clang_x64', 'clang_i386'];
    final String genSnapshotName = _artifactToFileName(Artifact.genSnapshot);
    for (String clangDir in clangDirs) {
      final String genSnapshotPath = fs.path.join(engineOutPath, clangDir, genSnapshotName);
      if (fs.file(genSnapshotPath).existsSync())
        return genSnapshotPath;
277
    }
278
    throw new Exception('Unable to find $genSnapshotName');
279 280
  }

281
  String _flutterTesterPath(TargetPlatform platform) {
282
    if (getCurrentHostPlatform() == HostPlatform.linux_x64) {
283
      return fs.path.join(engineOutPath, _artifactToFileName(Artifact.flutterTester));
284
    } else if (getCurrentHostPlatform() == HostPlatform.darwin_x64) {
285
      return fs.path.join(engineOutPath, 'flutter_tester');
286 287 288 289
    }
    throw new Exception('Unsupported platform $platform.');
  }
}