| // 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; | |
| ////////////////////////////////////////////////////////////////////// | |
| // // | |
| // ✨ THINKING OF MOVING/REFACTORING THIS FILE? READ ME FIRST! ✨ // | |
| // // | |
| // There is a link to this file in //docs/tool/Engine-artfiacts.md // | |
| // and it would be very kind of you to update the link, if needed. // | |
| // // | |
| ////////////////////////////////////////////////////////////////////// | |
| /// Defines what engine artifacts are available (not necessarily on each platform). | |
| enum Artifact { | |
| /// The tool which compiles a dart kernel file into native code. | |
| genSnapshot('gen_snapshot'), | |
| genSnapshotArm64('gen_snapshot_arm64'), | |
| genSnapshotRiscv64('gen_snapshot_riscv64'), | |
| genSnapshotX64('gen_snapshot_x64'), | |
| /// The flutter tester binary. | |
| flutterTester('flutter_tester', isExecutable: true), | |
| flutterFramework('Flutter.framework'), | |
| flutterFrameworkDsym('Flutter.framework.dSYM'), | |
| flutterXcframework('Flutter.xcframework'), | |
| /// The framework directory of the macOS desktop. | |
| flutterMacOSFramework('FlutterMacOS.framework'), | |
| flutterMacOSFrameworkDsym('FlutterMacOS.framework.dSYM'), | |
| flutterMacOSXcframework('FlutterMacOS.xcframework'), | |
| vmSnapshotData('vm_isolate_snapshot.bin'), | |
| isolateSnapshotData('isolate_snapshot.bin'), | |
| icuData('icudtl.dat'), | |
| platformKernelDill('platform_strong.dill'), | |
| platformLibrariesJson('libraries.json'), | |
| flutterPatchedSdkPath('', isPatchedSdk: true), | |
| /// The root directory of the dart SDK. | |
| engineDartSdkPath('dart-sdk'), | |
| /// The dart binary used to execute any of the required snapshots. | |
| engineDartBinary('dart', isExecutable: true), | |
| /// The dart binary for running aot snapshots | |
| engineDartAotRuntime('dartaotruntime', isExecutable: true), | |
| /// The snapshot of frontend_server compiler. | |
| frontendServerSnapshotForEngineDartSdk('frontend_server_aot.dart.snapshot'), | |
| /// The root of the Linux desktop sources. | |
| linuxDesktopPath.directory(), | |
| // The root of the cpp headers for Linux desktop. | |
| linuxHeaders('flutter_linux'), | |
| /// The root of the Windows desktop sources. | |
| windowsDesktopPath.directory(), | |
| /// The root of the cpp client code for Windows desktop. | |
| windowsCppClientWrapper('cpp_client_wrapper'), | |
| /// The root of the sky_engine package. | |
| skyEnginePath('sky_engine'), | |
| // Fuchsia artifacts from the engine prebuilts. | |
| fuchsiaKernelCompiler('kernel_compiler.snapshot'), | |
| fuchsiaFlutterRunner('', isFuchsiaRunner: true), | |
| /// Tools related to subsetting or icon font files. | |
| fontSubset('font-subset', isExecutable: true), | |
| /// The location of file generators. | |
| flutterToolsFileGenerators.directory(); | |
| const Artifact( | |
| this._fileName, { | |
| this.isExecutable = false, | |
| this.isPatchedSdk = false, | |
| this.isFuchsiaRunner = false, | |
| }); | |
| const Artifact.directory() | |
| : _fileName = '', | |
| isExecutable = false, | |
| isPatchedSdk = false, | |
| isFuchsiaRunner = false; | |
| final String _fileName; | |
| final bool isExecutable; | |
| final bool isPatchedSdk; | |
| final bool isFuchsiaRunner; | |
| String getFileName(Platform hostPlatform, [BuildMode? mode]) { | |
| if (isPatchedSdk) { | |
| throw StateError('No filename for sdk path, should not be invoked'); | |
| } | |
| if (isFuchsiaRunner) { | |
| if (mode == null) { | |
| throw ArgumentError('BuildMode is required for fuchsiaFlutterRunner'); | |
| } | |
| final jitOrAot = mode.isJit ? '_jit' : '_aot'; | |
| final productOrNo = mode.isRelease ? '_product' : ''; | |
| return 'flutter$jitOrAot${productOrNo}_runner-0.far'; | |
| } | |
| final exe = (isExecutable && hostPlatform.isWindows) ? '.exe' : ''; | |
| return '$_fileName$exe'; | |
| } | |
| } | |
| /// 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.directory(), | |
| /// The libraries JSON file for web release builds. | |
| flutterWebLibrariesJson('libraries.json'), | |
| // The flutter.js bootstrapping file provided by the engine. | |
| flutterJsDirectory('flutter_js'), | |
| /// Folder that contains platform dill files for the web sdk. | |
| webPlatformKernelFolder('kernel'), | |
| // **NOTE**: All of the precompiled SDKs, summaries, and source maps are | |
| // strictly with sound null-safety, there is no longer support for unsound | |
| // null-safety within the Flutter tool or SDK. | |
| // | |
| // See https://github.com/flutter/flutter/issues/162846. | |
| /// The summary dill for the dartdevc target. | |
| webPlatformDDCKernelDill('ddc_outline.dill'), | |
| /// The summary dill for the dart2js target. | |
| webPlatformDart2JSKernelDill('dart2js_platform.dill'), | |
| /// The precompiled SDKs and sourcemaps for web debug builds with the AMD module system. | |
| // TODO(markzipan): delete these when DDC's AMD module system is deprecated, https://github.com/flutter/flutter/issues/142060. | |
| webPrecompiledAmdCanvaskitSdk('dart_sdk.js'), | |
| webPrecompiledAmdCanvaskitSdkSourcemaps('dart_sdk.js.map'), | |
| /// The precompiled SDKs and sourcemaps for web debug builds with the DDC | |
| /// library bundle module system. Only SDKs built with sound null-safety are | |
| /// provided here. | |
| webPrecompiledDdcLibraryBundleCanvaskitSdk('dart_sdk.js'), | |
| webPrecompiledDdcLibraryBundleCanvaskitSdkSourcemaps('dart_sdk.js.map'), | |
| iosDeploy('ios-deploy'), | |
| idevicesyslog('idevicesyslog'), | |
| iproxy('iproxy'), | |
| idevicescreenshot('idevicescreenshot'), | |
| /// The root of the sky_engine package. | |
| skyEnginePath('sky_engine'), | |
| // The Impeller shader compiler. | |
| impellerc('impellerc', isExecutable: true), | |
| // Impeller's tessellation library. | |
| libtessellator('libtessellator', isDll: true); | |
| const HostArtifact(this._fileName, {this.isExecutable = false, this.isDll = false}); | |
| const HostArtifact.directory() : _fileName = '', isExecutable = false, isDll = false; | |
| final String _fileName; | |
| final bool isExecutable; | |
| final bool isDll; | |
| String getFileName(Platform platform) { | |
| if (isDll) { | |
| var dll = '.so'; | |
| if (platform.isWindows) { | |
| dll = '.dll'; | |
| } else if (platform.isMacOS) { | |
| dll = '.dylib'; | |
| } | |
| return '$_fileName$dll'; | |
| } | |
| final exe = (isExecutable && platform.isWindows) ? '.exe' : ''; | |
| return '$_fileName$exe'; | |
| } | |
| } | |
| // 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 platform.getName(); | |
| } | |
| // 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.linux_riscv64: | |
| case TargetPlatform.windows_x64: | |
| case TargetPlatform.windows_arm64: | |
| 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.unsupported: | |
| case null: | |
| return targetPlatform; | |
| } | |
| } | |
| 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/blob/main/docs/tool/README.md#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. | |
| @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 use any locally built files that are not part of | |
| /// a versioned engine. | |
| bool get usesLocalArtifacts; | |
| /// 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: | |
| case HostArtifact.flutterWebLibrariesJson: | |
| case HostArtifact.flutterJsDirectory: | |
| case HostArtifact.webPlatformKernelFolder: | |
| case HostArtifact.webPlatformDDCKernelDill: | |
| case HostArtifact.webPlatformDart2JSKernelDill: | |
| case HostArtifact.webPrecompiledAmdCanvaskitSdk: | |
| case HostArtifact.webPrecompiledAmdCanvaskitSdkSourcemaps: | |
| case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSdk: | |
| case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSdkSourcemaps: | |
| return _resolveWebArtifact(artifact, _getFlutterWebSdkPath(), _fileSystem, _platform); | |
| case HostArtifact.idevicesyslog: | |
| case HostArtifact.idevicescreenshot: | |
| final String artifactFileName = artifact.getFileName(_platform); | |
| return _cache.getArtifactDirectory('libimobiledevice').childFile(artifactFileName); | |
| case HostArtifact.skyEnginePath: | |
| final Directory dartPackageDirectory = _cache.getCacheDir('pkg'); | |
| final String path = _fileSystem.path.join( | |
| dartPackageDirectory.path, | |
| artifact.getFileName(_platform), | |
| ); | |
| return _fileSystem.directory(path); | |
| case HostArtifact.iosDeploy: | |
| final String artifactFileName = artifact.getFileName(_platform); | |
| return _cache.getArtifactDirectory('ios-deploy').childFile(artifactFileName); | |
| case HostArtifact.iproxy: | |
| final String artifactFileName = artifact.getFileName(_platform); | |
| return _cache.getArtifactDirectory('libusbmuxd').childFile(artifactFileName); | |
| case HostArtifact.impellerc: | |
| case HostArtifact.libtessellator: | |
| final String artifactFileName = artifact.getFileName(_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: | |
| 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.linux_riscv64: | |
| case TargetPlatform.windows_x64: | |
| case TargetPlatform.windows_arm64: | |
| 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, | |
| ); | |
| case TargetPlatform.unsupported: | |
| TargetPlatform.throwUnsupportedTarget(); | |
| } | |
| } | |
| @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. | |
| final String engineDir = _getEngineArtifactsPath(platform, mode)!; | |
| switch (artifact) { | |
| case Artifact.genSnapshot: | |
| case Artifact.genSnapshotArm64: | |
| case Artifact.genSnapshotRiscv64: | |
| case Artifact.genSnapshotX64: | |
| return _fileSystem.path.join(engineDir, artifact.getFileName(_platform)); | |
| case Artifact.engineDartSdkPath: | |
| case Artifact.engineDartBinary: | |
| case Artifact.engineDartAotRuntime: | |
| case Artifact.frontendServerSnapshotForEngineDartSdk: | |
| case Artifact.flutterFramework: | |
| case Artifact.flutterFrameworkDsym: | |
| case Artifact.flutterMacOSFramework: | |
| return _getMacOSFrameworkPath(engineDir, _fileSystem, _platform); | |
| case Artifact.flutterMacOSFrameworkDsym: | |
| return _getMacOSFrameworkDsymPath(engineDir, _fileSystem, _platform); | |
| case Artifact.flutterMacOSXcframework: | |
| 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: | |
| return _getHostArtifactPath(artifact, platform, mode); | |
| } | |
| } | |
| String _getAndroidArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) { | |
| final String engineDir = _getEngineArtifactsPath(platform, mode)!; | |
| switch (artifact) { | |
| case Artifact.genSnapshot: | |
| case Artifact.genSnapshotArm64: | |
| case Artifact.genSnapshotRiscv64: | |
| case Artifact.genSnapshotX64: | |
| assert(mode != BuildMode.debug, 'Artifact $artifact only available in non-debug mode.'); | |
| // TODO(cbracken): Build Android gen_snapshot as Arm64 binary to run | |
| // natively on Apple Silicon. See: | |
| // https://github.com/flutter/flutter/issues/152281 | |
| HostPlatform hostPlatform = getCurrentHostPlatform(); | |
| if (hostPlatform == HostPlatform.darwin_arm64) { | |
| hostPlatform = HostPlatform.darwin_x64; | |
| } | |
| final String hostPlatformName = hostPlatform.cliName; | |
| return _fileSystem.path.join(engineDir, hostPlatformName, artifact.getFileName(_platform)); | |
| case Artifact.engineDartSdkPath: | |
| case Artifact.engineDartBinary: | |
| case Artifact.engineDartAotRuntime: | |
| case Artifact.frontendServerSnapshotForEngineDartSdk: | |
| case Artifact.flutterFramework: | |
| case Artifact.flutterFrameworkDsym: | |
| case Artifact.flutterMacOSFramework: | |
| case Artifact.flutterMacOSFrameworkDsym: | |
| case Artifact.flutterMacOSXcframework: | |
| 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: | |
| return _getHostArtifactPath(artifact, platform, mode); | |
| } | |
| } | |
| String _getIosArtifactPath( | |
| Artifact artifact, | |
| TargetPlatform platform, | |
| BuildMode? mode, | |
| EnvironmentType? environmentType, | |
| ) { | |
| switch (artifact) { | |
| case Artifact.genSnapshot: | |
| case Artifact.genSnapshotArm64: | |
| case Artifact.genSnapshotRiscv64: | |
| case Artifact.genSnapshotX64: | |
| case Artifact.flutterXcframework: | |
| final String artifactFileName = artifact.getFileName(_platform); | |
| final String engineDir = _getEngineArtifactsPath(platform, mode)!; | |
| return _fileSystem.path.join(engineDir, artifactFileName); | |
| case Artifact.flutterFramework: | |
| final String engineDir = _getEngineArtifactsPath(platform, mode)!; | |
| return _getIosFrameworkPath(engineDir, environmentType, _fileSystem, _platform); | |
| case Artifact.flutterFrameworkDsym: | |
| final String engineDir = _getEngineArtifactsPath(platform, mode)!; | |
| return _getIosFrameworkDsymPath(engineDir, environmentType, _fileSystem, _platform); | |
| case Artifact.engineDartSdkPath: | |
| case Artifact.engineDartBinary: | |
| case Artifact.engineDartAotRuntime: | |
| case Artifact.frontendServerSnapshotForEngineDartSdk: | |
| case Artifact.flutterMacOSFramework: | |
| case Artifact.flutterMacOSFrameworkDsym: | |
| case Artifact.flutterMacOSXcframework: | |
| 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: | |
| 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 runtime = mode.isJit ? 'jit' : 'aot'; | |
| switch (artifact) { | |
| case Artifact.genSnapshot: | |
| final genSnapshot = mode.isRelease ? 'gen_snapshot_product' : 'gen_snapshot'; | |
| return _fileSystem.path.join(root, runtime, 'dart_binaries', genSnapshot); | |
| case Artifact.genSnapshotArm64: | |
| case Artifact.genSnapshotRiscv64: | |
| case Artifact.genSnapshotX64: | |
| throw ArgumentError('$artifact is not available on this platform'); | |
| case Artifact.flutterPatchedSdkPath: | |
| const artifactFileName = 'flutter_runner_patched_sdk'; | |
| return _fileSystem.path.join(root, runtime, artifactFileName); | |
| case Artifact.platformKernelDill: | |
| final String artifactFileName = artifact.getFileName(_platform, mode); | |
| return _fileSystem.path.join(root, runtime, 'flutter_runner_patched_sdk', artifactFileName); | |
| case Artifact.fuchsiaKernelCompiler: | |
| final String artifactFileName = artifact.getFileName(_platform, mode); | |
| return _fileSystem.path.join(root, runtime, 'dart_binaries', artifactFileName); | |
| case Artifact.fuchsiaFlutterRunner: | |
| final String artifactFileName = artifact.getFileName(_platform, mode); | |
| return _fileSystem.path.join(root, runtime, artifactFileName); | |
| case Artifact.flutterFramework: | |
| case Artifact.flutterFrameworkDsym: | |
| case Artifact.flutterMacOSFramework: | |
| case Artifact.flutterMacOSFrameworkDsym: | |
| case Artifact.flutterMacOSXcframework: | |
| case Artifact.flutterTester: | |
| case Artifact.flutterXcframework: | |
| case Artifact.fontSubset: | |
| case Artifact.engineDartSdkPath: | |
| case Artifact.engineDartBinary: | |
| case Artifact.engineDartAotRuntime: | |
| 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: | |
| 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: | |
| case Artifact.genSnapshotArm64: | |
| case Artifact.genSnapshotRiscv64: | |
| case Artifact.genSnapshotX64: | |
| // 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.frontendServerSnapshotForEngineDartSdk: | |
| return _fileSystem.path.join( | |
| _dartSdkPath(_cache), | |
| 'bin', | |
| 'snapshots', | |
| artifact.getFileName(_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, | |
| artifact.getFileName(_platform, mode), | |
| ); | |
| case Artifact.platformKernelDill: | |
| return _fileSystem.path.join( | |
| _getFlutterPatchedSdkPath(mode), | |
| artifact.getFileName(_platform), | |
| ); | |
| case Artifact.platformLibrariesJson: | |
| return _fileSystem.path.join( | |
| _getFlutterPatchedSdkPath(mode), | |
| 'lib', | |
| artifact.getFileName(_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', artifact.getFileName(_platform)); | |
| case Artifact.flutterMacOSFramework: | |
| String platformDirName = _enginePlatformDirectoryName(platform); | |
| if (mode == BuildMode.profile || mode == BuildMode.release) { | |
| platformDirName = '$platformDirName-${mode!.cliName}'; | |
| } | |
| final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path; | |
| return _getMacOSFrameworkPath( | |
| _fileSystem.path.join(engineArtifactsPath, platformDirName), | |
| _fileSystem, | |
| _platform, | |
| ); | |
| case Artifact.flutterMacOSFrameworkDsym: | |
| String platformDirName = _enginePlatformDirectoryName(platform); | |
| if (mode == BuildMode.profile || mode == BuildMode.release) { | |
| platformDirName = '$platformDirName-${mode!.cliName}'; | |
| } | |
| final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path; | |
| return _getMacOSFrameworkDsymPath( | |
| _fileSystem.path.join(engineArtifactsPath, platformDirName), | |
| _fileSystem, | |
| _platform, | |
| ); | |
| case Artifact.flutterMacOSXcframework: | |
| 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, | |
| artifact.getFileName(_platform, mode), | |
| ); | |
| case Artifact.windowsCppClientWrapper: | |
| final String platformDirName = _enginePlatformDirectoryName(platform); | |
| final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path; | |
| return _fileSystem.path.join( | |
| engineArtifactsPath, | |
| platformDirName, | |
| artifact.getFileName(_platform, mode), | |
| ); | |
| case Artifact.skyEnginePath: | |
| final Directory dartPackageDirectory = _cache.getCacheDir('pkg'); | |
| return _fileSystem.path.join(dartPackageDirectory.path, artifact.getFileName(_platform)); | |
| case Artifact.fontSubset: | |
| return _cache | |
| .getArtifactDirectory('engine') | |
| .childDirectory(_enginePlatformDirectoryName(platform)) | |
| .childFile(artifact.getFileName(_platform, mode)) | |
| .path; | |
| case Artifact.flutterFramework: | |
| case Artifact.flutterFrameworkDsym: | |
| case Artifact.flutterXcframework: | |
| case Artifact.fuchsiaFlutterRunner: | |
| case Artifact.fuchsiaKernelCompiler: | |
| throw StateError('Artifact $artifact not available for platform $platform.'); | |
| case Artifact.flutterToolsFileGenerators: | |
| return _getFileGeneratorsPath(); | |
| } | |
| } | |
| 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.linux_riscv64: | |
| case TargetPlatform.darwin: | |
| case TargetPlatform.windows_x64: | |
| case TargetPlatform.windows_arm64: | |
| // 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 suffix = mode != BuildMode.debug ? '-${kebabCase(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: | |
| assert(mode != null, 'Need to specify a build mode for platform $platform.'); | |
| final suffix = mode != BuildMode.debug ? '-${kebabCase(mode!.cliName)}' : ''; | |
| return _fileSystem.path.join(engineDir, platformName + suffix); | |
| case TargetPlatform.android: | |
| assert(false, 'cannot use TargetPlatform.android to look up artifacts'); | |
| return null; | |
| case TargetPlatform.unsupported: | |
| TargetPlatform.throwUnsupportedTarget(); | |
| } | |
| } | |
| @override | |
| bool get usesLocalArtifacts => false; | |
| } | |
| TargetPlatform _currentHostPlatform(Platform platform, OperatingSystemUtils operatingSystemUtils) { | |
| if (platform.isMacOS) { | |
| return TargetPlatform.darwin; | |
| } | |
| if (platform.isLinux) { | |
| return switch (operatingSystemUtils.hostPlatform) { | |
| HostPlatform.linux_x64 => TargetPlatform.linux_x64, | |
| HostPlatform.linux_riscv64 => TargetPlatform.linux_riscv64, | |
| _ => TargetPlatform.linux_arm64, | |
| }; | |
| } | |
| if (platform.isWindows) { | |
| return operatingSystemUtils.hostPlatform == HostPlatform.windows_arm64 | |
| ? TargetPlatform.windows_arm64 | |
| : TargetPlatform.windows_x64; | |
| } | |
| throw UnimplementedError('Host OS not supported.'); | |
| } | |
| /// Returns the Flutter.xcframework platform directory for the specified environment type. | |
| /// | |
| /// `Flutter.xcframework` contains target environment/architecture-specific | |
| /// subdirectories containing the appropriate `Flutter.framework` and | |
| /// `dSYMs/Flutter.framework.dSYMs` bundles for that target architecture. | |
| Directory _getIosFlutterFrameworkPlatformDirectory( | |
| String engineDirectory, | |
| EnvironmentType? environmentType, | |
| FileSystem fileSystem, | |
| Platform hostPlatform, | |
| ) { | |
| final Directory xcframeworkDirectory = fileSystem | |
| .directory(engineDirectory) | |
| .childDirectory(Artifact.flutterXcframework.getFileName(hostPlatform)); | |
| if (!xcframeworkDirectory.existsSync()) { | |
| throwToolExit( | |
| 'No xcframework found at ${xcframeworkDirectory.path}. Try running "flutter precache --ios".', | |
| ); | |
| } | |
| // NOTE: If you modify this function, you should likely also update the equivalent implementation in | |
| // packages/flutter_tools/templates/add_to_app/darwin/Tools/FlutterToolHelper/FlutterAssembleToolHelper.swift.tmpl | |
| 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)) { | |
| return platformDirectory; | |
| } | |
| } | |
| throwToolExit('No iOS frameworks found in ${xcframeworkDirectory.path}'); | |
| } | |
| /// Returns the path to Flutter.framework. | |
| String _getIosFrameworkPath( | |
| String engineDirectory, | |
| EnvironmentType? environmentType, | |
| FileSystem fileSystem, | |
| Platform hostPlatform, | |
| ) { | |
| final Directory platformDir = _getIosFlutterFrameworkPlatformDirectory( | |
| engineDirectory, | |
| environmentType, | |
| fileSystem, | |
| hostPlatform, | |
| ); | |
| return platformDir.childDirectory(Artifact.flutterFramework.getFileName(hostPlatform)).path; | |
| } | |
| /// Returns the path to Flutter.framework.dSYM. | |
| String _getIosFrameworkDsymPath( | |
| String engineDirectory, | |
| EnvironmentType? environmentType, | |
| FileSystem fileSystem, | |
| Platform hostPlatform, | |
| ) { | |
| final Directory platformDir = _getIosFlutterFrameworkPlatformDirectory( | |
| engineDirectory, | |
| environmentType, | |
| fileSystem, | |
| hostPlatform, | |
| ); | |
| return platformDir | |
| .childDirectory('dSYMs') | |
| .childDirectory(Artifact.flutterFrameworkDsym.getFileName(hostPlatform)) | |
| .path; | |
| } | |
| /// Returns the Flutter.xcframework platform directory for the specified environment type. | |
| /// | |
| /// `FlutterMacOS.xcframework` contains target environment/architecture-specific | |
| /// subdirectories containing the appropriate `FlutterMacOS.framework` and | |
| /// `FlutterMacOS.framework.dSYM` bundles for that target architecture. At present, | |
| /// there is only one such directory: `macos-arm64_x86_64`. | |
| Directory _getMacOSFrameworkPlatformDirectory( | |
| String engineDirectory, | |
| FileSystem fileSystem, | |
| Platform hostPlatform, | |
| ) { | |
| final Directory xcframeworkDirectory = fileSystem | |
| .directory(engineDirectory) | |
| .childDirectory(Artifact.flutterMacOSXcframework.getFileName(hostPlatform)); | |
| if (!xcframeworkDirectory.existsSync()) { | |
| throwToolExit( | |
| 'No xcframework found at ${xcframeworkDirectory.path}. Try running "flutter precache --macos".', | |
| ); | |
| } | |
| // NOTE: If you modify this function, you should likely also update the equivalent implementation in | |
| // packages/flutter_tools/templates/add_to_app/darwin/Tools/FlutterToolHelper/FlutterAssembleToolHelper.swift.tmpl | |
| final Directory? platformDirectory = xcframeworkDirectory | |
| .listSync() | |
| .whereType<Directory>() | |
| .where((Directory platformDirectory) => platformDirectory.basename.startsWith('macos-')) | |
| .firstOrNull; | |
| if (platformDirectory == null) { | |
| throwToolExit('No macOS frameworks found in ${xcframeworkDirectory.path}'); | |
| } | |
| return platformDirectory; | |
| } | |
| /// Returns the path to `FlutterMacOS.framework`. | |
| String _getMacOSFrameworkPath( | |
| String engineDirectory, | |
| FileSystem fileSystem, | |
| Platform hostPlatform, | |
| ) { | |
| final Directory platformDirectory = _getMacOSFrameworkPlatformDirectory( | |
| engineDirectory, | |
| fileSystem, | |
| hostPlatform, | |
| ); | |
| return platformDirectory | |
| .childDirectory(Artifact.flutterMacOSFramework.getFileName(hostPlatform)) | |
| .path; | |
| } | |
| /// Returns the path to `FlutterMacOS.framework`. | |
| String _getMacOSFrameworkDsymPath( | |
| String engineDirectory, | |
| FileSystem fileSystem, | |
| Platform hostPlatform, | |
| ) { | |
| final Directory platformDirectory = _getMacOSFrameworkPlatformDirectory( | |
| engineDirectory, | |
| fileSystem, | |
| hostPlatform, | |
| ); | |
| return platformDirectory | |
| .childDirectory('dSYMs') | |
| .childDirectory(Artifact.flutterMacOSFrameworkDsym.getFileName(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, | |
| ), | |
| _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 ProcessManager _processManager; | |
| final Platform _platform; | |
| final OperatingSystemUtils _operatingSystemUtils; | |
| final Artifacts _backupCache; | |
| @override | |
| FileSystemEntity getHostArtifact(HostArtifact artifact) { | |
| switch (artifact) { | |
| case HostArtifact.impellerc: | |
| case HostArtifact.libtessellator: | |
| final String artifactFileName = artifact.getFileName(_platform); | |
| final File file = _fileSystem.file( | |
| _fileSystem.path.join(_hostEngineOutPath, artifactFileName), | |
| ); | |
| if (!file.existsSync()) { | |
| return _backupCache.getHostArtifact(artifact); | |
| } | |
| return file; | |
| case HostArtifact.flutterWebSdk: | |
| case HostArtifact.flutterWebLibrariesJson: | |
| case HostArtifact.flutterJsDirectory: | |
| case HostArtifact.webPlatformKernelFolder: | |
| case HostArtifact.webPlatformDDCKernelDill: | |
| case HostArtifact.webPlatformDart2JSKernelDill: | |
| case HostArtifact.webPrecompiledAmdCanvaskitSdk: | |
| case HostArtifact.webPrecompiledAmdCanvaskitSdkSourcemaps: | |
| case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSdk: | |
| case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSdkSourcemaps: | |
| case HostArtifact.idevicesyslog: | |
| case HostArtifact.idevicescreenshot: | |
| case HostArtifact.skyEnginePath: | |
| case HostArtifact.iosDeploy: | |
| case HostArtifact.iproxy: | |
| return _backupCache.getHostArtifact(artifact); | |
| } | |
| } | |
| @override | |
| String getArtifactPath( | |
| Artifact artifact, { | |
| TargetPlatform? platform, | |
| BuildMode? mode, | |
| EnvironmentType? environmentType, | |
| }) { | |
| platform ??= _currentHostPlatform(_platform, _operatingSystemUtils); | |
| platform = _mapTargetPlatform(platform); | |
| final isDirectoryArtifact = artifact == Artifact.flutterPatchedSdkPath; | |
| final String? artifactFileName = isDirectoryArtifact | |
| ? null | |
| : artifact.getFileName(_platform, mode); | |
| switch (artifact) { | |
| case Artifact.genSnapshot: | |
| case Artifact.genSnapshotArm64: | |
| case Artifact.genSnapshotRiscv64: | |
| case Artifact.genSnapshotX64: | |
| return _genSnapshotPath(artifact); | |
| 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.flutterMacOSXcframework: | |
| 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 _getIosFrameworkPath( | |
| localEngineInfo.targetOutPath, | |
| environmentType, | |
| _fileSystem, | |
| _platform, | |
| ); | |
| case Artifact.flutterFrameworkDsym: | |
| return _getIosFrameworkDsymPath( | |
| localEngineInfo.targetOutPath, | |
| environmentType, | |
| _fileSystem, | |
| _platform, | |
| ); | |
| case Artifact.flutterMacOSFramework: | |
| return _getMacOSFrameworkPath(localEngineInfo.targetOutPath, _fileSystem, _platform); | |
| case Artifact.flutterMacOSFrameworkDsym: | |
| return _getMacOSFrameworkDsymPath(localEngineInfo.targetOutPath, _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 = getCurrentHostPlatform().cliName; | |
| final modeName = mode!.isRelease ? 'release' : mode.toString(); | |
| final dartBinaries = 'dart_binaries-$modeName-$hostPlatform'; | |
| return _fileSystem.path.join( | |
| localEngineInfo.targetOutPath, | |
| 'host_bundle', | |
| dartBinaries, | |
| 'kernel_compiler.dart.snapshot', | |
| ); | |
| case Artifact.fuchsiaFlutterRunner: | |
| final jitOrAot = mode!.isJit ? '_jit' : '_aot'; | |
| final 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.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.frontendServerSnapshotForEngineDartSdk: | |
| return _fileSystem.path.join(_getDartSdkPath(), 'bin', 'snapshots', artifactFileName); | |
| case Artifact.flutterToolsFileGenerators: | |
| return _getFileGeneratorsPath(); | |
| } | |
| } | |
| @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(_hostEngineOutPath, _fileSystem), | |
| _getPrebuiltTarget(_platform, _operatingSystemUtils), | |
| 'dart-sdk', | |
| ); | |
| if (_fileSystem.isDirectorySync(prebuiltPath)) { | |
| return prebuiltPath; | |
| } | |
| throwToolExit( | |
| 'Unable to find a built dart sdk at: "$builtPath" or a prebuilt dart sdk at: "$prebuiltPath"', | |
| ); | |
| } | |
| String _genSnapshotPath(Artifact artifact) { | |
| const clangDirs = <String>[ | |
| '.', | |
| 'universal', | |
| 'clang_x64', | |
| 'clang_x86', | |
| 'clang_i386', | |
| 'clang_arm64', | |
| 'clang_riscv64', | |
| ]; | |
| final String genSnapshotName = artifact.getFileName(_platform); | |
| for (final 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) { | |
| return _fileSystem.path.join( | |
| localEngineInfo.hostOutPath, | |
| Artifact.flutterTester.getFileName(_platform), | |
| ); | |
| } | |
| @override | |
| bool get usesLocalArtifacts => 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', | |
| artifact.getFileName(_platform, mode), | |
| ); | |
| case Artifact.frontendServerSnapshotForEngineDartSdk: | |
| return _fileSystem.path.join( | |
| _getDartSdkPath(), | |
| 'bin', | |
| 'snapshots', | |
| artifact.getFileName(_platform, mode), | |
| ); | |
| case Artifact.genSnapshot: | |
| case Artifact.genSnapshotArm64: | |
| case Artifact.genSnapshotRiscv64: | |
| case Artifact.genSnapshotX64: | |
| case Artifact.flutterTester: | |
| case Artifact.flutterFramework: | |
| case Artifact.flutterFrameworkDsym: | |
| case Artifact.flutterXcframework: | |
| case Artifact.flutterMacOSFramework: | |
| case Artifact.flutterMacOSFrameworkDsym: | |
| case Artifact.flutterMacOSXcframework: | |
| 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.flutterToolsFileGenerators: | |
| 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: | |
| case HostArtifact.flutterWebLibrariesJson: | |
| case HostArtifact.flutterJsDirectory: | |
| case HostArtifact.webPlatformKernelFolder: | |
| case HostArtifact.webPlatformDDCKernelDill: | |
| case HostArtifact.webPlatformDart2JSKernelDill: | |
| case HostArtifact.webPrecompiledAmdCanvaskitSdk: | |
| case HostArtifact.webPrecompiledAmdCanvaskitSdkSourcemaps: | |
| case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSdk: | |
| case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSdkSourcemaps: | |
| return _resolveWebArtifact(artifact, _getFlutterWebSdkPath(), _fileSystem, _platform); | |
| case HostArtifact.iosDeploy: | |
| case HostArtifact.idevicesyslog: | |
| case HostArtifact.idevicescreenshot: | |
| case HostArtifact.iproxy: | |
| case HostArtifact.skyEnginePath: | |
| case HostArtifact.impellerc: | |
| case HostArtifact.libtessellator: | |
| return _parent.getHostArtifact(artifact); | |
| } | |
| } | |
| String _getDartSdkPath() { | |
| // If the parent is a local engine, then use the locally built Dart SDK. | |
| if (_parent.usesLocalArtifacts) { | |
| return _parent.getArtifactPath(Artifact.engineDartSdkPath); | |
| } | |
| // If we couldn't find a built dart sdk, let's look for a prebuilt one. | |
| final String prebuiltPath = _fileSystem.path.join( | |
| _getFlutterPrebuiltsPath(_webSdkPath, _fileSystem), | |
| _getPrebuiltTarget(_platform, _operatingSystemUtils), | |
| 'dart-sdk', | |
| ); | |
| if (_fileSystem.isDirectorySync(prebuiltPath)) { | |
| return prebuiltPath; | |
| } | |
| throwToolExit('Unable to find a prebuilt dart sdk at: "$prebuiltPath"'); | |
| } | |
| String _getFlutterWebSdkPath() { | |
| return _fileSystem.path.join(_webSdkPath, 'flutter_web_sdk'); | |
| } | |
| @override | |
| bool get usesLocalArtifacts => true; | |
| @override | |
| LocalEngineInfo? get localEngineInfo => _parent.localEngineInfo; | |
| } | |
| /// 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 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 usesLocalArtifacts => 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 usesLocalArtifacts => 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', | |
| ); | |
| } | |
| FileSystemEntity _resolveWebArtifact( | |
| HostArtifact artifact, | |
| String webSdkPath, | |
| FileSystem fileSystem, | |
| Platform platform, | |
| ) { | |
| switch (artifact) { | |
| case HostArtifact.flutterWebSdk: | |
| return fileSystem.directory(webSdkPath); | |
| case HostArtifact.flutterWebLibrariesJson: | |
| return fileSystem.file(fileSystem.path.join(webSdkPath, artifact.getFileName(platform))); | |
| case HostArtifact.flutterJsDirectory: | |
| return fileSystem.directory(fileSystem.path.join(webSdkPath, artifact.getFileName(platform))); | |
| case HostArtifact.webPlatformKernelFolder: | |
| return fileSystem.file(fileSystem.path.join(webSdkPath, artifact.getFileName(platform))); | |
| case HostArtifact.webPlatformDDCKernelDill: | |
| case HostArtifact.webPlatformDart2JSKernelDill: | |
| return fileSystem.file( | |
| fileSystem.path.join(webSdkPath, 'kernel', artifact.getFileName(platform)), | |
| ); | |
| case HostArtifact.webPrecompiledAmdCanvaskitSdk: | |
| case HostArtifact.webPrecompiledAmdCanvaskitSdkSourcemaps: | |
| return fileSystem.file( | |
| fileSystem.path.join(webSdkPath, 'kernel', 'amd-canvaskit', artifact.getFileName(platform)), | |
| ); | |
| case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSdk: | |
| case HostArtifact.webPrecompiledDdcLibraryBundleCanvaskitSdkSourcemaps: | |
| return fileSystem.file( | |
| fileSystem.path.join( | |
| webSdkPath, | |
| 'kernel', | |
| 'ddcLibraryBundle-canvaskit', | |
| artifact.getFileName(platform), | |
| ), | |
| ); | |
| case HostArtifact.iosDeploy: | |
| case HostArtifact.idevicesyslog: | |
| case HostArtifact.idevicescreenshot: | |
| case HostArtifact.iproxy: | |
| case HostArtifact.skyEnginePath: | |
| case HostArtifact.impellerc: | |
| case HostArtifact.libtessellator: | |
| throw ArgumentError('Not a web artifact: $artifact'); | |
| } | |
| } | |
| String _getFlutterPrebuiltsPath(String baseOutPath, FileSystem fileSystem) { | |
| final String engineSrcPath = fileSystem.path.dirname(fileSystem.path.dirname(baseOutPath)); | |
| return fileSystem.path.join(engineSrcPath, 'flutter', 'prebuilts'); | |
| } | |
| String _getPrebuiltTarget(Platform platform, OperatingSystemUtils operatingSystemUtils) { | |
| final TargetPlatform hostPlatform = _currentHostPlatform(platform, operatingSystemUtils); | |
| switch (hostPlatform) { | |
| case TargetPlatform.darwin: | |
| return 'macos-x64'; | |
| case TargetPlatform.linux_riscv64: | |
| return 'linux-riscv64'; | |
| case TargetPlatform.linux_arm64: | |
| return 'linux-arm64'; | |
| case TargetPlatform.linux_x64: | |
| return 'linux-x64'; | |
| case TargetPlatform.windows_x64: | |
| return 'windows-x64'; | |
| case TargetPlatform.windows_arm64: | |
| return 'windows-arm64'; | |
| case TargetPlatform.ios: | |
| case TargetPlatform.android: | |
| case TargetPlatform.android_arm: | |
| case TargetPlatform.android_arm64: | |
| case TargetPlatform.android_x64: | |
| case TargetPlatform.fuchsia_arm64: | |
| case TargetPlatform.fuchsia_x64: | |
| case TargetPlatform.web_javascript: | |
| case TargetPlatform.tester: | |
| throwToolExit('Unsupported host platform: $hostPlatform'); | |
| case TargetPlatform.unsupported: | |
| TargetPlatform.throwUnsupportedTarget(); | |
| } | |
| } |