From cd8434d9315963744b3d5467e7f55efd0824f960 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Thu, 16 Feb 2017 23:10:11 -0800 Subject: [PATCH] Refactor how Artifacts are located (#8234) Artifacts are now located in a central place. This will enable us to downlaod artifacts when we need them (instead of downloading them all upfront). This also makes replacing sky_snapshot with gen_snapshot easier. --- packages/flutter_tools/lib/executable.dart | 4 +- packages/flutter_tools/lib/src/artifacts.dart | 264 ++++++++++++++++++ .../lib/src/commands/build_aot.dart | 39 +-- .../lib/src/commands/build_apk.dart | 39 +-- .../lib/src/commands/build_ios.dart | 3 +- .../flutter_tools/lib/src/commands/test.dart | 5 +- .../lib/src/dart/dependencies.dart | 4 +- packages/flutter_tools/lib/src/flx.dart | 4 +- packages/flutter_tools/lib/src/globals.dart | 4 +- .../flutter_tools/lib/src/ios/xcodeproj.dart | 9 +- .../src/runner/flutter_command_runner.dart | 5 +- packages/flutter_tools/lib/src/toolchain.dart | 83 ------ packages/flutter_tools/test/all.dart | 4 +- .../flutter_tools/test/artifacts_test.dart | 118 ++++++++ packages/flutter_tools/test/src/context.dart | 4 +- .../flutter_tools/test/toolchain_test.dart | 46 --- 16 files changed, 425 insertions(+), 210 deletions(-) create mode 100644 packages/flutter_tools/lib/src/artifacts.dart delete mode 100644 packages/flutter_tools/lib/src/toolchain.dart create mode 100644 packages/flutter_tools/test/artifacts_test.dart delete mode 100644 packages/flutter_tools/test/toolchain_test.dart diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart index 8d4085bde4..af22636709 100644 --- a/packages/flutter_tools/lib/executable.dart +++ b/packages/flutter_tools/lib/executable.dart @@ -41,6 +41,7 @@ import 'src/commands/test.dart'; import 'src/commands/trace.dart'; import 'src/commands/update_packages.dart'; import 'src/commands/upgrade.dart'; +import 'src/artifacts.dart'; import 'src/devfs.dart'; import 'src/device.dart'; import 'src/doctor.dart'; @@ -49,7 +50,6 @@ import 'src/ios/mac.dart'; import 'src/ios/simulators.dart'; import 'src/run_hot.dart'; import 'src/runner/flutter_command_runner.dart'; -import 'src/toolchain.dart'; import 'src/usage.dart'; @@ -113,7 +113,7 @@ Future main(List args) async { context.putIfAbsent(Doctor, () => new Doctor()); context.putIfAbsent(HotRunnerConfig, () => new HotRunnerConfig()); context.putIfAbsent(Cache, () => new Cache()); - context.putIfAbsent(ToolConfiguration, () => new ToolConfiguration()); + context.putIfAbsent(Artifacts, () => new CachedArtifacts()); context.putIfAbsent(Config, () => new Config()); context.putIfAbsent(OperatingSystemUtils, () => new OperatingSystemUtils()); context.putIfAbsent(Xcode, () => new Xcode()); diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart new file mode 100644 index 0000000000..0aa9ddc7fb --- /dev/null +++ b/packages/flutter_tools/lib/src/artifacts.dart @@ -0,0 +1,264 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'base/context.dart'; +import 'base/file_system.dart'; +import 'base/platform.dart'; +import 'build_info.dart'; +import 'globals.dart'; + +enum Artifact { + chromiumDebugKeyStore, + classesDexJar, + icudtlDat, + libskyShellSo, + dartIoEntriesTxt, + dartVmEntryPointsTxt, + dartVmEntryPointsAndroidTxt, + genSnapshot, + skyShell, + skySnapshot, + snapshotDart, + flutterFramework, +} + +String _artifactToFileName(Artifact artifact) { + switch (artifact) { + case Artifact.chromiumDebugKeyStore: + return 'chromium-debug.keystore'; + case Artifact.classesDexJar: + return 'classes.dex.jar'; + case Artifact.icudtlDat: + return 'icudtl.dat'; + case Artifact.libskyShellSo: + return 'libsky_shell.so'; + case Artifact.dartIoEntriesTxt: + return 'dart_io_entries.txt'; + case Artifact.dartVmEntryPointsTxt: + return 'dart_vm_entry_points.txt'; + case Artifact.dartVmEntryPointsAndroidTxt: + return 'dart_vm_entry_points_android.txt'; + case Artifact.genSnapshot: + return 'gen_snapshot'; + case Artifact.skySnapshot: + return 'sky_snapshot'; + case Artifact.skyShell: + return 'sky_shell'; + case Artifact.snapshotDart: + return 'snapshot.dart'; + case Artifact.flutterFramework: + return 'Flutter.framework'; + } + assert(false, 'Invalid artifact $artifact.'); + return null; +} + +// Manages the engine artifacts of Flutter. +abstract class Artifacts { + static Artifacts get instance => context[Artifacts]; + + static void useLocalEngine(String engineSrcPath, String engineOutPath) { + context.setVariable(Artifacts, new LocalEngineArtifacts(engineSrcPath, engineOutPath)); + } + + // Returns the requested [artifact] for the [platform] and [mode] combination. + String getArtifactPath(Artifact artifact, [TargetPlatform platform, BuildMode mode]); + + // Returns which set of engine artifacts is currently used for the [platform] + // and [mode] combination. + String getEngineType(TargetPlatform platform, [BuildMode mode]); +} + +/// Manages the engine artifacts downloaded to the local cache. +class CachedArtifacts extends Artifacts { + + @override + String getArtifactPath(Artifact artifact, [TargetPlatform platform, BuildMode mode]) { + platform ??= _currentHostPlatform; + switch (platform) { + case TargetPlatform.android_arm: + case TargetPlatform.android_x64: + case TargetPlatform.android_x86: + return _getAndroidArtifactPath(artifact, platform, mode); + case TargetPlatform.ios: + return _getIosArtifactPath(artifact, platform, mode); + case TargetPlatform.darwin_x64: + case TargetPlatform.linux_x64: + assert(mode == null, 'Platform $platform does not support different build modes.'); + return _getHostArtifactPath(artifact, platform); + } + assert(false, 'Invalid platform $platform.'); + return null; + } + + @override + String getEngineType(TargetPlatform platform, [BuildMode mode]){ + return fs.path.basename(_getEngineArtifactsPath(platform, mode)); + } + + String _getAndroidArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) { + String engineDir = _getEngineArtifactsPath(platform, mode); + switch (artifact) { + case Artifact.chromiumDebugKeyStore: + case Artifact.classesDexJar: + case Artifact.icudtlDat: + case Artifact.libskyShellSo: + return fs.path.join(engineDir, _artifactToFileName(artifact)); + case Artifact.dartIoEntriesTxt: + case Artifact.dartVmEntryPointsTxt: + case Artifact.dartVmEntryPointsAndroidTxt: + assert(mode != BuildMode.debug, 'Artifact $artifact only available in non-debug mode.'); + return fs.path.join(engineDir, _artifactToFileName(artifact)); + case Artifact.genSnapshot: + assert(mode != BuildMode.debug, 'Artifact $artifact only available in non-debug mode.'); + String hostPlatform = getNameForHostPlatform(getCurrentHostPlatform()); + return fs.path.join(engineDir, hostPlatform, _artifactToFileName(artifact)); + default: + assert(false, 'Artifact $artifact not available for platform $platform.'); + return null; + } + } + + String _getIosArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) { + String engineDir = _getEngineArtifactsPath(platform, mode); + switch (artifact) { + case Artifact.dartIoEntriesTxt: + case Artifact.dartVmEntryPointsTxt: + case Artifact.genSnapshot: + case Artifact.snapshotDart: + case Artifact.flutterFramework: + return fs.path.join(engineDir, _artifactToFileName(artifact)); + default: + assert(false, 'Artifact $artifact not available for platform $platform.'); + return null; + } + } + + String _getHostArtifactPath(Artifact artifact, TargetPlatform platform) { + switch (artifact) { + case Artifact.skyShell: + case Artifact.skySnapshot: + case Artifact.icudtlDat: + String engineArtifactsPath = cache.getArtifactDirectory('engine').path; + String platformDirName = getNameForTargetPlatform(platform); + return fs.path.join(engineArtifactsPath, platformDirName, _artifactToFileName(artifact)); + default: + assert(false, 'Artifact $artifact not available for platform $platform.'); + return null; + } + } + + String _getEngineArtifactsPath(TargetPlatform platform, [BuildMode mode]) { + String engineDir = cache.getArtifactDirectory('engine').path; + String platformName = getNameForTargetPlatform(platform); + switch (platform) { + case TargetPlatform.linux_x64: + case TargetPlatform.darwin_x64: + assert(mode == null, 'Platform $platform does not support different build modes.'); + return fs.path.join(engineDir, platformName); + case TargetPlatform.ios: + case TargetPlatform.android_arm: + case TargetPlatform.android_x64: + case TargetPlatform.android_x86: + assert(mode != null, 'Need to specify a build mode for platform $platform.'); + String suffix = mode != BuildMode.debug ? '-${getModeName(mode)}' : ''; + return fs.path.join(engineDir, platformName + suffix); + } + assert(false, 'Invalid platform $platform.'); + return null; + } + + TargetPlatform get _currentHostPlatform { + if (platform.isMacOS) + return TargetPlatform.darwin_x64; + if (platform.isLinux) + return TargetPlatform.linux_x64; + throw new UnimplementedError('Host OS not supported.'); + } +} + +/// Manages the artifacts of a locally built engine. +class LocalEngineArtifacts extends Artifacts { + final String _engineSrcPath; + final String engineOutPath; // TODO(goderbauer): This should be private. + + LocalEngineArtifacts(this._engineSrcPath, this.engineOutPath); + + @override + String getArtifactPath(Artifact artifact, [TargetPlatform platform, BuildMode mode]) { + switch (artifact) { + case Artifact.chromiumDebugKeyStore: + return fs.path.join(_engineSrcPath, 'build', 'android', 'ant', _artifactToFileName(artifact)); + case Artifact.dartIoEntriesTxt: + return fs.path.join(_engineSrcPath, 'dart', 'runtime', 'bin', _artifactToFileName(artifact)); + case Artifact.dartVmEntryPointsTxt: + return fs.path.join(_engineSrcPath, 'flutter', 'runtime', _artifactToFileName(artifact)); + case Artifact.dartVmEntryPointsAndroidTxt: + return fs.path.join(_engineSrcPath, 'flutter', 'runtime', _artifactToFileName(artifact)); + case Artifact.snapshotDart: + return fs.path.join(_engineSrcPath, 'flutter', 'lib', 'snapshot', _artifactToFileName(artifact)); + case Artifact.classesDexJar: + return fs.path.join(engineOutPath, 'gen', 'flutter', 'shell', 'platform', 'android', 'android', _artifactToFileName(artifact)); + case Artifact.icudtlDat: + return fs.path.join(engineOutPath, _artifactToFileName(artifact)); + case Artifact.libskyShellSo: + String abi = _getAbiDirectory(platform); + return fs.path.join(engineOutPath, 'gen', 'flutter', 'shell', 'platform', 'android', 'android', fs.path.join('android', 'libs', abi, _artifactToFileName(artifact))); + case Artifact.genSnapshot: + return _genSnapshotPath(platform); + case Artifact.skyShell: + return _skyShellPath(platform); + case Artifact.skySnapshot: + return _skySnapshotPath(); + case Artifact.flutterFramework: + return fs.path.join(engineOutPath, _artifactToFileName(artifact)); + } + assert(false, 'Invalid artifact $artifact.'); + return null; + } + + @override + String getEngineType(TargetPlatform platform, [BuildMode mode]) { + return fs.path.basename(engineOutPath); + } + + String _genSnapshotPath(TargetPlatform platform) { + String clang; + if (platform == TargetPlatform.ios) { + clang = 'clang_x64'; + } else { + clang = getCurrentHostPlatform() == HostPlatform.darwin_x64 ? 'clang_i386' : 'clang_x86'; + } + return fs.path.join(engineOutPath, clang, _artifactToFileName(Artifact.genSnapshot)); + } + + String _skySnapshotPath() { + String clangPath = fs.path.join(engineOutPath, 'clang_x64', _artifactToFileName(Artifact.skySnapshot)); + if (fs.isFileSync(clangPath)) + return clangPath; + return fs.path.join(engineOutPath, _artifactToFileName(Artifact.skySnapshot)); + } + + String _skyShellPath(TargetPlatform platform) { + if (getCurrentHostPlatform() == HostPlatform.linux_x64) { + return fs.path.join(engineOutPath, _artifactToFileName(Artifact.skyShell)); + } else if (getCurrentHostPlatform() == HostPlatform.darwin_x64) { + return fs.path.join(engineOutPath, 'SkyShell.app', 'Contents', 'MacOS', 'SkyShell'); + } + throw new Exception('Unsupported platform $platform.'); + } + + String _getAbiDirectory(TargetPlatform platform) { + switch (platform) { + case TargetPlatform.android_arm: + return 'armeabi-v7a'; + case TargetPlatform.android_x64: + return 'x86_64'; + case TargetPlatform.android_x86: + return 'x86'; + default: + throw new Exception('Unsupported platform $platform.'); + } + } +} diff --git a/packages/flutter_tools/lib/src/commands/build_aot.dart b/packages/flutter_tools/lib/src/commands/build_aot.dart index 368a563fce..27529c2051 100644 --- a/packages/flutter_tools/lib/src/commands/build_aot.dart +++ b/packages/flutter_tools/lib/src/commands/build_aot.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import '../artifacts.dart'; import '../base/common.dart'; import '../base/file_system.dart'; import '../base/logger.dart'; @@ -49,7 +50,7 @@ class BuildAotCommand extends BuildSubCommand { if (platform == null) throwToolExit('Unknown platform: $targetPlatform'); - String typeName = fs.path.basename(tools.getEngineArtifactsDirectory(platform, getBuildMode()).path); + String typeName = artifacts.getEngineType(platform, getBuildMode()); Status status = logger.startProgress('Building AOT snapshot in ${getModeName(getBuildMode())} mode ($typeName)...', expectSlowOperation: true); String outputPath = await buildAotSnapshot( @@ -115,33 +116,7 @@ Future _buildAotSnapshot( return null; } - String entryPointsDir, dartEntryPointsDir, snapshotterDir, genSnapshot; - - String engineSrc = tools.engineSrcPath; - String genSnapshotExecutable = 'gen_snapshot'; - if (engineSrc != null) { - entryPointsDir = fs.path.join(engineSrc, 'flutter', 'runtime'); - dartEntryPointsDir = fs.path.join(engineSrc, 'dart', 'runtime', 'bin'); - snapshotterDir = fs.path.join(engineSrc, 'flutter', 'lib', 'snapshot'); - String engineOut = tools.getEngineArtifactsDirectory(platform, buildMode).path; - if (platform == TargetPlatform.ios) { - genSnapshot = fs.path.join(engineOut, 'clang_x64', genSnapshotExecutable); - } else { - String host32BitToolchain = getCurrentHostPlatform() == HostPlatform.darwin_x64 ? 'clang_i386' : 'clang_x86'; - genSnapshot = fs.path.join(engineOut, host32BitToolchain, genSnapshotExecutable); - } - } else { - String artifactsDir = tools.getEngineArtifactsDirectory(platform, buildMode).path; - entryPointsDir = artifactsDir; - dartEntryPointsDir = entryPointsDir; - snapshotterDir = entryPointsDir; - if (platform == TargetPlatform.ios) { - genSnapshot = fs.path.join(artifactsDir, genSnapshotExecutable); - } else { - String hostToolsDir = fs.path.join(artifactsDir, getNameForHostPlatform(getCurrentHostPlatform())); - genSnapshot = fs.path.join(hostToolsDir, genSnapshotExecutable); - } - } + String genSnapshot = artifacts.getArtifactPath(Artifact.genSnapshot, platform, buildMode); Directory outputDir = fs.directory(outputPath); outputDir.createSync(recursive: true); @@ -150,8 +125,8 @@ Future _buildAotSnapshot( String isolateSnapshotData = fs.path.join(outputDir.path, 'isolate_snapshot_data'); String isolateSnapshotInstructions = fs.path.join(outputDir.path, 'isolate_snapshot_instr'); - String vmEntryPoints = fs.path.join(entryPointsDir, 'dart_vm_entry_points.txt'); - String ioEntryPoints = fs.path.join(dartEntryPointsDir, 'dart_io_entries.txt'); + String vmEntryPoints = artifacts.getArtifactPath(Artifact.dartVmEntryPointsTxt, platform, buildMode); + String ioEntryPoints = artifacts.getArtifactPath(Artifact.dartIoEntriesTxt, platform, buildMode); PackageMap packageMap = new PackageMap(PackageMap.globalPackagesPath); String packageMapError = packageMap.checkValid(); @@ -184,13 +159,13 @@ Future _buildAotSnapshot( case TargetPlatform.android_arm: case TargetPlatform.android_x64: case TargetPlatform.android_x86: - vmEntryPointsAndroid = fs.path.join(entryPointsDir, 'dart_vm_entry_points_android.txt'); + vmEntryPointsAndroid = artifacts.getArtifactPath(Artifact.dartVmEntryPointsAndroidTxt, platform, buildMode); filePaths.addAll([ vmEntryPointsAndroid, ]); break; case TargetPlatform.ios: - snapshotDartIOS = fs.path.join(snapshotterDir, 'snapshot.dart'); + snapshotDartIOS = artifacts.getArtifactPath(Artifact.snapshotDart, platform, buildMode); assembly = fs.path.join(outputDir.path, 'snapshot_assembly.S'); filePaths.addAll([ snapshotDartIOS, diff --git a/packages/flutter_tools/lib/src/commands/build_apk.dart b/packages/flutter_tools/lib/src/commands/build_apk.dart index 8f64bea660..f87592e932 100644 --- a/packages/flutter_tools/lib/src/commands/build_apk.dart +++ b/packages/flutter_tools/lib/src/commands/build_apk.dart @@ -7,6 +7,7 @@ import 'dart:convert' show JSON; import '../android/android_sdk.dart'; import '../android/gradle.dart'; +import '../artifacts.dart'; import '../base/common.dart'; import '../base/file_system.dart'; import '../base/logger.dart'; @@ -285,28 +286,12 @@ Future<_ApkComponents> _findApkComponents( components.manifest = fs.file(manifest); components.resources = resources == null ? null : fs.directory(resources); components.extraFiles = extraFiles != null ? extraFiles : {}; - - if (tools.isLocalEngine) { - String abiDir = getAbiDirectory(platform); - String enginePath = tools.engineSrcPath; - String buildDir = tools.getEngineArtifactsDirectory(platform, buildMode).path; - - components.icuData = fs.file('$enginePath/third_party/icu/android/icudtl.dat'); - components.jars = [ - fs.file('$buildDir/gen/flutter/shell/platform/android/android/classes.dex.jar') - ]; - components.libSkyShell = fs.file('$buildDir/gen/flutter/shell/platform/android/android/android/libs/$abiDir/libsky_shell.so'); - components.debugKeystore = fs.file('$enginePath/build/android/ant/chromium-debug.keystore'); - } else { - Directory artifacts = tools.getEngineArtifactsDirectory(platform, buildMode); - - components.icuData = fs.file(fs.path.join(artifacts.path, 'icudtl.dat')); - components.jars = [ - fs.file(fs.path.join(artifacts.path, 'classes.dex.jar')) - ]; - components.libSkyShell = fs.file(fs.path.join(artifacts.path, 'libsky_shell.so')); - components.debugKeystore = fs.file(fs.path.join(artifacts.path, 'chromium-debug.keystore')); - } + components.icuData = fs.file(artifacts.getArtifactPath(Artifact.icudtlDat, platform, buildMode)); + components.jars = [ + fs.file(artifacts.getArtifactPath(Artifact.classesDexJar, platform, buildMode)) + ]; + components.libSkyShell = fs.file(artifacts.getArtifactPath(Artifact.libskyShellSo, platform, buildMode)); + components.debugKeystore = fs.file(artifacts.getArtifactPath(Artifact.chromiumDebugKeyStore, platform, buildMode)); await parseServiceConfigs(components.services, jars: components.jars); @@ -534,8 +519,8 @@ Future buildAndroid( if (components == null) throwToolExit('Failure building APK: unable to find components.'); - String typeName = fs.path.basename(tools.getEngineArtifactsDirectory(platform, buildMode).path); - Status status = logger.startProgress('Building APK in ${getModeName(buildMode)} mode ($typeName)...', + String typeName = artifacts.getEngineType(platform, buildMode); + Status status = logger.startProgress('Building APK in ${getModeName(buildMode)} mode ($typeName)...', expectSlowOperation: true); if (flxPath != null && flxPath.isNotEmpty) { @@ -658,8 +643,10 @@ void _writeBuildMetaEntry(String buildDirectoryPath, String key, dynamic value) String _getTargetBuildTypeToken(TargetPlatform platform, BuildMode buildMode, File outputBinary) { String buildType = getNameForTargetPlatform(platform) + '-' + getModeName(buildMode); - if (tools.isLocalEngine) - buildType += ' [${tools.engineBuildPath}]'; + if (artifacts is LocalEngineArtifacts) { + LocalEngineArtifacts localEngineArtifacts = artifacts; + buildType += ' [${localEngineArtifacts.engineOutPath}]'; + } if (outputBinary.existsSync()) buildType += ' [${outputBinary.lastModifiedSync().millisecondsSinceEpoch}]'; return buildType; diff --git a/packages/flutter_tools/lib/src/commands/build_ios.dart b/packages/flutter_tools/lib/src/commands/build_ios.dart index 5e3fc80029..34adb0b61e 100644 --- a/packages/flutter_tools/lib/src/commands/build_ios.dart +++ b/packages/flutter_tools/lib/src/commands/build_ios.dart @@ -6,7 +6,6 @@ import 'dart:async'; import '../application_package.dart'; import '../base/common.dart'; -import '../base/file_system.dart'; import '../base/logger.dart'; import '../base/utils.dart'; import '../build_info.dart'; @@ -63,7 +62,7 @@ class BuildIOSCommand extends BuildSubCommand { String logTarget = forSimulator ? 'simulator' : 'device'; - String typeName = fs.path.basename(tools.getEngineArtifactsDirectory(TargetPlatform.ios, getBuildMode()).path); + String typeName = artifacts.getEngineType(TargetPlatform.ios, getBuildMode()); Status status = logger.startProgress('Building $app for $logTarget ($typeName)...', expectSlowOperation: true); XcodeBuildResult result = await buildXcodeProject( diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart index ef9b7e3826..292bbc2be0 100644 --- a/packages/flutter_tools/lib/src/commands/test.dart +++ b/packages/flutter_tools/lib/src/commands/test.dart @@ -6,11 +6,11 @@ import 'dart:async'; import 'package:test/src/executable.dart' as test; // ignore: implementation_imports +import '../artifacts.dart'; import '../base/common.dart'; import '../base/file_system.dart'; import '../base/io.dart'; import '../base/logger.dart'; -import '../base/platform.dart'; import '../base/process_manager.dart'; import '../base/os.dart'; import '../cache.dart'; @@ -19,7 +19,6 @@ import '../globals.dart'; import '../runner/flutter_command.dart'; import '../test/coverage_collector.dart'; import '../test/flutter_platform.dart' as loader; -import '../toolchain.dart'; class TestCommand extends FlutterCommand { TestCommand() { @@ -190,7 +189,7 @@ class TestCommand extends FlutterCommand { } testArgs.addAll(files); - final String shellPath = tools.getHostToolPath(HostTool.SkyShell) ?? platform.environment['SKY_SHELL']; + final String shellPath = artifacts.getArtifactPath(Artifact.skyShell); if (!fs.isFileSync(shellPath)) throwToolExit('Cannot find Flutter shell at $shellPath'); loader.installHook( diff --git a/packages/flutter_tools/lib/src/dart/dependencies.dart b/packages/flutter_tools/lib/src/dart/dependencies.dart index 5fb22c332f..6d55526598 100644 --- a/packages/flutter_tools/lib/src/dart/dependencies.dart +++ b/packages/flutter_tools/lib/src/dart/dependencies.dart @@ -4,9 +4,9 @@ import 'dart:convert'; +import '../artifacts.dart'; import '../base/file_system.dart'; import '../base/process.dart'; -import '../toolchain.dart'; class DartDependencySetBuilder { DartDependencySetBuilder(this.mainScriptPath, @@ -19,7 +19,7 @@ class DartDependencySetBuilder { Set build() { final String skySnapshotPath = - ToolConfiguration.instance.getHostToolPath(HostTool.SkySnapshot); + Artifacts.instance.getArtifactPath(Artifact.skySnapshot); final List args = [ skySnapshotPath, diff --git a/packages/flutter_tools/lib/src/flx.dart b/packages/flutter_tools/lib/src/flx.dart index 73b3fee470..8f2bdf8a4e 100644 --- a/packages/flutter_tools/lib/src/flx.dart +++ b/packages/flutter_tools/lib/src/flx.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'artifacts.dart'; import 'asset.dart'; import 'base/common.dart'; import 'base/file_system.dart'; @@ -12,7 +13,6 @@ import 'dart/package_map.dart'; import 'devfs.dart'; import 'build_info.dart'; import 'globals.dart'; -import 'toolchain.dart'; import 'zip.dart'; const String defaultMainPath = 'lib/main.dart'; @@ -88,7 +88,7 @@ Future build({ bool includeRobotoFonts: true, bool reportLicensedPackages: false }) async { - snapshotterPath ??= tools.getHostToolPath(HostTool.SkySnapshot); + snapshotterPath ??= artifacts.getArtifactPath(Artifact.skySnapshot); outputPath ??= defaultFlxOutputPath; kernelPath ??= defaultKernelPath; snapshotPath ??= defaultSnapshotPath; diff --git a/packages/flutter_tools/lib/src/globals.dart b/packages/flutter_tools/lib/src/globals.dart index f177ebb402..3334798248 100644 --- a/packages/flutter_tools/lib/src/globals.dart +++ b/packages/flutter_tools/lib/src/globals.dart @@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'artifacts.dart'; import 'base/config.dart'; import 'base/context.dart'; import 'base/logger.dart'; import 'cache.dart'; -import 'toolchain.dart'; Logger get logger => context[Logger]; Cache get cache => Cache.instance; Config get config => Config.instance; -ToolConfiguration get tools => ToolConfiguration.instance; +Artifacts get artifacts => Artifacts.instance; /// Display an error level message to the user. Commands should use this if they /// fail in some way. diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart index 245b335cdc..c7bb1d92ec 100644 --- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart +++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart @@ -5,6 +5,7 @@ import '../base/file_system.dart'; import '../base/process.dart'; import '../build_info.dart'; +import '../artifacts.dart'; import '../cache.dart'; import '../globals.dart'; @@ -33,11 +34,13 @@ void updateXcodeGeneratedProperties(String projectPath, BuildMode mode, String t localsBuffer.writeln('SYMROOT=\${SOURCE_ROOT}/../${getIosBuildDirectory()}'); - String flutterFrameworkDir = fs.path.normalize(tools.getEngineArtifactsDirectory(TargetPlatform.ios, mode).path); + String flutterFrameworkDir = fs.path.normalize(fs.path.dirname(artifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, mode))); localsBuffer.writeln('FLUTTER_FRAMEWORK_DIR=$flutterFrameworkDir'); - if (tools.isLocalEngine) - localsBuffer.writeln('LOCAL_ENGINE=${tools.engineBuildPath}'); + if (artifacts is LocalEngineArtifacts) { + LocalEngineArtifacts localEngineArtifacts = artifacts; + localsBuffer.writeln('LOCAL_ENGINE=${localEngineArtifacts.engineOutPath}'); + } File localsFile = fs.file(fs.path.join(projectPath, 'ios', 'Flutter', 'Generated.xcconfig')); localsFile.createSync(recursive: true); diff --git a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart index 1eeea2c70d..5cb6ca955d 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart @@ -8,6 +8,7 @@ import 'package:args/args.dart'; import 'package:args/command_runner.dart'; import '../android/android_sdk.dart'; +import '../artifacts.dart'; import '../base/common.dart'; import '../base/context.dart'; import '../base/file_system.dart'; @@ -19,7 +20,6 @@ import '../cache.dart'; import '../dart/package_map.dart'; import '../device.dart'; import '../globals.dart'; -import '../toolchain.dart'; import '../usage.dart'; import '../version.dart'; @@ -206,8 +206,7 @@ class FlutterCommandRunner extends CommandRunner { // Set up the tooling configuration. String enginePath = _findEnginePath(globalResults); if (enginePath != null) { - ToolConfiguration.instance.engineSrcPath = enginePath; - ToolConfiguration.instance.engineBuildPath = _findEngineBuildPath(globalResults, enginePath); + Artifacts.useLocalEngine(enginePath, _findEngineBuildPath(globalResults, enginePath)); } // The Android SDK could already have been set by tests. diff --git a/packages/flutter_tools/lib/src/toolchain.dart b/packages/flutter_tools/lib/src/toolchain.dart deleted file mode 100644 index f60c6e2b79..0000000000 --- a/packages/flutter_tools/lib/src/toolchain.dart +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'base/context.dart'; -import 'base/file_system.dart'; -import 'build_info.dart'; -import 'cache.dart'; -import 'globals.dart'; - -enum HostTool { - SkySnapshot, - SkyShell, -} - -const Map _kHostToolFileName = const { - HostTool.SkySnapshot: 'sky_snapshot', - HostTool.SkyShell: 'sky_shell', -}; - -/// A ToolConfiguration can return the tools directory for the current host platform -/// and the engine artifact directory for a given target platform. It is configurable -/// via command-line arguments in order to support local engine builds. -class ToolConfiguration { - ToolConfiguration(); - - Cache get cache => context[Cache]; - - static ToolConfiguration get instance => context[ToolConfiguration]; - - /// Override using the artifacts from the cache directory (--engine-src-path). - String engineSrcPath; - - /// Path to a local engine build acting as a source for artifacts (--local-engine). - String engineBuildPath; - - bool get isLocalEngine => engineSrcPath != null; - - /// Return the directory that contains engine artifacts for the given targets. - /// This directory might contain artifacts like `libsky_shell.so`. - Directory getEngineArtifactsDirectory(TargetPlatform platform, BuildMode mode) { - Directory dir = _getEngineArtifactsDirectory(platform, mode); - if (dir != null) - printTrace('Using engine artifacts dir: ${dir.path}'); - return dir; - } - - Directory _getEngineArtifactsDirectory(TargetPlatform platform, BuildMode mode) { - if (engineBuildPath != null) { - return fs.directory(engineBuildPath); - } else { - String suffix = mode != BuildMode.debug ? '-${getModeName(mode)}' : ''; - - // Create something like `android-arm` or `android-arm-release`. - String dirName = getNameForTargetPlatform(platform) + suffix; - Directory engineDir = cache.getArtifactDirectory('engine'); - return fs.directory(fs.path.join(engineDir.path, dirName)); - } - } - - String getHostToolPath(HostTool tool) { - if (engineBuildPath == null) { - return fs.path.join(cache.getArtifactDirectory('engine').path, - getNameForHostPlatform(getCurrentHostPlatform()), - _kHostToolFileName[tool]); - } - - if (tool == HostTool.SkySnapshot) { - String clangPath = fs.path.join(engineBuildPath, 'clang_x64', 'sky_snapshot'); - if (fs.isFileSync(clangPath)) - return clangPath; - return fs.path.join(engineBuildPath, 'sky_snapshot'); - } else if (tool == HostTool.SkyShell) { - if (getCurrentHostPlatform() == HostPlatform.linux_x64) { - return fs.path.join(engineBuildPath, 'sky_shell'); - } else if (getCurrentHostPlatform() == HostPlatform.darwin_x64) { - return fs.path.join(engineBuildPath, 'SkyShell.app', 'Contents', 'MacOS', 'SkyShell'); - } - } - - throw 'Unexpected host tool: $tool'; - } -} diff --git a/packages/flutter_tools/test/all.dart b/packages/flutter_tools/test/all.dart index b07cb50232..be37b4cc62 100644 --- a/packages/flutter_tools/test/all.dart +++ b/packages/flutter_tools/test/all.dart @@ -16,6 +16,7 @@ import 'analyze_test.dart' as analyze_test; import 'android_device_test.dart' as android_device_test; import 'android_sdk_test.dart' as android_sdk_test; import 'application_package_test.dart' as application_package_test; +import 'artifacts_test.dart' as artifacts_test; import 'asset_bundle_test.dart' as asset_bundle_test; import 'base_utils_test.dart' as base_utils_test; import 'channel_test.dart' as channel_test; @@ -41,7 +42,6 @@ import 'protocol_discovery_test.dart' as protocol_discovery_test; import 'run_test.dart' as run_test; import 'stop_test.dart' as stop_test; import 'test_test.dart' as test_test; -import 'toolchain_test.dart' as toolchain_test; import 'trace_test.dart' as trace_test; import 'upgrade_test.dart' as upgrade_test; import 'utils_test.dart' as utils_test; @@ -55,6 +55,7 @@ void main() { android_device_test.main(); android_sdk_test.main(); application_package_test.main(); + artifacts_test.main(); asset_bundle_test.main(); base_utils_test.main(); channel_test.main(); @@ -80,7 +81,6 @@ void main() { run_test.main(); stop_test.main(); test_test.main(); - toolchain_test.main(); trace_test.main(); upgrade_test.main(); utils_test.main(); diff --git a/packages/flutter_tools/test/artifacts_test.dart b/packages/flutter_tools/test/artifacts_test.dart new file mode 100644 index 0000000000..ad31621870 --- /dev/null +++ b/packages/flutter_tools/test/artifacts_test.dart @@ -0,0 +1,118 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_tools/src/base/file_system.dart'; +import 'package:flutter_tools/src/base/platform.dart'; +import 'package:flutter_tools/src/build_info.dart'; +import 'package:flutter_tools/src/cache.dart'; +import 'package:flutter_tools/src/artifacts.dart'; +import 'package:test/test.dart'; + +import 'src/context.dart'; + +void main() { + group('CachedArtifacts', () { + + Directory tempDir; + CachedArtifacts artifacts; + + setUp(() { + tempDir = fs.systemTempDirectory.createTempSync('flutter_temp'); + artifacts = new CachedArtifacts(); + }); + + tearDown(() { + tempDir.deleteSync(recursive: true); + }); + + testUsingContext('getArtifactPath', () { + expect( + artifacts.getArtifactPath(Artifact.libskyShellSo, TargetPlatform.android_arm, BuildMode.debug), + fs.path.join(tempDir.path, 'bin', 'cache', 'artifacts', 'engine', 'android-arm', 'libsky_shell.so') + ); + expect( + artifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, BuildMode.release), + fs.path.join(tempDir.path, 'bin', 'cache', 'artifacts', 'engine', 'ios-release', 'Flutter.framework') + ); + + expect( + artifacts.getArtifactPath(Artifact.skyShell), + fs.path.join(tempDir.path, 'bin', 'cache', 'artifacts', 'engine', 'linux-x64', 'sky_shell') + ); + }, overrides: { + Cache: () => new Cache(rootOverride: tempDir), + Platform: () => new FakePlatform(operatingSystem: 'linux') + }); + + testUsingContext('getEngineType', () { + expect( + artifacts.getEngineType(TargetPlatform.android_arm, BuildMode.debug), + 'android-arm' + ); + expect( + artifacts.getEngineType(TargetPlatform.ios, BuildMode.release), + 'ios-release' + ); + + expect( + artifacts.getEngineType(TargetPlatform.darwin_x64), + 'darwin-x64' + ); + }, overrides: { + Cache: () => new Cache(rootOverride: tempDir), + Platform: () => new FakePlatform(operatingSystem: 'linux') + }); + }); + + group('LocalEngineArtifacts', () { + + Directory tempDir; + LocalEngineArtifacts artifacts; + + setUp(() { + tempDir = fs.systemTempDirectory.createTempSync('flutter_temp'); + artifacts = new LocalEngineArtifacts(tempDir.path, fs.path.join(tempDir.path, 'out', 'android_debug_unopt')); + }); + + tearDown(() { + tempDir.deleteSync(recursive: true); + }); + + testUsingContext('getArtifactPath', () { + expect( + artifacts.getArtifactPath(Artifact.dartIoEntriesTxt, TargetPlatform.android_arm, BuildMode.debug), + fs.path.join(tempDir.path, 'dart', 'runtime', 'bin', 'dart_io_entries.txt') + ); + expect( + artifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, BuildMode.release), + fs.path.join(tempDir.path, 'out', 'android_debug_unopt', 'Flutter.framework') + ); + + expect( + artifacts.getArtifactPath(Artifact.skyShell), + fs.path.join(tempDir.path, 'out', 'android_debug_unopt', 'sky_shell') + ); + }, overrides: { + Platform: () => new FakePlatform(operatingSystem: 'linux') + }); + + testUsingContext('getEngineType', () { + expect( + artifacts.getEngineType(TargetPlatform.android_arm, BuildMode.debug), + 'android_debug_unopt' + ); + expect( + artifacts.getEngineType(TargetPlatform.ios, BuildMode.release), + 'android_debug_unopt' + ); + + expect( + artifacts.getEngineType(TargetPlatform.darwin_x64), + 'android_debug_unopt' + ); + }, overrides: { + Platform: () => new FakePlatform(operatingSystem: 'linux') + }); + }); +} \ No newline at end of file diff --git a/packages/flutter_tools/test/src/context.dart b/packages/flutter_tools/test/src/context.dart index c6b6087fff..f3230e34ed 100644 --- a/packages/flutter_tools/test/src/context.dart +++ b/packages/flutter_tools/test/src/context.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/config.dart'; import 'package:flutter_tools/src/base/context.dart'; import 'package:flutter_tools/src/base/file_system.dart'; @@ -17,7 +18,6 @@ import 'package:flutter_tools/src/doctor.dart'; import 'package:flutter_tools/src/ios/mac.dart'; import 'package:flutter_tools/src/ios/simulators.dart'; import 'package:flutter_tools/src/run_hot.dart'; -import 'package:flutter_tools/src/toolchain.dart'; import 'package:flutter_tools/src/usage.dart'; import 'package:mockito/mockito.dart'; @@ -53,7 +53,7 @@ void testUsingContext(String description, dynamic testMethod(), { testContext.putIfAbsent(Doctor, () => new MockDoctor()); testContext.putIfAbsent(HotRunnerConfig, () => new HotRunnerConfig()); testContext.putIfAbsent(Cache, () => new Cache()); - testContext.putIfAbsent(ToolConfiguration, () => new ToolConfiguration()); + testContext.putIfAbsent(Artifacts, () => new CachedArtifacts()); testContext.putIfAbsent(Config, () => new Config()); testContext.putIfAbsent(OperatingSystemUtils, () { MockOperatingSystemUtils os = new MockOperatingSystemUtils(); diff --git a/packages/flutter_tools/test/toolchain_test.dart b/packages/flutter_tools/test/toolchain_test.dart deleted file mode 100644 index 10fc3341e0..0000000000 --- a/packages/flutter_tools/test/toolchain_test.dart +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter_tools/src/base/file_system.dart'; -import 'package:flutter_tools/src/build_info.dart'; -import 'package:flutter_tools/src/cache.dart'; -import 'package:flutter_tools/src/toolchain.dart'; -import 'package:test/test.dart'; - -import 'src/context.dart'; - -void main() { - group('ToolConfiguration', () { - Directory tempDir; - tempDir = fs.systemTempDirectory.createTempSync('flutter_temp'); - - testUsingContext('using cache', () { - ToolConfiguration toolConfig = new ToolConfiguration(); - - expect( - toolConfig.getEngineArtifactsDirectory(TargetPlatform.android_arm, BuildMode.debug).path, - endsWith(fs.path.join('cache', 'artifacts', 'engine', 'android-arm')) - ); - expect( - toolConfig.getEngineArtifactsDirectory(TargetPlatform.android_arm, BuildMode.release).path, - endsWith(fs.path.join('cache', 'artifacts', 'engine', 'android-arm-release')) - ); - expect(tempDir, isNotNull); - tempDir.deleteSync(recursive: true); - }, overrides: { - Cache: () => new Cache(rootOverride: tempDir), - }); - - testUsingContext('using enginePath', () { - ToolConfiguration toolConfig = new ToolConfiguration(); - toolConfig.engineSrcPath = 'engine'; - toolConfig.engineBuildPath = 'engine/out/android_debug'; - - expect( - toolConfig.getEngineArtifactsDirectory(TargetPlatform.android_arm, BuildMode.debug).path, - 'engine/out/android_debug' - ); - }); - }); -}