Commit f132acaf authored by Devon Carew's avatar Devon Carew

use the new cache code to locate more artifacts (#3361)

* use the new cache code to locate more artifacts

* add todo

* review comments
parent 4678c120
......@@ -47,7 +47,7 @@ class AndroidApk extends ApplicationPackage {
}
/// Creates a new AndroidApk based on the information in the Android manifest.
factory AndroidApk.fromBuildConfiguration(BuildConfiguration config) {
factory AndroidApk.fromCurrentDirectory() {
String manifestPath = path.join('android', 'AndroidManifest.xml');
if (!FileSystemEntity.isFileSync(manifestPath))
return null;
......@@ -82,8 +82,8 @@ class IOSApp extends ApplicationPackage {
String iosProjectBundleId
}) : super(localPath: iosProjectDir, id: iosProjectBundleId);
factory IOSApp.fromBuildConfiguration(BuildConfiguration config) {
if (getCurrentHostPlatform() != HostPlatform.mac)
factory IOSApp.fromCurrentDirectory() {
if (getCurrentHostPlatform() != HostPlatform.darwin_x64)
return null;
String plistPath = path.join('ios', 'Info.plist');
......@@ -99,9 +99,22 @@ class IOSApp extends ApplicationPackage {
String get displayName => id;
}
ApplicationPackage getApplicationPackageForPlatform(TargetPlatform platform) {
switch (platform) {
case TargetPlatform.android_arm:
case TargetPlatform.android_x64:
return new AndroidApk.fromCurrentDirectory();
case TargetPlatform.ios:
return new IOSApp.fromCurrentDirectory();
case TargetPlatform.darwin_x64:
case TargetPlatform.linux_x64:
return null;
}
}
class ApplicationPackageStore {
final AndroidApk android;
final IOSApp iOS;
AndroidApk android;
IOSApp iOS;
ApplicationPackageStore({ this.android, this.iOS });
......@@ -109,36 +122,14 @@ class ApplicationPackageStore {
switch (platform) {
case TargetPlatform.android_arm:
case TargetPlatform.android_x64:
android ??= new AndroidApk.fromCurrentDirectory();
return android;
case TargetPlatform.ios:
iOS ??= new IOSApp.fromCurrentDirectory();
return iOS;
case TargetPlatform.darwin_x64:
case TargetPlatform.linux_x64:
return null;
}
}
static ApplicationPackageStore forConfigs(List<BuildConfiguration> configs) {
AndroidApk android;
IOSApp iOS;
for (BuildConfiguration config in configs) {
switch (config.targetPlatform) {
case TargetPlatform.android_arm:
case TargetPlatform.android_x64:
android ??= new AndroidApk.fromBuildConfiguration(config);
break;
case TargetPlatform.ios:
iOS ??= new IOSApp.fromBuildConfiguration(config);
break;
case TargetPlatform.darwin_x64:
case TargetPlatform.linux_x64:
break;
}
}
return new ApplicationPackageStore(android: android, iOS: iOS);
}
}
......@@ -9,30 +9,6 @@ import 'package:path/path.dart' as path;
import 'build_configuration.dart';
import 'globals.dart';
String _getNameForHostPlatform(HostPlatform platform) {
switch (platform) {
case HostPlatform.linux:
return 'linux-x64';
case HostPlatform.mac:
return 'darwin-x64';
}
}
String getNameForTargetPlatform(TargetPlatform platform) {
switch (platform) {
case TargetPlatform.android_arm:
return 'android-arm';
case TargetPlatform.android_x64:
return 'android-x64';
case TargetPlatform.ios:
return 'ios';
case TargetPlatform.darwin_x64:
return 'darwin-x64';
case TargetPlatform.linux_x64:
return 'linux-x64';
}
}
enum ArtifactType {
snapshot,
shell,
......@@ -41,7 +17,6 @@ enum ArtifactType {
androidIcuData,
androidKeystore,
androidLibSkyShell,
iosXcodeProject,
}
class Artifact {
......@@ -63,7 +38,7 @@ class Artifact {
if (targetPlatform != null)
return getNameForTargetPlatform(targetPlatform);
if (hostPlatform != null)
return _getNameForHostPlatform(hostPlatform);
return getNameForHostPlatform(hostPlatform);
assert(false);
return null;
}
......@@ -84,13 +59,13 @@ class ArtifactStore {
name: 'Sky Snapshot',
fileName: 'sky_snapshot',
type: ArtifactType.snapshot,
hostPlatform: HostPlatform.linux
hostPlatform: HostPlatform.linux_x64
),
const Artifact._(
name: 'Sky Snapshot',
fileName: 'sky_snapshot',
type: ArtifactType.snapshot,
hostPlatform: HostPlatform.mac
hostPlatform: HostPlatform.darwin_x64
),
// mojo
......@@ -158,14 +133,6 @@ class ArtifactStore {
type: ArtifactType.androidLibSkyShell,
targetPlatform: TargetPlatform.android_x64
),
// iOS
const Artifact._(
name: 'iOS Runner (Xcode Project)',
fileName: 'FlutterXcode.zip',
type: ArtifactType.iosXcodeProject,
targetPlatform: TargetPlatform.ios
),
];
static Artifact getArtifact({
......
......@@ -34,6 +34,13 @@ String camelCase(String str) {
/// Return the plural of the given word (`cat(s)`).
String pluralize(String word, int count) => count == 1 ? word : word + 's';
/// Return the name of an enum item.
String getEnumName(dynamic enumItem) {
String name = '$enumItem';
int index = name.indexOf('.');
return index == -1 ? name : name.substring(index + 1);
}
File getUniqueFile(Directory dir, String baseName, String ext) {
int i = 1;
......
......@@ -6,6 +6,7 @@ import 'dart:io';
import 'package:path/path.dart' as path;
import 'base/utils.dart';
import 'globals.dart';
enum BuildType {
......@@ -22,15 +23,15 @@ enum BuildVariant {
deploy
}
String getVariantName(BuildVariant variant) {
String name = '$variant';
int index = name.indexOf('.');
return index == -1 ? name : name.substring(index + 1);
}
String getVariantName(BuildVariant variant) => getEnumName(variant);
enum HostPlatform {
mac,
linux,
darwin_x64,
linux_x64,
}
String getNameForHostPlatform(HostPlatform platform) {
return getEnumName(platform).replaceAll('_', '-');
}
enum TargetPlatform {
......@@ -41,13 +42,19 @@ enum TargetPlatform {
linux_x64
}
String getNameForTargetPlatform(TargetPlatform platform) {
return getEnumName(platform).replaceAll('_', '-');
}
HostPlatform getCurrentHostPlatform() {
if (Platform.isMacOS)
return HostPlatform.mac;
return HostPlatform.darwin_x64;
if (Platform.isLinux)
return HostPlatform.linux;
return HostPlatform.linux_x64;
printError('Unsupported host platform, defaulting to Linux');
return HostPlatform.linux;
return HostPlatform.linux_x64;
}
TargetPlatform getCurrentHostPlatformAsTarget() {
......
......@@ -15,16 +15,28 @@ import 'globals.dart';
/// A warpper around the `bin/cache/` directory.
class Cache {
/// [rootOverride] is configurable for testing.
Cache({ Directory rootOverride }) {
this._rootOverride = rootOverride;
}
Directory _rootOverride;
static Cache get instance => context[Cache] ?? (context[Cache] = new Cache());
/// Return the top-level directory in the cache; this is `bin/cache`.
Directory getRoot() => new Directory(path.join(ArtifactStore.flutterRoot, 'bin', 'cache'));
Directory getRoot() {
if (_rootOverride != null)
return new Directory(path.join(_rootOverride.path, 'bin', 'cache'));
else
return new Directory(path.join(ArtifactStore.flutterRoot, 'bin', 'cache'));
}
/// Return a directory in the cache dir. For `pkg`, this will return `bin/cache/pkg`.
Directory getCacheDir(String name) {
Directory dir = new Directory(path.join(getRoot().path, name));
if (!dir.existsSync())
dir.createSync();
dir.createSync(recursive: true);
return dir;
}
......
......@@ -25,7 +25,7 @@ class BuildIOSCommand extends FlutterCommand {
@override
Future<int> runInProject() async {
if (getCurrentHostPlatform() != HostPlatform.mac) {
if (getCurrentHostPlatform() != HostPlatform.darwin_x64) {
printError('Building for iOS is only supported on the Mac.');
return 1;
}
......
......@@ -8,9 +8,9 @@ import 'dart:io';
import '../android/android_device.dart';
import '../application_package.dart';
import '../artifacts.dart';
import '../base/context.dart';
import '../base/logger.dart';
import '../build_configuration.dart';
import '../device.dart';
import '../globals.dart';
import '../ios/devices.dart';
......@@ -264,7 +264,6 @@ class AppDomain extends Domain {
try {
int result = await startApp(
device,
command.applicationPackages,
command.toolchain,
command.buildConfigurations,
stop: true,
......
......@@ -304,8 +304,7 @@ void restoreAppStopper() {
Future<int> stopApp(DriveCommand command) async {
printTrace('Stopping application.');
ApplicationPackage package = command.applicationPackages
.getPackageForPlatform(command.device.platform);
ApplicationPackage package = command.applicationPackages.getPackageForPlatform(command.device.platform);
bool stopped = await command.device.stopApp(package);
return stopped ? 0 : 1;
}
......@@ -58,7 +58,6 @@ class ListenCommand extends RunCommandBase {
result = await startApp(
deviceForCommand,
applicationPackages,
toolchain,
buildConfigurations,
target: target,
......
......@@ -96,7 +96,6 @@ class RunCommand extends RunCommandBase {
int result = await startApp(
deviceForCommand,
applicationPackages,
toolchain,
buildConfigurations,
target: target,
......@@ -128,7 +127,6 @@ String _getMissingPackageHintForPlatform(TargetPlatform platform) {
Future<int> startApp(
Device device,
ApplicationPackageStore applicationPackages,
Toolchain toolchain,
List<BuildConfiguration> configs, {
String target,
......@@ -151,7 +149,7 @@ Future<int> startApp(
return 1;
}
ApplicationPackage package = applicationPackages.getPackageForPlatform(device.platform);
ApplicationPackage package = getApplicationPackageForPlatform(device.platform);
if (package == null) {
String message = 'No application found for ${device.platform}.';
......
......@@ -8,7 +8,6 @@ import 'dart:math' as math;
import 'android/android_device.dart';
import 'application_package.dart';
import 'artifacts.dart';
import 'base/common.dart';
import 'base/utils.dart';
import 'build_configuration.dart';
......
......@@ -8,12 +8,14 @@ import 'base/logger.dart';
import 'cache.dart';
import 'device.dart';
import 'doctor.dart';
import 'toolchain.dart';
DeviceManager get deviceManager => context[DeviceManager];
Logger get logger => context[Logger];
AndroidSdk get androidSdk => context[AndroidSdk];
Doctor get doctor => context[Doctor];
Cache get cache => Cache.instance;
ToolConfiguration get tools => ToolConfiguration.instance;
/// Display an error level message to the user. Commands should use this if they
/// fail in some way.
......
......@@ -99,13 +99,9 @@ Future<int> setupXcodeProjectHarness(String flutterProjectPath) async {
String iosFilesPath = path.join(flutterProjectPath, 'ios');
String xcodeprojPath = path.join(iosFilesPath, '.generated');
Artifact xcodeProject = ArtifactStore.getArtifact(
type: ArtifactType.iosXcodeProject,
targetPlatform: TargetPlatform.ios
);
String xcodeProjectPath = ArtifactStore.getPath(xcodeProject);
List<int> archiveBytes = new File(xcodeProjectPath).readAsBytesSync();
Directory toolDir = tools.getEngineArtifactsDirectory(TargetPlatform.ios, BuildVariant.develop);
File archiveFile = new File(path.join(toolDir.path, 'FlutterXcode.zip'));
List<int> archiveBytes = archiveFile.readAsBytesSync();
if (archiveBytes.isEmpty) {
printError('Error: No archive bytes received.');
......
......@@ -65,7 +65,7 @@ abstract class FlutterCommand extends Command {
}
void _setupApplicationPackages() {
applicationPackages ??= ApplicationPackageStore.forConfigs(buildConfigurations);
applicationPackages ??= new ApplicationPackageStore();
}
@override
......
......@@ -17,6 +17,7 @@ import '../base/process.dart';
import '../build_configuration.dart';
import '../globals.dart';
import '../package_map.dart';
import '../toolchain.dart';
import 'version.dart';
const String kFlutterRootEnvironmentVariableName = 'FLUTTER_ROOT'; // should point to //flutter/ (root of flutter/flutter repo)
......@@ -79,6 +80,7 @@ class FlutterCommandRunner extends CommandRunner {
'Defaults to \$$kFlutterEngineEnvironmentVariableName if set, otherwise defaults to the path given in your pubspec.yaml\n'
'dependency_overrides for $kFlutterEnginePackageName, if any, or, failing that, tries to guess at the location\n'
'based on the value of the --flutter-root option.');
argParser.addOption('host-debug-build-path',
hide: !verboseHelp,
help:
......@@ -91,6 +93,7 @@ class FlutterCommandRunner extends CommandRunner {
'Path to your host Release out directory (i.e. the one that runs on your workstation, not a device), if you are building Flutter locally.\n'
'This path is relative to --engine-src-path. Not normally required.',
defaultsTo: 'out/Release/');
argParser.addOption('android-debug-build-path',
hide: !verboseHelp,
help:
......@@ -209,6 +212,16 @@ class FlutterCommandRunner extends CommandRunner {
// See if the user specified a specific device.
deviceManager.specifiedDeviceId = globalResults['device-id'];
// Set up the tooling configuration.
if (enginePath != null) {
ToolConfiguration.instance.engineSrcPath = enginePath;
if (globalResults.wasParsed('release'))
ToolConfiguration.instance.release = globalResults['release'];
if (globalResults.wasParsed('debug'))
ToolConfiguration.instance.release = !globalResults['debug'];
}
// The Android SDK could already have been set by tests.
if (!context.isSet(AndroidSdk)) {
if (enginePath != null) {
......@@ -287,17 +300,17 @@ class FlutterCommandRunner extends CommandRunner {
targetPlatform: TargetPlatform.android_x64
));
if (hostPlatform == HostPlatform.linux) {
if (hostPlatform == HostPlatform.linux_x64) {
configs.add(new BuildConfiguration.prebuilt(
hostPlatform: HostPlatform.linux,
hostPlatform: HostPlatform.linux_x64,
targetPlatform: TargetPlatform.linux_x64,
testable: true
));
}
if (hostPlatform == HostPlatform.mac) {
if (hostPlatform == HostPlatform.darwin_x64) {
configs.add(new BuildConfiguration.prebuilt(
hostPlatform: HostPlatform.mac,
hostPlatform: HostPlatform.darwin_x64,
targetPlatform: TargetPlatform.ios
));
}
......
......@@ -8,8 +8,11 @@ import 'dart:io';
import 'package:path/path.dart' as path;
import 'artifacts.dart';
import 'base/context.dart';
import 'base/process.dart';
import 'build_configuration.dart';
import 'cache.dart';
import 'globals.dart';
import 'package_map.dart';
class SnapshotCompiler {
......@@ -37,6 +40,8 @@ class SnapshotCompiler {
}
}
// TODO(devoncarew): This should instead take a host platform and target platform.
String _getCompilerPath(BuildConfiguration config) {
if (config.type != BuildType.prebuilt) {
String compilerPath = path.join(config.buildDir, 'clang_x64', 'sky_snapshot');
......@@ -66,3 +71,99 @@ class Toolchain {
return null;
}
}
/// 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 {
/// [overrideCache] is configurable for testing.
ToolConfiguration({ Cache overrideCache }) {
_cache = overrideCache ?? cache;
}
Cache _cache;
static ToolConfiguration get instance {
if (context[ToolConfiguration] == null)
context[ToolConfiguration] = new ToolConfiguration();
return context[ToolConfiguration];
}
/// Override using the artifacts from the cache directory (--engine-src-path).
String engineSrcPath;
/// The engine mode to use (only relevent when [engineSrcPath] is set).
bool release;
/// Used to override the directory calculated from engineSrcPath (--engine-out-dir).
String engineOutDir;
String get _modeStr => release ? 'Release' : 'Debug';
/// The directory that contains development tools for the given platform. This
/// includes things like `sky_shell` and `sky_snapshot`.
///
/// If [platform] is not specified it defaults to [getCurrentHostPlatform].
Directory getToolsDirectory({ HostPlatform platform }) {
Directory dir = _getToolsDirectory(platform: platform);
if (dir != null)
printTrace('Using engine tools dir: ${dir.path}');
return dir;
}
Directory _getToolsDirectory({ HostPlatform platform }) {
platform ??= getCurrentHostPlatform();
if (engineSrcPath != null) {
return new Directory(path.join(engineSrcPath, 'out/$_modeStr'));
} else {
Directory engineDir = _cache.getArtifactDirectory('engine');
return new Directory(path.join(engineDir.path, getNameForHostPlatform(platform)));
}
}
/// Return the directory that contains engine artifacts for the given targets.
/// This directory might contain artifacts like `libsky_shell.so`.
Directory getEngineArtifactsDirectory(TargetPlatform platform, BuildVariant variant) {
Directory dir = _getEngineArtifactsDirectory(platform, variant);
if (dir != null)
printTrace('Using engine artifacts dir: ${dir.path}');
return dir;
}
Directory _getEngineArtifactsDirectory(TargetPlatform platform, BuildVariant variant) {
if (engineOutDir != null) {
return new Directory(engineOutDir);
} else if (engineSrcPath != null) {
String type;
switch (platform) {
case TargetPlatform.android_arm:
type = 'android';
break;
case TargetPlatform.android_x64:
type = 'android_sim';
break;
// TODO(devoncarew): We will need an ios vs ios_x86 target (for ios vs. ios_sim).
case TargetPlatform.ios:
type = 'ios';
break;
// These targets don't have engine artifacts.
case TargetPlatform.darwin_x64:
case TargetPlatform.linux_x64:
return null;
}
// Return something like 'out/android_Release'.
return new Directory(path.join(engineSrcPath, 'out/${type}_$_modeStr'));
} else {
// TODO(devoncarew): We'll want to suffix the directory name with the variant.
String dirName = getNameForTargetPlatform(platform);
Directory engineDir = _cache.getArtifactDirectory('engine');
return new Directory(path.join(engineDir.path, dirName));
}
}
}
......@@ -25,6 +25,7 @@ import 'os_utils_test.dart' as os_utils_test;
import 'run_test.dart' as run_test;
import 'service_protocol_test.dart' as service_protocol_test;
import 'stop_test.dart' as stop_test;
import 'toolchain_test.dart' as toolchain_test;
import 'trace_test.dart' as trace_test;
import 'upgrade_test.dart' as upgrade_test;
......@@ -47,6 +48,7 @@ void main() {
run_test.main();
service_protocol_test.main();
stop_test.main();
toolchain_test.main();
trace_test.main();
upgrade_test.main();
}
// 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 'dart:io';
import 'package:flutter_tools/src/build_configuration.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;
setUp(() {
tempDir = Directory.systemTemp.createTempSync('flutter_temp');
});
tearDown(() {
tempDir.deleteSync(recursive: true);
});
testUsingContext('using cache', () {
ToolConfiguration toolConfig = new ToolConfiguration(
overrideCache: new Cache(rootOverride: tempDir)
);
expect(
toolConfig.getToolsDirectory(platform: HostPlatform.linux_x64).path,
endsWith('cache/artifacts/engine/linux-x64')
);
expect(
toolConfig.getEngineArtifactsDirectory(TargetPlatform.android_arm, BuildVariant.develop).path,
endsWith('cache/artifacts/engine/android-arm')
);
expect(
toolConfig.getEngineArtifactsDirectory(TargetPlatform.android_arm, BuildVariant.deploy).path,
endsWith('cache/artifacts/engine/android-arm')
);
});
testUsingContext('using enginePath', () {
ToolConfiguration toolConfig = new ToolConfiguration();
toolConfig.engineSrcPath = 'engine';
toolConfig.release = true;
expect(
toolConfig.getToolsDirectory(platform: HostPlatform.linux_x64).path,
'engine/out/Release'
);
expect(
toolConfig.getEngineArtifactsDirectory(TargetPlatform.android_arm, BuildVariant.develop).path,
'engine/out/android_Release'
);
toolConfig.release = false;
expect(
toolConfig.getToolsDirectory(platform: HostPlatform.linux_x64).path,
'engine/out/Debug'
);
});
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment