Add a --no-http flag to start command This flag builds a local FLX file and pushes that to the device instead of using an HTTP server.
diff --git a/packages/flutter_tools/lib/src/application_package.dart b/packages/flutter_tools/lib/src/application_package.dart index 09a2061..f705622 100644 --- a/packages/flutter_tools/lib/src/application_package.dart +++ b/packages/flutter_tools/lib/src/application_package.dart
@@ -66,16 +66,15 @@ ApplicationPackageStore({ this.android, this.iOS, this.iOSSimulator }); - ApplicationPackage getPackageForPlatform(BuildPlatform platform) { + ApplicationPackage getPackageForPlatform(TargetPlatform platform) { switch (platform) { - case BuildPlatform.android: + case TargetPlatform.android: return android; - case BuildPlatform.iOS: + case TargetPlatform.iOS: return iOS; - case BuildPlatform.iOSSimulator: + case TargetPlatform.iOSSimulator: return iOSSimulator; - case BuildPlatform.mac: - case BuildPlatform.linux: + case TargetPlatform.linux: return null; } } @@ -86,31 +85,32 @@ IOSApp iOSSimulator; for (BuildConfiguration config in configs) { - switch (config.platform) { - case BuildPlatform.android: + switch (config.targetPlatform) { + case TargetPlatform.android: assert(android == null); - String localPath = config.type == BuildType.prebuilt ? - await ArtifactStore.getPath(Artifact.flutterShell) : - path.join(config.buildDir, 'apks', AndroidApk._defaultName); - android = new AndroidApk(localPath: localPath); + if (config.type != BuildType.prebuilt) { + String localPath = path.join(config.buildDir, 'apks', AndroidApk._defaultName); + android = new AndroidApk(localPath: localPath); + } else { + Artifact artifact = ArtifactStore.getArtifact( + type: ArtifactType.shell, targetPlatform: TargetPlatform.android); + android = new AndroidApk(localPath: await ArtifactStore.getPath(artifact)); + } break; - case BuildPlatform.iOS: + case TargetPlatform.iOS: assert(iOS == null); assert(config.type != BuildType.prebuilt); iOS = new IOSApp(localPath: path.join(config.buildDir, IOSApp._defaultName)); break; - case BuildPlatform.iOSSimulator: + case TargetPlatform.iOSSimulator: assert(iOSSimulator == null); assert(config.type != BuildType.prebuilt); iOSSimulator = new IOSApp(localPath: path.join(config.buildDir, IOSApp._defaultName)); break; - case BuildPlatform.mac: - case BuildPlatform.linux: - // TODO(abarth): Support mac and linux targets. - assert(false); + case TargetPlatform.linux: break; } }
diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart index 9bd6a06..5e39e47 100644 --- a/packages/flutter_tools/lib/src/artifacts.dart +++ b/packages/flutter_tools/lib/src/artifacts.dart
@@ -10,15 +10,147 @@ import 'package:logging/logging.dart'; import 'package:path/path.dart' as path; +import 'build_configuration.dart'; + final Logger _logging = new Logger('sky_tools.artifacts'); -enum Artifact { - flutterCompiler, - flutterShell, - skyViewerMojo, +const String _kShellCategory = 'shell'; +const String _kViewerCategory = 'viewer'; + +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: + return 'android-arm'; + case TargetPlatform.iOS: + return 'ios-arm'; + case TargetPlatform.iOSSimulator: + return 'ios-x64'; + case TargetPlatform.linux: + return 'linux-x64'; + } +} + +// Keep in sync with https://github.com/flutter/engine/blob/master/sky/tools/big_red_button.py#L50 +String _getCloudStorageBaseUrl({String category, String platform, String revision}) { + if (platform == 'darwin-x64') { + // In the fullness of time, we'll have a consistent URL pattern for all of + // our artifacts, but, for the time being, darwin artifacts are stored in a + // different cloud storage bucket. + return 'https://storage.googleapis.com/mojo_infra/flutter/${platform}/${revision}/'; + } + return 'https://storage.googleapis.com/mojo/sky/${category}/${platform}/${revision}/'; +} + +enum ArtifactType { + snapshot, + shell, + viewer, +} + +class Artifact { + const Artifact._({ + this.name, + this.fileName, + this.category, + this.type, + this.hostPlatform, + this.targetPlatform + }); + + final String name; + final String fileName; + final String category; // TODO(abarth): Remove categories. + final ArtifactType type; + final HostPlatform hostPlatform; + final TargetPlatform targetPlatform; + + String get platform { + if (targetPlatform != null) + return _getNameForTargetPlatform(targetPlatform); + if (hostPlatform != null) + return _getNameForHostPlatform(hostPlatform); + assert(false); + return null; + } + + String getUrl(String revision) { + return _getCloudStorageBaseUrl(category: category, platform: platform, revision: revision) + fileName; + } + + // Whether the artifact needs to be marked as executable on disk. + bool get executable => type == ArtifactType.snapshot; } class ArtifactStore { + static const List<Artifact> knownArtifacts = const <Artifact>[ + const Artifact._( + name: 'Sky Shell', + fileName: 'SkyShell.apk', + category: _kShellCategory, + type: ArtifactType.shell, + targetPlatform: TargetPlatform.android + ), + const Artifact._( + name: 'Sky Snapshot', + fileName: 'sky_snapshot', + category: _kShellCategory, + type: ArtifactType.snapshot, + hostPlatform: HostPlatform.linux + ), + const Artifact._( + name: 'Sky Snapshot', + fileName: 'sky_snapshot', + category: _kShellCategory, + type: ArtifactType.snapshot, + hostPlatform: HostPlatform.mac + ), + const Artifact._( + name: 'Sky Viewer', + fileName: 'sky_viewer.mojo', + category: _kViewerCategory, + type: ArtifactType.viewer, + targetPlatform: TargetPlatform.android + ), + const Artifact._( + name: 'Sky Viewer', + fileName: 'sky_viewer.mojo', + category: _kViewerCategory, + type: ArtifactType.viewer, + targetPlatform: TargetPlatform.linux + ), + ]; + + static Artifact getArtifact({ + ArtifactType type, + HostPlatform hostPlatform, + TargetPlatform targetPlatform + }) { + for (Artifact artifact in ArtifactStore.knownArtifacts) { + if (type != null && + type != artifact.type) + continue; + if (hostPlatform != null && + artifact.hostPlatform != null && + hostPlatform != artifact.hostPlatform) + continue; + if (targetPlatform != null && + artifact.targetPlatform != null && + targetPlatform != artifact.targetPlatform) + continue; + return artifact; + } + return null; + } + static String packageRoot; static String _engineRevision; @@ -31,102 +163,68 @@ return _engineRevision; } - // Keep in sync with https://github.com/flutter/engine/blob/master/sky/tools/big_red_button.py#L50 - static String googleStorageUrl(String category, String platform) { - return 'https://storage.googleapis.com/mojo/sky/${category}/${platform}/${engineRevision}/'; + static String getCloudStorageBaseUrl(String category, String platform) { + return _getCloudStorageBaseUrl(category: category, platform: platform, revision: engineRevision); } static Future _downloadFile(String url, File file) async { - print('Downloading $url to ${file.path}.'); + _logging.info('Downloading $url to ${file.path}.'); HttpClient httpClient = new HttpClient(); HttpClientRequest request = await httpClient.getUrl(Uri.parse(url)); HttpClientResponse response = await request.close(); - _logging.fine('Received response'); - if (response.statusCode != 200) throw new Exception(response.reasonPhrase); + _logging.fine('Received response statusCode=${response.statusCode}'); + if (response.statusCode != 200) + throw new Exception(response.reasonPhrase); IOSink sink = file.openWrite(); await sink.addStream(response); await sink.close(); _logging.fine('Wrote file'); } - static Future<Directory> _cacheDir() async { + static Directory _getBaseCacheDir() { Directory cacheDir = new Directory(path.join(packageRoot, 'sky_tools', 'cache')); - if (!await cacheDir.exists()) { - await cacheDir.create(recursive: true); - } + if (!cacheDir.existsSync()) + cacheDir.createSync(recursive: true); return cacheDir; } - static Future<Directory> _engineSpecificCacheDir() async { - Directory cacheDir = await _cacheDir(); + static Directory _getCacheDirForArtifact(Artifact artifact) { + Directory baseDir = _getBaseCacheDir(); // For now, all downloaded artifacts are release mode host binaries so use // a path that mirrors a local release build. // TODO(jamesr): Add support for more configurations. String config = 'Release'; - Directory engineSpecificDir = new Directory(path.join(cacheDir.path, 'sky_engine', engineRevision, config)); - - if (!await engineSpecificDir.exists()) { - await engineSpecificDir.create(recursive: true); - } - return engineSpecificDir; - } - - // Whether the artifact needs to be marked as executable on disk. - static bool _needsToBeExecutable(Artifact artifact) { - return artifact == Artifact.flutterCompiler; + Directory artifactSpecificDir = new Directory(path.join( + baseDir.path, 'sky_engine', engineRevision, config, artifact.platform)); + if (!artifactSpecificDir.existsSync()) + artifactSpecificDir.createSync(recursive: true); + return artifactSpecificDir; } static Future<String> getPath(Artifact artifact) async { - Directory cacheDir = await _engineSpecificCacheDir(); - - String category; - String platform; - String name; - - switch (artifact) { - case Artifact.flutterCompiler: - category = 'shell'; - name = 'sky_snapshot'; - break; - case Artifact.flutterShell: - category = 'shell'; - platform = 'android-arm'; - name = 'SkyShell.apk'; - break; - case Artifact.skyViewerMojo: - category = 'viewer'; - name = 'sky_viewer.mojo'; - break; - } - - File cachedFile = new File(path.join(cacheDir.path, name)); - if (!await cachedFile.exists()) { - _logging.info('Downloading ${name} from the cloud, one moment please...'); - if (platform == null) { - if (!Platform.isLinux) - throw new Exception('Platform unsupported.'); - platform = 'linux-x64'; - } - String url = googleStorageUrl(category, platform) + name; - await _downloadFile(url, cachedFile); - if (_needsToBeExecutable(artifact)) { - ProcessResult result = await Process.run('chmod', ['u+x', cachedFile.path]); - if (result.exitCode != 0) throw new Exception(result.stderr); + Directory cacheDir = _getCacheDirForArtifact(artifact); + File cachedFile = new File(path.join(cacheDir.path, artifact.fileName)); + if (!cachedFile.existsSync()) { + print('Downloading ${artifact.name} from the cloud, one moment please...'); + await _downloadFile(artifact.getUrl(engineRevision), cachedFile); + if (artifact.executable) { + // TODO(abarth): We should factor this out into a separate function that + // can have a platform-specific implementation. + ProcessResult result = Process.runSync('chmod', ['u+x', cachedFile.path]); + if (result.exitCode != 0) + throw new Exception(result.stderr); } } return cachedFile.path; } - static Future clear() async { - Directory cacheDir = await _cacheDir(); + static void clear() { + Directory cacheDir = _getBaseCacheDir(); _logging.fine('Clearing cache directory ${cacheDir.path}'); - await cacheDir.delete(recursive: true); + cacheDir.deleteSync(recursive: true); } - static Future populate() async { - for (Artifact artifact in Artifact.values) { - _logging.fine('Populating cache with $artifact'); - await getPath(artifact); - } + static Future populate() { + return Future.wait(knownArtifacts.map((artifact) => getPath(artifact))); } }
diff --git a/packages/flutter_tools/lib/src/build_configuration.dart b/packages/flutter_tools/lib/src/build_configuration.dart index 0db0299e..5fc0356 100644 --- a/packages/flutter_tools/lib/src/build_configuration.dart +++ b/packages/flutter_tools/lib/src/build_configuration.dart
@@ -2,29 +2,48 @@ // 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:logging/logging.dart'; import 'package:path/path.dart' as path; +final Logger _logging = new Logger('sky_tools.build_configuration'); + enum BuildType { prebuilt, release, debug, } -enum BuildPlatform { - android, - iOS, - iOSSimulator, +enum HostPlatform { mac, linux, } +enum TargetPlatform { + android, + iOS, + iOSSimulator, + linux, +} + +HostPlatform getCurrentHostPlatform() { + if (Platform.isMacOS) + return HostPlatform.mac; + if (Platform.isLinux) + return HostPlatform.linux; + _logging.warning('Unsupported host platform, defaulting to Linux'); + return HostPlatform.linux; +} + class BuildConfiguration { - BuildConfiguration.prebuilt({ this.platform }) + BuildConfiguration.prebuilt({ this.hostPlatform, this.targetPlatform }) : type = BuildType.prebuilt, buildDir = null; BuildConfiguration.local({ this.type, - this.platform, + this.hostPlatform, + this.targetPlatform, String enginePath, String buildPath }) : buildDir = path.normalize(path.join(enginePath, buildPath)) { @@ -32,6 +51,7 @@ } final BuildType type; - final BuildPlatform platform; + final HostPlatform hostPlatform; + final TargetPlatform targetPlatform; final String buildDir; }
diff --git a/packages/flutter_tools/lib/src/commands/flutter_command_runner.dart b/packages/flutter_tools/lib/src/commands/flutter_command_runner.dart index b12c257..8f0b389 100644 --- a/packages/flutter_tools/lib/src/commands/flutter_command_runner.dart +++ b/packages/flutter_tools/lib/src/commands/flutter_command_runner.dart
@@ -27,8 +27,10 @@ negatable: false, help: 'Very noisy logging, including the output of all ' 'shell commands executed.'); + argParser.addOption('package-root', + help: 'Path to your packages directory.', defaultsTo: 'packages'); - argParser.addSeparator('Global build selection options:'); + argParser.addSeparator('Local build selection options:'); argParser.addFlag('debug', negatable: false, help: @@ -48,42 +50,40 @@ 'Automatically detect your engine src directory from an overridden Flutter package.' 'Useful if you are building Flutter locally and are using a dependency_override for' 'the Flutter package that points to your engine src directory.'); - argParser.addOption('engine-src-path', + argParser.addOption('engine-src-path', hide: true, help: 'Path to your engine src directory, if you are building Flutter locally. ' 'Ignored if neither debug nor release is set. Not normally required.'); - argParser.addOption('android-debug-build-path', + argParser.addOption('android-debug-build-path', hide: true, help: 'Path to your Android Debug out directory, if you are building Flutter locally. ' 'This path is relative to engine-src-path. Not normally required.', defaultsTo: 'out/android_Debug/'); - argParser.addOption('android-release-build-path', + argParser.addOption('android-release-build-path', hide: true, help: 'Path to your Android Release out directory, if you are building Flutter locally. ' 'This path is relative to engine-src-path. Not normally required.', defaultsTo: 'out/android_Release/'); - argParser.addOption('ios-debug-build-path', + argParser.addOption('ios-debug-build-path', hide: true, help: 'Path to your iOS Debug out directory, if you are building Flutter locally. ' 'This path is relative to engine-src-path. Not normally required.', defaultsTo: 'out/ios_Debug/'); - argParser.addOption('ios-release-build-path', + argParser.addOption('ios-release-build-path', hide: true, help: 'Path to your iOS Release out directory, if you are building Flutter locally. ' 'This path is relative to engine-src-path. Not normally required.', defaultsTo: 'out/ios_Release/'); - argParser.addOption('ios-sim-debug-build-path', + argParser.addOption('ios-sim-debug-build-path', hide: true, help: 'Path to your iOS Simulator Debug out directory, if you are building Sky locally. ' 'This path is relative to engine-src-path. Not normally required.', defaultsTo: 'out/ios_sim_Debug/'); - argParser.addOption('ios-sim-release-build-path', + argParser.addOption('ios-sim-release-build-path', hide: true, help: 'Path to your iOS Simulator Release out directory, if you are building Sky locally. ' 'This path is relative to engine-src-path. Not normally required.', defaultsTo: 'out/ios_sim_Release/'); - argParser.addOption('package-root', - help: 'Path to your packages directory.', defaultsTo: 'packages'); } List<BuildConfiguration> get buildConfigurations { @@ -124,6 +124,7 @@ String enginePath = globalResults['engine-src-path']; bool isDebug = globalResults['debug']; bool isRelease = globalResults['release']; + HostPlatform hostPlatform = getCurrentHostPlatform(); if (enginePath == null && globalResults['local-build']) { Directory flutterDir = new Directory(path.join(globalResults['package-root'], 'flutter')); @@ -141,7 +142,8 @@ List<BuildConfiguration> configs = <BuildConfiguration>[]; if (enginePath == null) { - configs.add(new BuildConfiguration.prebuilt(platform: BuildPlatform.android)); + configs.add(new BuildConfiguration.prebuilt( + hostPlatform: hostPlatform, targetPlatform: TargetPlatform.android)); } else { if (!FileSystemEntity.isDirectorySync(enginePath)) _logging.warning('$enginePath is not a valid directory'); @@ -152,7 +154,8 @@ if (isDebug) { configs.add(new BuildConfiguration.local( type: BuildType.debug, - platform: BuildPlatform.android, + hostPlatform: hostPlatform, + targetPlatform: TargetPlatform.android, enginePath: enginePath, buildPath: globalResults['android-debug-build-path'] )); @@ -160,14 +163,16 @@ if (Platform.isMacOS) { configs.add(new BuildConfiguration.local( type: BuildType.debug, - platform: BuildPlatform.iOS, + hostPlatform: hostPlatform, + targetPlatform: TargetPlatform.iOS, enginePath: enginePath, buildPath: globalResults['ios-debug-build-path'] )); configs.add(new BuildConfiguration.local( type: BuildType.debug, - platform: BuildPlatform.iOSSimulator, + hostPlatform: hostPlatform, + targetPlatform: TargetPlatform.iOSSimulator, enginePath: enginePath, buildPath: globalResults['ios-sim-debug-build-path'] )); @@ -177,7 +182,8 @@ if (isRelease) { configs.add(new BuildConfiguration.local( type: BuildType.release, - platform: BuildPlatform.android, + hostPlatform: hostPlatform, + targetPlatform: TargetPlatform.android, enginePath: enginePath, buildPath: globalResults['android-release-build-path'] )); @@ -185,14 +191,16 @@ if (Platform.isMacOS) { configs.add(new BuildConfiguration.local( type: BuildType.release, - platform: BuildPlatform.iOS, + hostPlatform: hostPlatform, + targetPlatform: TargetPlatform.iOS, enginePath: enginePath, buildPath: globalResults['ios-release-build-path'] )); configs.add(new BuildConfiguration.local( type: BuildType.release, - platform: BuildPlatform.iOSSimulator, + hostPlatform: hostPlatform, + targetPlatform: TargetPlatform.iOSSimulator, enginePath: enginePath, buildPath: globalResults['ios-sim-release-build-path'] ));
diff --git a/packages/flutter_tools/lib/src/commands/run_mojo.dart b/packages/flutter_tools/lib/src/commands/run_mojo.dart index bbab6ac..5853204 100644 --- a/packages/flutter_tools/lib/src/commands/run_mojo.dart +++ b/packages/flutter_tools/lib/src/commands/run_mojo.dart
@@ -9,6 +9,7 @@ import 'package:logging/logging.dart'; import 'package:path/path.dart' as path; +import '../build_configuration.dart'; import '../artifacts.dart'; import '../process.dart'; @@ -40,7 +41,7 @@ } Future<int> _runAndroid(String devtoolsPath, _MojoConfig mojoConfig, String appPath, List<String> additionalArgs) { - String skyViewerUrl = ArtifactStore.googleStorageUrl('viewer', 'android-arm'); + String skyViewerUrl = ArtifactStore.getCloudStorageBaseUrl('viewer', 'android-arm'); String command = _makePathAbsolute(devtoolsPath); String appName = path.basename(appPath); String appDir = path.dirname(appPath); @@ -65,7 +66,8 @@ } Future<int> _runLinux(String mojoPath, _MojoConfig mojoConfig, String appPath, List<String> additionalArgs) async { - String viewerPath = _makePathAbsolute(await ArtifactStore.getPath(Artifact.skyViewerMojo)); + Artifact artifact = ArtifactStore.getArtifact(type: ArtifactType.viewer, targetPlatform: TargetPlatform.linux); + String viewerPath = _makePathAbsolute(await ArtifactStore.getPath(artifact)); String mojoBuildType = mojoConfig == _MojoConfig.Debug ? 'Debug' : 'Release'; String mojoShellPath = _makePathAbsolute(path.join(mojoPath, 'out', mojoBuildType, 'mojo_shell')); List<String> cmd = [
diff --git a/packages/flutter_tools/lib/src/commands/start.dart b/packages/flutter_tools/lib/src/commands/start.dart index 33f9f46..2fb4701 100644 --- a/packages/flutter_tools/lib/src/commands/start.dart +++ b/packages/flutter_tools/lib/src/commands/start.dart
@@ -3,17 +3,21 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:io'; import 'package:logging/logging.dart'; import 'package:path/path.dart' as path; import '../application_package.dart'; import '../device.dart'; +import 'build.dart'; import 'flutter_command.dart'; import 'install.dart'; import 'stop.dart'; final Logger _logging = new Logger('sky_tools.start'); +const String _localBundlePath = 'app.flx'; +const bool _kUseServer = true; class StartCommand extends FlutterCommand { final String name = 'start'; @@ -31,13 +35,20 @@ defaultsTo: '.', abbr: 't', help: 'Target app path or filename to start.'); + argParser.addFlag('http', + negatable: true, + defaultsTo: true, + help: 'Use a local HTTP server to serve your app to your device.'); argParser.addFlag('boot', help: 'Boot the iOS Simulator if it isn\'t already running.'); } @override Future<int> runInProject() async { - await downloadApplicationPackagesAndConnectToDevices(); + await Future.wait([ + downloadToolchain(), + downloadApplicationPackagesAndConnectToDevices(), + ]); bool poke = argResults['poke']; if (!poke) { @@ -59,8 +70,19 @@ continue; if (device is AndroidDevice) { String target = path.absolute(argResults['target']); - if (await device.startServer(target, poke, argResults['checked'], package)) - startedSomething = true; + if (argResults['http']) { + if (await device.startServer(target, poke, argResults['checked'], package)) + startedSomething = true; + } else { + String mainPath = target; + if (FileSystemEntity.isDirectorySync(target)) + mainPath = path.join(target, 'lib', 'main.dart'); + BuildCommand builder = new BuildCommand(); + builder.inheritFromParent(this); + await builder.build(outputPath: _localBundlePath, mainPath: mainPath); + if (device.startBundle(package, _localBundlePath, poke, argResults['checked'])) + startedSomething = true; + } } else { if (await device.startApp(package)) startedSomething = true;
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index 75c994e..fa13654 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart
@@ -66,7 +66,7 @@ /// Check if the current version of the given app is already installed bool isAppInstalled(ApplicationPackage app); - BuildPlatform get platform; + TargetPlatform get platform; Future<int> logs({bool clear: false}); @@ -271,7 +271,7 @@ } @override - BuildPlatform get platform => BuildPlatform.iOS; + TargetPlatform get platform => TargetPlatform.iOS; /// Note that clear is not supported on iOS at this time. Future<int> logs({bool clear: false}) async { @@ -487,7 +487,7 @@ } @override - BuildPlatform get platform => BuildPlatform.iOSSimulator; + TargetPlatform get platform => TargetPlatform.iOSSimulator; Future<int> logs({bool clear: false}) async { if (!isConnected()) { @@ -695,6 +695,10 @@ return '${_getDeviceDataPath(app)}/${app.name}.sha1'; } + String _getDeviceBundlePath(ApplicationPackage app) { + return '${_getDeviceDataPath(app)}/dev.flx'; + } + String _getDeviceApkSha1(ApplicationPackage app) { return runCheckedSync([adbPath, 'shell', 'cat', _getDeviceSha1Path(app)]); } @@ -750,12 +754,45 @@ return true; } + void _forwardObservatoryPort() { + // Set up port forwarding for observatory. + String observatoryPortString = 'tcp:$_observatoryPort'; + runCheckedSync( + [adbPath, 'forward', observatoryPortString, observatoryPortString]); + } + + bool startBundle(AndroidApk apk, String bundlePath, bool poke, bool checked) { + if (!FileSystemEntity.isFileSync(bundlePath)) { + _logging.severe('Cannot find $bundlePath'); + return false; + } + + if (!poke) + _forwardObservatoryPort(); + + String deviceTmpPath = '/data/local/tmp/dev.flx'; + String deviceBundlePath = _getDeviceBundlePath(apk); + runCheckedSync([adbPath, 'push', bundlePath, deviceTmpPath]); + runCheckedSync([adbPath, 'shell', 'mv', deviceTmpPath, deviceBundlePath]); + List<String> cmd = [ + adbPath, + 'shell', 'am', 'start', + '-a', 'android.intent.action.RUN', + '-d', deviceBundlePath, + ]; + if (checked) + cmd.addAll(['--ez', 'enable-checked-mode', 'true']); + cmd.add(apk.launchActivity); + runCheckedSync(cmd); + return true; + } + Future<bool> startServer( String target, bool poke, bool checked, AndroidApk apk) async { String serverRoot = ''; String mainDart = ''; String missingMessage = ''; - if (await FileSystemEntity.isDirectory(target)) { + if (FileSystemEntity.isDirectorySync(target)) { serverRoot = target; mainDart = path.join(serverRoot, 'lib', 'main.dart'); missingMessage = 'Missing lib/main.dart in project: $serverRoot'; @@ -765,16 +802,13 @@ missingMessage = '$mainDart does not exist.'; } - if (!await FileSystemEntity.isFile(mainDart)) { + if (!FileSystemEntity.isFileSync(mainDart)) { _logging.severe(missingMessage); return false; } if (!poke) { - // Set up port forwarding for observatory. - String observatoryPortString = 'tcp:$_observatoryPort'; - runCheckedSync( - [adbPath, 'forward', observatoryPortString, observatoryPortString]); + _forwardObservatoryPort(); // Actually start the server. Process server = await Process.start( @@ -794,28 +828,20 @@ String relativeDartMain = _convertToURL(path.relative(mainDart, from: serverRoot)); String url = 'http://localhost:$_serverPort/$relativeDartMain'; - if (poke) { + if (poke) url += '?rand=${new Random().nextDouble()}'; - } // Actually launch the app on Android. List<String> cmd = [ adbPath, - 'shell', - 'am', - 'start', - '-a', - 'android.intent.action.VIEW', - '-d', - url, + 'shell', 'am', 'start', + '-a', 'android.intent.action.VIEW', + '-d', url, ]; - if (checked) { + if (checked) cmd.addAll(['--ez', 'enable-checked-mode', 'true']); - } cmd.add(apk.launchActivity); - runCheckedSync(cmd); - return true; } @@ -880,7 +906,7 @@ } @override - BuildPlatform get platform => BuildPlatform.android; + TargetPlatform get platform => TargetPlatform.android; void clearLogs() { runSync([adbPath, 'logcat', '-c']); @@ -985,24 +1011,20 @@ IOSSimulator iOSSimulator; for (BuildConfiguration config in configs) { - switch (config.platform) { - case BuildPlatform.android: + switch (config.targetPlatform) { + case TargetPlatform.android: assert(android == null); android = new AndroidDevice(); break; - case BuildPlatform.iOS: + case TargetPlatform.iOS: assert(iOS == null); iOS = new IOSDevice(); break; - case BuildPlatform.iOSSimulator: + case TargetPlatform.iOSSimulator: assert(iOSSimulator == null); iOSSimulator = new IOSSimulator(); break; - - case BuildPlatform.mac: - case BuildPlatform.linux: - // TODO(abarth): Support mac and linux targets. - assert(false); + case TargetPlatform.linux: break; } }
diff --git a/packages/flutter_tools/lib/src/toolchain.dart b/packages/flutter_tools/lib/src/toolchain.dart index 655e6b6..34301ec 100644 --- a/packages/flutter_tools/lib/src/toolchain.dart +++ b/packages/flutter_tools/lib/src/toolchain.dart
@@ -11,16 +11,16 @@ import 'process.dart'; class Compiler { - Compiler(this._compilerPath); + Compiler(this._path); - String _compilerPath; + String _path; Future<int> compile({ String mainPath, String snapshotPath }) { return runCommandAndStreamOutput([ - _compilerPath, + _path, mainPath, '--package-root=${ArtifactStore.packageRoot}', '--snapshot=$snapshotPath' @@ -28,18 +28,22 @@ } } +Future<String> _getCompilerPath(BuildConfiguration config) async { + if (config.type != BuildType.prebuilt) + return path.join(config.buildDir, 'clang_x64', 'sky_snapshot'); + Artifact artifact = ArtifactStore.getArtifact( + type: ArtifactType.snapshot, hostPlatform: config.hostPlatform); + return await ArtifactStore.getPath(artifact); +} + class Toolchain { Toolchain({ this.compiler }); final Compiler compiler; static Future<Toolchain> forConfigs(List<BuildConfiguration> configs) async { - // TODO(abarth): Add a notion of "host platform" to the build configs. - BuildConfiguration config = configs.first; - String compilerPath = config.type == BuildType.prebuilt ? - await ArtifactStore.getPath(Artifact.flutterCompiler) : - path.join(config.buildDir, 'clang_x64', 'sky_snapshot'); - + // TODO(abarth): Shouldn't we consider all the configs? + String compilerPath = await _getCompilerPath(configs.first); return new Toolchain(compiler: new Compiler(compilerPath)); } }