blob: 386741a0e40df65f52d1c3cb00d29b3a22286c61 [file] [log] [blame]
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:file/memory.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'base/common.dart';
import 'base/file_system.dart';
import 'base/os.dart';
import 'base/platform.dart';
import 'base/user_messages.dart';
import 'base/utils.dart';
import 'build_info.dart';
import 'cache.dart';
import 'globals.dart' as globals;
enum Artifact {
/// The tool which compiles a dart kernel file into native code.
genSnapshot,
/// The flutter tester binary.
flutterTester,
flutterFramework,
flutterXcframework,
/// The framework directory of the macOS desktop.
flutterMacOSFramework,
vmSnapshotData,
isolateSnapshotData,
icuData,
platformKernelDill,
platformLibrariesJson,
flutterPatchedSdkPath,
/// The root directory of the dart SDK.
engineDartSdkPath,
/// The dart binary used to execute any of the required snapshots.
engineDartBinary,
/// The dart binary for running aot snapshots
engineDartAotRuntime,
/// The snapshot of frontend_server compiler.
frontendServerSnapshotForEngineDartSdk,
/// The dart snapshot of the dart2js compiler.
dart2jsSnapshot,
/// The dart snapshot of the dart2wasm compiler.
dart2wasmSnapshot,
/// The wasm-opt binary that ships with the dart-sdk
wasmOptBinary,
/// The root of the Linux desktop sources.
linuxDesktopPath,
// The root of the cpp headers for Linux desktop.
linuxHeaders,
/// The root of the Windows desktop sources.
windowsDesktopPath,
/// The root of the cpp client code for Windows desktop.
windowsCppClientWrapper,
/// The root of the sky_engine package.
skyEnginePath,
// Fuchsia artifacts from the engine prebuilts.
fuchsiaKernelCompiler,
fuchsiaFlutterRunner,
/// Tools related to subsetting or icon font files.
fontSubset,
constFinder,
/// The location of file generators.
flutterToolsFileGenerators,
/// Pre-built desktop debug app.
flutterPreviewDevice,
}
/// A subset of [Artifact]s that are platform and build mode independent
enum HostArtifact {
/// The root of the web implementation of the dart SDK.
flutterWebSdk,
/// The libraries JSON file for web release builds.
flutterWebLibrariesJson,
// The flutter.js bootstrapping file provided by the engine.
flutterJsDirectory,
/// Folder that contains platform dill files for the web sdk.
webPlatformKernelFolder,
/// The summary dill for the dartdevc target.
webPlatformDDCKernelDill,
/// The summary dill with null safety enabled for the dartdevc target.g
webPlatformDDCSoundKernelDill,
/// The summary dill for the dartdevc target.
webPlatformDart2JSKernelDill,
/// The summary dill with null safety enabled for the dartdevc target.
webPlatformDart2JSSoundKernelDill,
/// The precompiled SDKs and sourcemaps for web debug builds.
webPrecompiledSdk,
webPrecompiledSdkSourcemaps,
webPrecompiledCanvaskitSdk,
webPrecompiledCanvaskitSdkSourcemaps,
webPrecompiledCanvaskitAndHtmlSdk,
webPrecompiledCanvaskitAndHtmlSdkSourcemaps,
webPrecompiledSoundSdk,
webPrecompiledSoundSdkSourcemaps,
webPrecompiledCanvaskitSoundSdk,
webPrecompiledCanvaskitSoundSdkSourcemaps,
webPrecompiledCanvaskitAndHtmlSoundSdk,
webPrecompiledCanvaskitAndHtmlSoundSdkSourcemaps,
iosDeploy,
idevicesyslog,
idevicescreenshot,
iproxy,
/// The root of the sky_engine package.
skyEnginePath,
// The Impeller shader compiler.
impellerc,
// The Impeller Scene 3D model importer.
scenec,
// Impeller's tessellation library.
libtessellator,
}
// TODO(knopp): Remove once darwin artifacts are universal and moved out of darwin-x64
String _enginePlatformDirectoryName(TargetPlatform platform) {
if (platform == TargetPlatform.darwin) {
return 'darwin-x64';
}
return getNameForTargetPlatform(platform);
}
// Remove android target platform type.
TargetPlatform? _mapTargetPlatform(TargetPlatform? targetPlatform) {
switch (targetPlatform) {
case TargetPlatform.android:
return TargetPlatform.android_arm64;
case TargetPlatform.ios:
case TargetPlatform.darwin:
case TargetPlatform.linux_x64:
case TargetPlatform.linux_arm64:
case TargetPlatform.windows_x64:
case TargetPlatform.fuchsia_arm64:
case TargetPlatform.fuchsia_x64:
case TargetPlatform.tester:
case TargetPlatform.web_javascript:
case TargetPlatform.android_arm:
case TargetPlatform.android_arm64:
case TargetPlatform.android_x64:
case TargetPlatform.android_x86:
case null:
return targetPlatform;
}
}
String? _artifactToFileName(Artifact artifact, Platform hostPlatform, [ BuildMode? mode ]) {
final String exe = hostPlatform.isWindows ? '.exe' : '';
switch (artifact) {
case Artifact.genSnapshot:
return 'gen_snapshot';
case Artifact.flutterTester:
return 'flutter_tester$exe';
case Artifact.flutterFramework:
return 'Flutter.framework';
case Artifact.flutterXcframework:
return 'Flutter.xcframework';
case Artifact.flutterMacOSFramework:
return 'FlutterMacOS.framework';
case Artifact.vmSnapshotData:
return 'vm_isolate_snapshot.bin';
case Artifact.isolateSnapshotData:
return 'isolate_snapshot.bin';
case Artifact.icuData:
return 'icudtl.dat';
case Artifact.platformKernelDill:
return 'platform_strong.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.engineDartBinary:
return 'dart$exe';
case Artifact.engineDartAotRuntime:
return 'dartaotruntime$exe';
case Artifact.dart2jsSnapshot:
return 'dart2js.dart.snapshot';
case Artifact.dart2wasmSnapshot:
return 'dart2wasm_product.snapshot';
case Artifact.wasmOptBinary:
return 'wasm-opt$exe';
case Artifact.frontendServerSnapshotForEngineDartSdk:
return 'frontend_server_aot.dart.snapshot';
case Artifact.linuxDesktopPath:
return '';
case Artifact.linuxHeaders:
return 'flutter_linux';
case Artifact.windowsCppClientWrapper:
return 'cpp_client_wrapper';
case Artifact.windowsDesktopPath:
return '';
case Artifact.skyEnginePath:
return 'sky_engine';
case Artifact.fuchsiaKernelCompiler:
return 'kernel_compiler.snapshot';
case Artifact.fuchsiaFlutterRunner:
final String jitOrAot = mode!.isJit ? '_jit' : '_aot';
final String productOrNo = mode.isRelease ? '_product' : '';
return 'flutter$jitOrAot${productOrNo}_runner-0.far';
case Artifact.fontSubset:
return 'font-subset$exe';
case Artifact.constFinder:
return 'const_finder.dart.snapshot';
case Artifact.flutterToolsFileGenerators:
return '';
case Artifact.flutterPreviewDevice:
return 'flutter_preview$exe';
}
}
String _hostArtifactToFileName(HostArtifact artifact, Platform platform) {
final String exe = platform.isWindows ? '.exe' : '';
String dll = '.so';
if (platform.isWindows) {
dll = '.dll';
} else if (platform.isMacOS) {
dll = '.dylib';
}
switch (artifact) {
case HostArtifact.flutterWebSdk:
return '';
case HostArtifact.flutterJsDirectory:
return 'flutter_js';
case HostArtifact.iosDeploy:
return 'ios-deploy';
case HostArtifact.idevicesyslog:
return 'idevicesyslog';
case HostArtifact.idevicescreenshot:
return 'idevicescreenshot';
case HostArtifact.iproxy:
return 'iproxy';
case HostArtifact.skyEnginePath:
return 'sky_engine';
case HostArtifact.webPlatformKernelFolder:
return 'kernel';
case HostArtifact.webPlatformDDCKernelDill:
return 'ddc_outline.dill';
case HostArtifact.webPlatformDDCSoundKernelDill:
return 'ddc_outline_sound.dill';
case HostArtifact.webPlatformDart2JSKernelDill:
return 'dart2js_platform_unsound.dill';
case HostArtifact.webPlatformDart2JSSoundKernelDill:
return 'dart2js_platform.dill';
case HostArtifact.flutterWebLibrariesJson:
return 'libraries.json';
case HostArtifact.webPrecompiledSdk:
case HostArtifact.webPrecompiledCanvaskitSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledSoundSdk:
case HostArtifact.webPrecompiledCanvaskitSoundSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdk:
return 'dart_sdk.js';
case HostArtifact.webPrecompiledSdkSourcemaps:
case HostArtifact.webPrecompiledCanvaskitSdkSourcemaps:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdkSourcemaps:
case HostArtifact.webPrecompiledSoundSdkSourcemaps:
case HostArtifact.webPrecompiledCanvaskitSoundSdkSourcemaps:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdkSourcemaps:
return 'dart_sdk.js.map';
case HostArtifact.impellerc:
return 'impellerc$exe';
case HostArtifact.scenec:
return 'scenec$exe';
case HostArtifact.libtessellator:
return 'libtessellator$dll';
}
}
class EngineBuildPaths {
const EngineBuildPaths({
required this.targetEngine,
required this.hostEngine,
required this.webSdk,
});
final String? targetEngine;
final String? hostEngine;
final String? webSdk;
}
/// Information about a local engine build (i.e. `--local-engine[-host]=...`).
///
/// See https://github.com/flutter/flutter/wiki/The-flutter-tool#using-a-locally-built-engine-with-the-flutter-tool
/// for more information about local engine builds.
class LocalEngineInfo {
/// Creates a reference to a local engine build.
///
/// The [targetOutPath] and [hostOutPath] are assumed to be resolvable
/// paths to the built engine artifacts for the target (device) and host
/// (build) platforms, respectively.
const LocalEngineInfo({
required this.targetOutPath,
required this.hostOutPath,
});
/// The path to the engine artifacts for the target (device) platform.
///
/// For example, if the target platform is Android debug, this would be a path
/// like `/path/to/engine/src/out/android_debug_unopt`. To retrieve just the
/// name (platform), see [localTargetName].
final String targetOutPath;
/// The path to the engine artifacts for the host (build) platform.
///
/// For example, if the host platform is debug, this would be a path like
/// `/path/to/engine/src/out/host_debug_unopt`. To retrieve just the name
/// (platform), see [localHostName].
final String hostOutPath;
/// The name of the target (device) platform, i.e. `android_debug_unopt`.
String get localTargetName => globals.fs.path.basename(targetOutPath);
/// The name of the host (build) platform, e.g. `host_debug_unopt`.
String get localHostName => globals.fs.path.basename(hostOutPath);
}
// Manages the engine artifacts of Flutter.
abstract class Artifacts {
/// A test-specific implementation of artifacts that returns stable paths for
/// all artifacts.
///
/// If a [fileSystem] is not provided, creates a new [MemoryFileSystem] instance.
///
/// Creates a [LocalEngineArtifacts] if `localEngine` is non-null
@visibleForTesting
factory Artifacts.test({FileSystem? fileSystem}) {
return _TestArtifacts(fileSystem ?? MemoryFileSystem.test());
}
/// A test-specific implementation of artifacts that returns stable paths for
/// all artifacts, and uses a local engine.
///
/// If a [fileSystem] is not provided, creates a new [MemoryFileSystem] instance.
@visibleForTesting
factory Artifacts.testLocalEngine({
required String localEngine,
required String localEngineHost,
FileSystem? fileSystem,
}) {
return _TestLocalEngine(
localEngine, localEngineHost, fileSystem ?? MemoryFileSystem.test());
}
static Artifacts getLocalEngine(EngineBuildPaths engineBuildPaths) {
Artifacts artifacts = CachedArtifacts(
fileSystem: globals.fs,
platform: globals.platform,
cache: globals.cache,
operatingSystemUtils: globals.os
);
if (engineBuildPaths.hostEngine != null && engineBuildPaths.targetEngine != null) {
artifacts = CachedLocalEngineArtifacts(
engineBuildPaths.hostEngine!,
engineOutPath: engineBuildPaths.targetEngine!,
cache: globals.cache,
fileSystem: globals.fs,
processManager: globals.processManager,
platform: globals.platform,
operatingSystemUtils: globals.os,
parent: artifacts,
);
}
if (engineBuildPaths.webSdk != null) {
artifacts = CachedLocalWebSdkArtifacts(
parent: artifacts,
webSdkPath: engineBuildPaths.webSdk!,
fileSystem: globals.fs,
platform: globals.platform,
operatingSystemUtils: globals.os
);
}
return artifacts;
}
/// Returns the requested [artifact] for the [platform], [mode], and [environmentType] combination.
String getArtifactPath(
Artifact artifact, {
TargetPlatform? platform,
BuildMode? mode,
EnvironmentType? environmentType,
});
/// Retrieve a host specific artifact that does not depend on the
/// current build mode or environment.
FileSystemEntity getHostArtifact(
HostArtifact artifact,
);
// Returns which set of engine artifacts is currently used for the [platform]
// and [mode] combination.
String getEngineType(TargetPlatform platform, [ BuildMode? mode ]);
/// Whether these artifacts correspond to a non-versioned local engine.
bool get isLocalEngine;
/// If these artifacts are bound to a local engine build, returns info about
/// the location and name of the local engine, otherwise returns null.
LocalEngineInfo? get localEngineInfo;
}
/// Manages the engine artifacts downloaded to the local cache.
class CachedArtifacts implements Artifacts {
CachedArtifacts({
required FileSystem fileSystem,
required Platform platform,
required Cache cache,
required OperatingSystemUtils operatingSystemUtils,
}) : _fileSystem = fileSystem,
_platform = platform,
_cache = cache,
_operatingSystemUtils = operatingSystemUtils;
final FileSystem _fileSystem;
final Platform _platform;
final Cache _cache;
final OperatingSystemUtils _operatingSystemUtils;
@override
LocalEngineInfo? get localEngineInfo => null;
@override
FileSystemEntity getHostArtifact(
HostArtifact artifact,
) {
switch (artifact) {
case HostArtifact.flutterWebSdk:
final String path = _getFlutterWebSdkPath();
return _fileSystem.directory(path);
case HostArtifact.flutterWebLibrariesJson:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.flutterJsDirectory:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'flutter_js');
return _fileSystem.directory(path);
case HostArtifact.webPlatformKernelFolder:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel');
return _fileSystem.file(path);
case HostArtifact.webPlatformDDCKernelDill:
case HostArtifact.webPlatformDDCSoundKernelDill:
case HostArtifact.webPlatformDart2JSKernelDill:
case HostArtifact.webPlatformDart2JSSoundKernelDill:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledSdk:
case HostArtifact.webPrecompiledSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitSdk:
case HostArtifact.webPrecompiledCanvaskitSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-html', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledSoundSdk:
case HostArtifact.webPrecompiledSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitSoundSdk:
case HostArtifact.webPrecompiledCanvaskitSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-html-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.idevicesyslog:
case HostArtifact.idevicescreenshot:
final String artifactFileName = _hostArtifactToFileName(artifact, _platform);
return _cache.getArtifactDirectory('libimobiledevice').childFile(artifactFileName);
case HostArtifact.skyEnginePath:
final Directory dartPackageDirectory = _cache.getCacheDir('pkg');
final String path = _fileSystem.path.join(dartPackageDirectory.path, _hostArtifactToFileName(artifact, _platform));
return _fileSystem.directory(path);
case HostArtifact.iosDeploy:
final String artifactFileName = _hostArtifactToFileName(artifact, _platform);
return _cache.getArtifactDirectory('ios-deploy').childFile(artifactFileName);
case HostArtifact.iproxy:
final String artifactFileName = _hostArtifactToFileName(artifact, _platform);
return _cache.getArtifactDirectory('usbmuxd').childFile(artifactFileName);
case HostArtifact.impellerc:
case HostArtifact.scenec:
case HostArtifact.libtessellator:
final String artifactFileName = _hostArtifactToFileName(artifact, _platform);
final String engineDir = _getEngineArtifactsPath(_currentHostPlatform(_platform, _operatingSystemUtils))!;
return _fileSystem.file(_fileSystem.path.join(engineDir, artifactFileName));
}
}
@override
String getArtifactPath(
Artifact artifact, {
TargetPlatform? platform,
BuildMode? mode,
EnvironmentType? environmentType,
}) {
platform = _mapTargetPlatform(platform);
switch (platform) {
case TargetPlatform.android:
case TargetPlatform.android_arm:
case TargetPlatform.android_arm64:
case TargetPlatform.android_x64:
case TargetPlatform.android_x86:
assert(platform != TargetPlatform.android);
return _getAndroidArtifactPath(artifact, platform!, mode!);
case TargetPlatform.ios:
return _getIosArtifactPath(artifact, platform!, mode, environmentType);
case TargetPlatform.darwin:
case TargetPlatform.linux_x64:
case TargetPlatform.linux_arm64:
case TargetPlatform.windows_x64:
return _getDesktopArtifactPath(artifact, platform, mode);
case TargetPlatform.fuchsia_arm64:
case TargetPlatform.fuchsia_x64:
return _getFuchsiaArtifactPath(artifact, platform!, mode!);
case TargetPlatform.tester:
case TargetPlatform.web_javascript:
case null:
return _getHostArtifactPath(artifact, platform ?? _currentHostPlatform(_platform, _operatingSystemUtils), mode);
}
}
@override
String getEngineType(TargetPlatform platform, [ BuildMode? mode ]) {
return _fileSystem.path.basename(_getEngineArtifactsPath(platform, mode)!);
}
String _getDesktopArtifactPath(Artifact artifact, TargetPlatform? platform, BuildMode? mode) {
// When platform is null, a generic host platform artifact is being requested
// and not the gen_snapshot for darwin as a target platform.
if (platform != null && artifact == Artifact.genSnapshot) {
final String engineDir = _getEngineArtifactsPath(platform, mode)!;
return _fileSystem.path.join(engineDir, _artifactToFileName(artifact, _platform));
}
return _getHostArtifactPath(artifact, platform ?? _currentHostPlatform(_platform, _operatingSystemUtils), mode);
}
String _getAndroidArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) {
final String engineDir = _getEngineArtifactsPath(platform, mode)!;
switch (artifact) {
case Artifact.genSnapshot:
assert(mode != BuildMode.debug, 'Artifact $artifact only available in non-debug mode.');
final String hostPlatform = getNameForHostPlatform(getCurrentHostPlatform());
return _fileSystem.path.join(engineDir, hostPlatform, _artifactToFileName(artifact, _platform));
case Artifact.engineDartSdkPath:
case Artifact.engineDartBinary:
case Artifact.engineDartAotRuntime:
case Artifact.dart2jsSnapshot:
case Artifact.dart2wasmSnapshot:
case Artifact.wasmOptBinary:
case Artifact.frontendServerSnapshotForEngineDartSdk:
case Artifact.constFinder:
case Artifact.flutterFramework:
case Artifact.flutterMacOSFramework:
case Artifact.flutterPatchedSdkPath:
case Artifact.flutterTester:
case Artifact.flutterXcframework:
case Artifact.fontSubset:
case Artifact.fuchsiaFlutterRunner:
case Artifact.fuchsiaKernelCompiler:
case Artifact.icuData:
case Artifact.isolateSnapshotData:
case Artifact.linuxDesktopPath:
case Artifact.linuxHeaders:
case Artifact.platformKernelDill:
case Artifact.platformLibrariesJson:
case Artifact.skyEnginePath:
case Artifact.vmSnapshotData:
case Artifact.windowsCppClientWrapper:
case Artifact.windowsDesktopPath:
case Artifact.flutterToolsFileGenerators:
case Artifact.flutterPreviewDevice:
return _getHostArtifactPath(artifact, platform, mode);
}
}
String _getIosArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode? mode, EnvironmentType? environmentType) {
switch (artifact) {
case Artifact.genSnapshot:
case Artifact.flutterXcframework:
final String artifactFileName = _artifactToFileName(artifact, _platform)!;
final String engineDir = _getEngineArtifactsPath(platform, mode)!;
return _fileSystem.path.join(engineDir, artifactFileName);
case Artifact.flutterFramework:
final String engineDir = _getEngineArtifactsPath(platform, mode)!;
return _getIosEngineArtifactPath(engineDir, environmentType, _fileSystem, _platform);
case Artifact.engineDartSdkPath:
case Artifact.engineDartBinary:
case Artifact.engineDartAotRuntime:
case Artifact.dart2jsSnapshot:
case Artifact.dart2wasmSnapshot:
case Artifact.wasmOptBinary:
case Artifact.frontendServerSnapshotForEngineDartSdk:
case Artifact.constFinder:
case Artifact.flutterMacOSFramework:
case Artifact.flutterPatchedSdkPath:
case Artifact.flutterTester:
case Artifact.fontSubset:
case Artifact.fuchsiaFlutterRunner:
case Artifact.fuchsiaKernelCompiler:
case Artifact.icuData:
case Artifact.isolateSnapshotData:
case Artifact.linuxDesktopPath:
case Artifact.linuxHeaders:
case Artifact.platformKernelDill:
case Artifact.platformLibrariesJson:
case Artifact.skyEnginePath:
case Artifact.vmSnapshotData:
case Artifact.windowsCppClientWrapper:
case Artifact.windowsDesktopPath:
case Artifact.flutterToolsFileGenerators:
case Artifact.flutterPreviewDevice:
return _getHostArtifactPath(artifact, platform, mode);
}
}
String _getFuchsiaArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) {
final String root = _fileSystem.path.join(
_cache.getArtifactDirectory('flutter_runner').path,
'flutter',
platform.fuchsiaArchForTargetPlatform,
mode.isRelease ? 'release' : mode.toString(),
);
final String runtime = mode.isJit ? 'jit' : 'aot';
switch (artifact) {
case Artifact.genSnapshot:
final String genSnapshot = mode.isRelease ? 'gen_snapshot_product' : 'gen_snapshot';
return _fileSystem.path.join(root, runtime, 'dart_binaries', genSnapshot);
case Artifact.flutterPatchedSdkPath:
const String artifactFileName = 'flutter_runner_patched_sdk';
return _fileSystem.path.join(root, runtime, artifactFileName);
case Artifact.platformKernelDill:
final String artifactFileName = _artifactToFileName(artifact, _platform, mode)!;
return _fileSystem.path.join(root, runtime, 'flutter_runner_patched_sdk', artifactFileName);
case Artifact.fuchsiaKernelCompiler:
final String artifactFileName = _artifactToFileName(artifact, _platform, mode)!;
return _fileSystem.path.join(root, runtime, 'dart_binaries', artifactFileName);
case Artifact.fuchsiaFlutterRunner:
final String artifactFileName = _artifactToFileName(artifact, _platform, mode)!;
return _fileSystem.path.join(root, runtime, artifactFileName);
case Artifact.constFinder:
case Artifact.flutterFramework:
case Artifact.flutterMacOSFramework:
case Artifact.flutterTester:
case Artifact.flutterXcframework:
case Artifact.fontSubset:
case Artifact.engineDartSdkPath:
case Artifact.engineDartBinary:
case Artifact.engineDartAotRuntime:
case Artifact.dart2jsSnapshot:
case Artifact.dart2wasmSnapshot:
case Artifact.wasmOptBinary:
case Artifact.frontendServerSnapshotForEngineDartSdk:
case Artifact.icuData:
case Artifact.isolateSnapshotData:
case Artifact.linuxDesktopPath:
case Artifact.linuxHeaders:
case Artifact.platformLibrariesJson:
case Artifact.skyEnginePath:
case Artifact.vmSnapshotData:
case Artifact.windowsCppClientWrapper:
case Artifact.windowsDesktopPath:
case Artifact.flutterToolsFileGenerators:
case Artifact.flutterPreviewDevice:
return _getHostArtifactPath(artifact, platform, mode);
}
}
String _getFlutterPatchedSdkPath(BuildMode? mode) {
final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path;
return _fileSystem.path.join(engineArtifactsPath, 'common',
mode == BuildMode.release ? 'flutter_patched_sdk_product' : 'flutter_patched_sdk');
}
String _getFlutterWebSdkPath() {
return _cache.getWebSdkDirectory().path;
}
String _getHostArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode? mode) {
switch (artifact) {
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);
case Artifact.dart2jsSnapshot:
case Artifact.dart2wasmSnapshot:
case Artifact.frontendServerSnapshotForEngineDartSdk:
return _fileSystem.path.join(
_dartSdkPath(_cache), 'bin', 'snapshots',
_artifactToFileName(artifact, _platform),
);
case Artifact.wasmOptBinary:
return _fileSystem.path.join(
_dartSdkPath(_cache), 'bin', 'utils',
_artifactToFileName(artifact, _platform),
);
case Artifact.flutterTester:
case Artifact.vmSnapshotData:
case Artifact.isolateSnapshotData:
case Artifact.icuData:
final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path;
final String platformDirName = _enginePlatformDirectoryName(platform);
return _fileSystem.path.join(engineArtifactsPath, platformDirName, _artifactToFileName(artifact, _platform, mode));
case Artifact.platformKernelDill:
return _fileSystem.path.join(_getFlutterPatchedSdkPath(mode), _artifactToFileName(artifact, _platform));
case Artifact.platformLibrariesJson:
return _fileSystem.path.join(_getFlutterPatchedSdkPath(mode), 'lib', _artifactToFileName(artifact, _platform));
case Artifact.flutterPatchedSdkPath:
return _getFlutterPatchedSdkPath(mode);
case Artifact.engineDartSdkPath:
return _dartSdkPath(_cache);
case Artifact.engineDartBinary:
case Artifact.engineDartAotRuntime:
return _fileSystem.path.join(_dartSdkPath(_cache), 'bin', _artifactToFileName(artifact, _platform));
case Artifact.flutterMacOSFramework:
case Artifact.linuxDesktopPath:
case Artifact.windowsDesktopPath:
case Artifact.linuxHeaders:
// TODO(zanderso): remove once debug desktop artifacts are uploaded
// under a separate directory from the host artifacts.
// https://github.com/flutter/flutter/issues/38935
String platformDirName = _enginePlatformDirectoryName(platform);
if (mode == BuildMode.profile || mode == BuildMode.release) {
platformDirName = '$platformDirName-${mode!.cliName}';
}
final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path;
return _fileSystem.path.join(engineArtifactsPath, platformDirName, _artifactToFileName(artifact, _platform, mode));
case Artifact.windowsCppClientWrapper:
final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path;
return _fileSystem.path.join(engineArtifactsPath, 'windows-x64', _artifactToFileName(artifact, _platform, mode));
case Artifact.skyEnginePath:
final Directory dartPackageDirectory = _cache.getCacheDir('pkg');
return _fileSystem.path.join(dartPackageDirectory.path, _artifactToFileName(artifact, _platform));
case Artifact.fontSubset:
case Artifact.constFinder:
return _cache.getArtifactDirectory('engine')
.childDirectory(_enginePlatformDirectoryName(platform))
.childFile(_artifactToFileName(artifact, _platform, mode)!)
.path;
case Artifact.flutterFramework:
case Artifact.flutterXcframework:
case Artifact.fuchsiaFlutterRunner:
case Artifact.fuchsiaKernelCompiler:
throw StateError('Artifact $artifact not available for platform $platform.');
case Artifact.flutterToolsFileGenerators:
return _getFileGeneratorsPath();
case Artifact.flutterPreviewDevice:
assert(platform == TargetPlatform.windows_x64);
return _cache.getArtifactDirectory('flutter_preview').childFile('flutter_preview.exe').path;
}
}
String? _getEngineArtifactsPath(TargetPlatform platform, [ BuildMode? mode ]) {
final String engineDir = _cache.getArtifactDirectory('engine').path;
final String platformName = _enginePlatformDirectoryName(platform);
switch (platform) {
case TargetPlatform.linux_x64:
case TargetPlatform.linux_arm64:
case TargetPlatform.darwin:
case TargetPlatform.windows_x64:
// TODO(zanderso): remove once debug desktop artifacts are uploaded
// under a separate directory from the host artifacts.
// https://github.com/flutter/flutter/issues/38935
if (mode == BuildMode.debug || mode == null) {
return _fileSystem.path.join(engineDir, platformName);
}
final String suffix = mode != BuildMode.debug ? '-${snakeCase(mode.cliName, '-')}' : '';
return _fileSystem.path.join(engineDir, platformName + suffix);
case TargetPlatform.fuchsia_arm64:
case TargetPlatform.fuchsia_x64:
case TargetPlatform.tester:
case TargetPlatform.web_javascript:
assert(mode == null, 'Platform $platform does not support different build modes.');
return _fileSystem.path.join(engineDir, platformName);
case TargetPlatform.ios:
case TargetPlatform.android_arm:
case TargetPlatform.android_arm64:
case TargetPlatform.android_x64:
case TargetPlatform.android_x86:
assert(mode != null, 'Need to specify a build mode for platform $platform.');
final String suffix = mode != BuildMode.debug ? '-${snakeCase(mode!.cliName, '-')}' : '';
return _fileSystem.path.join(engineDir, platformName + suffix);
case TargetPlatform.android:
assert(false, 'cannot use TargetPlatform.android to look up artifacts');
return null;
}
}
@override
bool get isLocalEngine => false;
}
TargetPlatform _currentHostPlatform(Platform platform, OperatingSystemUtils operatingSystemUtils) {
if (platform.isMacOS) {
return TargetPlatform.darwin;
}
if (platform.isLinux) {
return operatingSystemUtils.hostPlatform == HostPlatform.linux_x64 ?
TargetPlatform.linux_x64 : TargetPlatform.linux_arm64;
}
if (platform.isWindows) {
return TargetPlatform.windows_x64;
}
throw UnimplementedError('Host OS not supported.');
}
String _getIosEngineArtifactPath(String engineDirectory,
EnvironmentType? environmentType, FileSystem fileSystem, Platform hostPlatform) {
final Directory xcframeworkDirectory = fileSystem
.directory(engineDirectory)
.childDirectory(_artifactToFileName(Artifact.flutterXcframework, hostPlatform)!);
if (!xcframeworkDirectory.existsSync()) {
throwToolExit('No xcframework found at ${xcframeworkDirectory.path}. Try running "flutter precache --ios".');
}
Directory? flutterFrameworkSource;
for (final Directory platformDirectory
in xcframeworkDirectory.listSync().whereType<Directory>()) {
if (!platformDirectory.basename.startsWith('ios-')) {
continue;
}
// ios-x86_64-simulator, ios-arm64_x86_64-simulator, or ios-arm64.
final bool simulatorDirectory = platformDirectory.basename.endsWith('-simulator');
if ((environmentType == EnvironmentType.simulator && simulatorDirectory) ||
(environmentType == EnvironmentType.physical && !simulatorDirectory)) {
flutterFrameworkSource = platformDirectory;
}
}
if (flutterFrameworkSource == null) {
throwToolExit('No iOS frameworks found in ${xcframeworkDirectory.path}');
}
return flutterFrameworkSource
.childDirectory(_artifactToFileName(Artifact.flutterFramework, hostPlatform)!)
.path;
}
/// Manages the artifacts of a locally built engine.
class CachedLocalEngineArtifacts implements Artifacts {
CachedLocalEngineArtifacts(
this._hostEngineOutPath, {
required String engineOutPath,
required FileSystem fileSystem,
required Cache cache,
required ProcessManager processManager,
required Platform platform,
required OperatingSystemUtils operatingSystemUtils,
Artifacts? parent,
}) : _fileSystem = fileSystem,
localEngineInfo =
LocalEngineInfo(
targetOutPath: engineOutPath,
hostOutPath: _hostEngineOutPath,
),
_cache = cache,
_processManager = processManager,
_platform = platform,
_operatingSystemUtils = operatingSystemUtils,
_backupCache = parent ??
CachedArtifacts(
fileSystem: fileSystem,
platform: platform,
cache: cache,
operatingSystemUtils: operatingSystemUtils
);
@override
final LocalEngineInfo localEngineInfo;
final String _hostEngineOutPath;
final FileSystem _fileSystem;
final Cache _cache;
final ProcessManager _processManager;
final Platform _platform;
final OperatingSystemUtils _operatingSystemUtils;
final Artifacts _backupCache;
@override
FileSystemEntity getHostArtifact(HostArtifact artifact) {
switch (artifact) {
case HostArtifact.flutterWebSdk:
final String path = _getFlutterWebSdkPath();
return _fileSystem.directory(path);
case HostArtifact.flutterWebLibrariesJson:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.flutterJsDirectory:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'flutter_js');
return _fileSystem.directory(path);
case HostArtifact.webPlatformKernelFolder:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel');
return _fileSystem.file(path);
case HostArtifact.webPlatformDDCKernelDill:
case HostArtifact.webPlatformDDCSoundKernelDill:
case HostArtifact.webPlatformDart2JSKernelDill:
case HostArtifact.webPlatformDart2JSSoundKernelDill:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledSdk:
case HostArtifact.webPrecompiledSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitSdk:
case HostArtifact.webPrecompiledCanvaskitSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-html', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledSoundSdk:
case HostArtifact.webPrecompiledSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitSoundSdk:
case HostArtifact.webPrecompiledCanvaskitSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-html-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.idevicesyslog:
case HostArtifact.idevicescreenshot:
final String artifactFileName = _hostArtifactToFileName(artifact, _platform);
return _cache.getArtifactDirectory('libimobiledevice').childFile(artifactFileName);
case HostArtifact.skyEnginePath:
final Directory dartPackageDirectory = _cache.getCacheDir('pkg');
final String path = _fileSystem.path.join(dartPackageDirectory.path, _hostArtifactToFileName(artifact, _platform));
return _fileSystem.directory(path);
case HostArtifact.iosDeploy:
final String artifactFileName = _hostArtifactToFileName(artifact, _platform);
return _cache.getArtifactDirectory('ios-deploy').childFile(artifactFileName);
case HostArtifact.iproxy:
final String artifactFileName = _hostArtifactToFileName(artifact, _platform);
return _cache.getArtifactDirectory('usbmuxd').childFile(artifactFileName);
case HostArtifact.impellerc:
case HostArtifact.scenec:
case HostArtifact.libtessellator:
final String artifactFileName = _hostArtifactToFileName(artifact, _platform);
final File file = _fileSystem.file(_fileSystem.path.join(_hostEngineOutPath, artifactFileName));
if (!file.existsSync()) {
return _backupCache.getHostArtifact(artifact);
}
return file;
}
}
@override
String getArtifactPath(
Artifact artifact, {
TargetPlatform? platform,
BuildMode? mode,
EnvironmentType? environmentType,
}) {
platform ??= _currentHostPlatform(_platform, _operatingSystemUtils);
platform = _mapTargetPlatform(platform);
final bool isDirectoryArtifact = artifact == Artifact.flutterPatchedSdkPath;
final String? artifactFileName = isDirectoryArtifact ? null : _artifactToFileName(artifact, _platform, mode);
switch (artifact) {
case Artifact.genSnapshot:
return _genSnapshotPath();
case Artifact.flutterTester:
return _flutterTesterPath(platform!);
case Artifact.isolateSnapshotData:
case Artifact.vmSnapshotData:
return _fileSystem.path.join(localEngineInfo.targetOutPath, 'gen', 'flutter', 'lib', 'snapshot', artifactFileName);
case Artifact.icuData:
case Artifact.flutterXcframework:
case Artifact.flutterMacOSFramework:
return _fileSystem.path.join(localEngineInfo.targetOutPath, artifactFileName);
case Artifact.platformKernelDill:
if (platform == TargetPlatform.fuchsia_x64 || platform == TargetPlatform.fuchsia_arm64) {
return _fileSystem.path.join(localEngineInfo.targetOutPath, 'flutter_runner_patched_sdk', artifactFileName);
}
return _fileSystem.path.join(_getFlutterPatchedSdkPath(mode), artifactFileName);
case Artifact.platformLibrariesJson:
return _fileSystem.path.join(_getFlutterPatchedSdkPath(mode), 'lib', artifactFileName);
case Artifact.flutterFramework:
return _getIosEngineArtifactPath(
localEngineInfo.targetOutPath, environmentType, _fileSystem, _platform);
case Artifact.flutterPatchedSdkPath:
// When using local engine always use [BuildMode.debug] regardless of
// what was specified in [mode] argument because local engine will
// have only one flutter_patched_sdk in standard location, that
// is happen to be what debug(non-release) mode is using.
if (platform == TargetPlatform.fuchsia_x64 || platform == TargetPlatform.fuchsia_arm64) {
return _fileSystem.path.join(localEngineInfo.targetOutPath, 'flutter_runner_patched_sdk');
}
return _getFlutterPatchedSdkPath(BuildMode.debug);
case Artifact.skyEnginePath:
return _fileSystem.path.join(_hostEngineOutPath, 'gen', 'dart-pkg', artifactFileName);
case Artifact.fuchsiaKernelCompiler:
final String hostPlatform = getNameForHostPlatform(getCurrentHostPlatform());
final String modeName = mode!.isRelease ? 'release' : mode.toString();
final String dartBinaries = 'dart_binaries-$modeName-$hostPlatform';
return _fileSystem.path.join(localEngineInfo.targetOutPath, 'host_bundle', dartBinaries, 'kernel_compiler.dart.snapshot');
case Artifact.fuchsiaFlutterRunner:
final String jitOrAot = mode!.isJit ? '_jit' : '_aot';
final String productOrNo = mode.isRelease ? '_product' : '';
return _fileSystem.path.join(localEngineInfo.targetOutPath, 'flutter$jitOrAot${productOrNo}_runner-0.far');
case Artifact.fontSubset:
return _fileSystem.path.join(_hostEngineOutPath, artifactFileName);
case Artifact.constFinder:
return _fileSystem.path.join(_hostEngineOutPath, 'gen', artifactFileName);
case Artifact.linuxDesktopPath:
case Artifact.linuxHeaders:
case Artifact.windowsDesktopPath:
case Artifact.windowsCppClientWrapper:
return _fileSystem.path.join(_hostEngineOutPath, artifactFileName);
case Artifact.engineDartSdkPath:
return _getDartSdkPath();
case Artifact.engineDartBinary:
case Artifact.engineDartAotRuntime:
return _fileSystem.path.join(_getDartSdkPath(), 'bin', artifactFileName);
case Artifact.dart2jsSnapshot:
case Artifact.dart2wasmSnapshot:
case Artifact.frontendServerSnapshotForEngineDartSdk:
return _fileSystem.path.join(_getDartSdkPath(), 'bin', 'snapshots', artifactFileName);
case Artifact.wasmOptBinary:
return _fileSystem.path.join(_getDartSdkPath(), 'bin', 'utils', artifactFileName);
case Artifact.flutterToolsFileGenerators:
return _getFileGeneratorsPath();
case Artifact.flutterPreviewDevice:
return _backupCache.getArtifactPath(
artifact,
platform: platform,
mode: mode,
environmentType: environmentType,
);
}
}
@override
String getEngineType(TargetPlatform platform, [ BuildMode? mode ]) {
return _fileSystem.path.basename(localEngineInfo.targetOutPath);
}
String _getFlutterPatchedSdkPath(BuildMode? buildMode) {
return _fileSystem.path.join(localEngineInfo.targetOutPath,
buildMode == BuildMode.release ? 'flutter_patched_sdk_product' : 'flutter_patched_sdk');
}
String _getDartSdkPath() {
final String builtPath = _fileSystem.path.join(_hostEngineOutPath, 'dart-sdk');
if (_fileSystem.isDirectorySync(_fileSystem.path.join(builtPath, 'bin'))) {
return builtPath;
}
// If we couldn't find a built dart sdk, let's look for a prebuilt one.
final String prebuiltPath = _fileSystem.path.join(_getFlutterPrebuiltsPath(), _getPrebuiltTarget(), 'dart-sdk');
if (_fileSystem.isDirectorySync(prebuiltPath)) {
return prebuiltPath;
}
throw ToolExit('Unable to find a built dart sdk at: "$builtPath" or a prebuilt dart sdk at: "$prebuiltPath"');
}
String _getFlutterPrebuiltsPath() {
final String engineSrcPath = _fileSystem.path.dirname(_fileSystem.path.dirname(_hostEngineOutPath));
return _fileSystem.path.join(engineSrcPath, 'flutter', 'prebuilts');
}
String _getPrebuiltTarget() {
final TargetPlatform hostPlatform = _currentHostPlatform(_platform, _operatingSystemUtils);
switch (hostPlatform) {
case TargetPlatform.darwin:
return 'macos-x64';
case TargetPlatform.linux_arm64:
return 'linux-arm64';
case TargetPlatform.linux_x64:
return 'linux-x64';
case TargetPlatform.windows_x64:
return 'windows-x64';
case TargetPlatform.ios:
case TargetPlatform.android:
case TargetPlatform.android_arm:
case TargetPlatform.android_arm64:
case TargetPlatform.android_x64:
case TargetPlatform.android_x86:
case TargetPlatform.fuchsia_arm64:
case TargetPlatform.fuchsia_x64:
case TargetPlatform.web_javascript:
case TargetPlatform.tester:
throwToolExit('Unsupported host platform: $hostPlatform');
}
}
String _getFlutterWebSdkPath() {
return _fileSystem.path.join(localEngineInfo.targetOutPath, 'flutter_web_sdk');
}
String _genSnapshotPath() {
const List<String> clangDirs = <String>['.', 'clang_x64', 'clang_x86', 'clang_i386', 'clang_arm64'];
final String genSnapshotName = _artifactToFileName(Artifact.genSnapshot, _platform)!;
for (final String clangDir in clangDirs) {
final String genSnapshotPath = _fileSystem.path.join(localEngineInfo.targetOutPath, clangDir, genSnapshotName);
if (_processManager.canRun(genSnapshotPath)) {
return genSnapshotPath;
}
}
throw Exception('Unable to find $genSnapshotName');
}
String _flutterTesterPath(TargetPlatform platform) {
if (_platform.isLinux) {
return _fileSystem.path.join(localEngineInfo.targetOutPath, _artifactToFileName(Artifact.flutterTester, _platform));
} else if (_platform.isMacOS) {
return _fileSystem.path.join(localEngineInfo.targetOutPath, 'flutter_tester');
} else if (_platform.isWindows) {
return _fileSystem.path.join(localEngineInfo.targetOutPath, 'flutter_tester.exe');
}
throw Exception('Unsupported platform $platform.');
}
@override
bool get isLocalEngine => true;
}
class CachedLocalWebSdkArtifacts implements Artifacts {
CachedLocalWebSdkArtifacts({
required Artifacts parent,
required String webSdkPath,
required FileSystem fileSystem,
required Platform platform,
required OperatingSystemUtils operatingSystemUtils
}) : _parent = parent,
_webSdkPath = webSdkPath,
_fileSystem = fileSystem,
_platform = platform,
_operatingSystemUtils = operatingSystemUtils;
final Artifacts _parent;
final String _webSdkPath;
final FileSystem _fileSystem;
final Platform _platform;
final OperatingSystemUtils _operatingSystemUtils;
@override
String getArtifactPath(Artifact artifact, {TargetPlatform? platform, BuildMode? mode, EnvironmentType? environmentType}) {
if (platform == TargetPlatform.web_javascript) {
switch (artifact) {
case Artifact.engineDartSdkPath:
return _getDartSdkPath();
case Artifact.engineDartBinary:
case Artifact.engineDartAotRuntime:
return _fileSystem.path.join(
_getDartSdkPath(), 'bin',
_artifactToFileName(artifact, _platform, mode));
case Artifact.dart2jsSnapshot:
case Artifact.dart2wasmSnapshot:
case Artifact.frontendServerSnapshotForEngineDartSdk:
return _fileSystem.path.join(
_getDartSdkPath(), 'bin', 'snapshots',
_artifactToFileName(artifact, _platform, mode),
);
case Artifact.wasmOptBinary:
return _fileSystem.path.join(
_getDartSdkPath(), 'bin', 'utils',
_artifactToFileName(artifact, _platform, mode),
);
case Artifact.genSnapshot:
case Artifact.flutterTester:
case Artifact.flutterFramework:
case Artifact.flutterXcframework:
case Artifact.flutterMacOSFramework:
case Artifact.vmSnapshotData:
case Artifact.isolateSnapshotData:
case Artifact.icuData:
case Artifact.platformKernelDill:
case Artifact.platformLibrariesJson:
case Artifact.flutterPatchedSdkPath:
case Artifact.linuxDesktopPath:
case Artifact.linuxHeaders:
case Artifact.windowsDesktopPath:
case Artifact.windowsCppClientWrapper:
case Artifact.skyEnginePath:
case Artifact.fuchsiaKernelCompiler:
case Artifact.fuchsiaFlutterRunner:
case Artifact.fontSubset:
case Artifact.constFinder:
case Artifact.flutterToolsFileGenerators:
case Artifact.flutterPreviewDevice:
break;
}
}
return _parent.getArtifactPath(artifact, platform: platform, mode: mode, environmentType: environmentType);
}
@override
String getEngineType(TargetPlatform platform, [BuildMode? mode]) => _parent.getEngineType(platform, mode);
@override
FileSystemEntity getHostArtifact(HostArtifact artifact) {
switch (artifact) {
case HostArtifact.flutterWebSdk:
final String path = _getFlutterWebSdkPath();
return _fileSystem.directory(path);
case HostArtifact.flutterWebLibrariesJson:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.flutterJsDirectory:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'flutter_js');
return _fileSystem.directory(path);
case HostArtifact.webPlatformKernelFolder:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel');
return _fileSystem.file(path);
case HostArtifact.webPlatformDDCKernelDill:
case HostArtifact.webPlatformDDCSoundKernelDill:
case HostArtifact.webPlatformDart2JSKernelDill:
case HostArtifact.webPlatformDart2JSSoundKernelDill:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledSdk:
case HostArtifact.webPrecompiledSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitSdk:
case HostArtifact.webPrecompiledCanvaskitSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-html', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledSoundSdk:
case HostArtifact.webPrecompiledSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitSoundSdk:
case HostArtifact.webPrecompiledCanvaskitSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdk:
case HostArtifact.webPrecompiledCanvaskitAndHtmlSoundSdkSourcemaps:
final String path = _fileSystem.path.join(_getFlutterWebSdkPath(), 'kernel', 'amd-canvaskit-html-sound', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.iosDeploy:
case HostArtifact.idevicesyslog:
case HostArtifact.idevicescreenshot:
case HostArtifact.iproxy:
case HostArtifact.skyEnginePath:
case HostArtifact.impellerc:
case HostArtifact.scenec:
case HostArtifact.libtessellator:
return _parent.getHostArtifact(artifact);
}
}
String _getDartSdkPath() {
// If we couldn't find a built dart sdk, let's look for a prebuilt one.
final String prebuiltPath = _fileSystem.path.join(_getFlutterPrebuiltsPath(), _getPrebuiltTarget(), 'dart-sdk');
if (_fileSystem.isDirectorySync(prebuiltPath)) {
return prebuiltPath;
}
throw ToolExit('Unable to find a prebuilt dart sdk at: "$prebuiltPath"');
}
String _getFlutterPrebuiltsPath() {
final String engineSrcPath = _fileSystem.path.dirname(_fileSystem.path.dirname(_webSdkPath));
return _fileSystem.path.join(engineSrcPath, 'flutter', 'prebuilts');
}
String _getPrebuiltTarget() {
final TargetPlatform hostPlatform = _currentHostPlatform(_platform, _operatingSystemUtils);
switch (hostPlatform) {
case TargetPlatform.darwin:
return 'macos-x64';
case TargetPlatform.linux_arm64:
return 'linux-arm64';
case TargetPlatform.linux_x64:
return 'linux-x64';
case TargetPlatform.windows_x64:
return 'windows-x64';
case TargetPlatform.ios:
case TargetPlatform.android:
case TargetPlatform.android_arm:
case TargetPlatform.android_arm64:
case TargetPlatform.android_x64:
case TargetPlatform.android_x86:
case TargetPlatform.fuchsia_arm64:
case TargetPlatform.fuchsia_x64:
case TargetPlatform.web_javascript:
case TargetPlatform.tester:
throwToolExit('Unsupported host platform: $hostPlatform');
}
}
String _getFlutterWebSdkPath() {
return _fileSystem.path.join(_webSdkPath, 'flutter_web_sdk');
}
@override
bool get isLocalEngine => _parent.isLocalEngine;
@override
LocalEngineInfo? get localEngineInfo => _parent.localEngineInfo;
}
/// An implementation of [Artifacts] that provides individual overrides.
///
/// If an artifact is not provided, the lookup delegates to the parent.
class OverrideArtifacts implements Artifacts {
/// Creates a new [OverrideArtifacts].
///
/// [parent] must be provided.
OverrideArtifacts({
required this.parent,
this.frontendServer,
this.engineDartBinary,
this.platformKernelDill,
this.flutterPatchedSdk,
});
final Artifacts parent;
final File? frontendServer;
final File? engineDartBinary;
final File? platformKernelDill;
final File? flutterPatchedSdk;
@override
LocalEngineInfo? get localEngineInfo => parent.localEngineInfo;
@override
String getArtifactPath(
Artifact artifact, {
TargetPlatform? platform,
BuildMode? mode,
EnvironmentType? environmentType,
}) {
if (artifact == Artifact.engineDartBinary && engineDartBinary != null) {
return engineDartBinary!.path;
}
if (artifact == Artifact.frontendServerSnapshotForEngineDartSdk && frontendServer != null) {
return frontendServer!.path;
}
if (artifact == Artifact.platformKernelDill && platformKernelDill != null) {
return platformKernelDill!.path;
}
if (artifact == Artifact.flutterPatchedSdkPath && flutterPatchedSdk != null) {
return flutterPatchedSdk!.path;
}
return parent.getArtifactPath(
artifact,
platform: platform,
mode: mode,
environmentType: environmentType,
);
}
@override
String getEngineType(TargetPlatform platform, [ BuildMode? mode ]) => parent.getEngineType(platform, mode);
@override
bool get isLocalEngine => parent.isLocalEngine;
@override
FileSystemEntity getHostArtifact(HostArtifact artifact) {
return parent.getHostArtifact(
artifact,
);
}
}
/// Locate the Dart SDK.
String _dartSdkPath(Cache cache) {
return cache.getRoot().childDirectory('dart-sdk').path;
}
class _TestArtifacts implements Artifacts {
_TestArtifacts(this.fileSystem);
final FileSystem fileSystem;
@override
LocalEngineInfo? get localEngineInfo => null;
@override
String getArtifactPath(
Artifact artifact, {
TargetPlatform? platform,
BuildMode? mode,
EnvironmentType? environmentType,
}) {
// The path to file generators is the same even in the test environment.
if (artifact == Artifact.flutterToolsFileGenerators) {
return _getFileGeneratorsPath();
}
final StringBuffer buffer = StringBuffer();
buffer.write(artifact);
if (platform != null) {
buffer.write('.$platform');
}
if (mode != null) {
buffer.write('.$mode');
}
if (environmentType != null) {
buffer.write('.$environmentType');
}
return buffer.toString();
}
@override
String getEngineType(TargetPlatform platform, [ BuildMode? mode ]) {
return 'test-engine';
}
@override
bool get isLocalEngine => false;
@override
FileSystemEntity getHostArtifact(HostArtifact artifact) {
return fileSystem.file(artifact.toString());
}
}
class _TestLocalEngine extends _TestArtifacts {
_TestLocalEngine(
String engineOutPath,
String engineHostOutPath,
super.fileSystem,
) : localEngineInfo = LocalEngineInfo(
targetOutPath: engineOutPath,
hostOutPath: engineHostOutPath,
);
@override
bool get isLocalEngine => true;
@override
final LocalEngineInfo localEngineInfo;
}
String _getFileGeneratorsPath() {
final String flutterRoot = Cache.defaultFlutterRoot(
fileSystem: globals.localFileSystem,
platform: const LocalPlatform(),
userMessages: UserMessages(),
);
return globals.localFileSystem.path.join(
flutterRoot,
'packages',
'flutter_tools',
'lib',
'src',
'web',
'file_generators',
);
}