dissallow -release mode on emulators (#4204)

* dissallow -release mode on emulators

* have the help text print the default mode
diff --git a/packages/flutter_tools/lib/src/base/process.dart b/packages/flutter_tools/lib/src/base/process.dart
index 8c9209a..4969545 100644
--- a/packages/flutter_tools/lib/src/base/process.dart
+++ b/packages/flutter_tools/lib/src/base/process.dart
@@ -77,6 +77,7 @@
 }
 
 /// Run cmd and return stdout.
+///
 /// Throws an error if cmd exits with a non-zero value.
 String runCheckedSync(List<String> cmd, {
   String workingDirectory, bool truncateCommand: false
diff --git a/packages/flutter_tools/lib/src/base/utils.dart b/packages/flutter_tools/lib/src/base/utils.dart
index 312739a..052e671 100644
--- a/packages/flutter_tools/lib/src/base/utils.dart
+++ b/packages/flutter_tools/lib/src/base/utils.dart
@@ -39,6 +39,12 @@
   return str;
 }
 
+String toTitleCase(String str) {
+  if (str.isEmpty)
+    return str;
+  return str.substring(0, 1).toUpperCase() + str.substring(1);
+}
+
 /// Return the plural of the given word (`cat(s)`).
 String pluralize(String word, int count) => count == 1 ? word : word + 's';
 
diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart
index efa53c1..76b6632 100644
--- a/packages/flutter_tools/lib/src/build_info.dart
+++ b/packages/flutter_tools/lib/src/build_info.dart
@@ -27,6 +27,9 @@
   return mode == BuildMode.profile || mode == BuildMode.release;
 }
 
+// Returns true if the given build mode can be used on emulators / simulators.
+bool isEmulatorBuildMode(BuildMode mode) => mode == BuildMode.debug;
+
 enum HostPlatform {
   darwin_x64,
   linux_x64,
diff --git a/packages/flutter_tools/lib/src/commands/build_aot.dart b/packages/flutter_tools/lib/src/commands/build_aot.dart
index c18bfdd..4915f1a 100644
--- a/packages/flutter_tools/lib/src/commands/build_aot.dart
+++ b/packages/flutter_tools/lib/src/commands/build_aot.dart
@@ -8,6 +8,7 @@
 import 'package:path/path.dart' as path;
 
 import '../base/process.dart';
+import '../base/utils.dart';
 import '../build_info.dart';
 import '../dart/sdk.dart';
 import '../globals.dart';
@@ -69,6 +70,8 @@
   return path.join(path.dirname(packageDir.resolveSymbolicLinksSync()), 'sdk_ext');
 }
 
+/// Build an AOT snapshot. Return `null` (and log to `printError`) if the method
+/// fails.
 String buildAotSnapshot(
   String mainPath,
   TargetPlatform platform,
@@ -76,8 +79,30 @@
   String outputPath: _kDefaultAotOutputDir,
   bool interpreter: false
 }) {
+  try {
+    return _buildAotSnapshot(
+      mainPath,
+      platform,
+      buildMode,
+      outputPath: outputPath,
+      interpreter: interpreter
+    );
+  } on String catch (error) {
+    // Catch the String exceptions thrown from the `runCheckedSync` methods below.
+    printError(error);
+    return null;
+  }
+}
+
+String _buildAotSnapshot(
+  String mainPath,
+  TargetPlatform platform,
+  BuildMode buildMode, {
+  String outputPath: _kDefaultAotOutputDir,
+  bool interpreter: false
+}) {
   if (!isAotBuildMode(buildMode)) {
-    printError('${getModeName(buildMode)} mode does not support AOT compilation.');
+    printError('${toTitleCase(getModeName(buildMode))} mode does not support AOT compilation.');
     return null;
   }
 
@@ -120,8 +145,7 @@
 
   String packagesPath = path.absolute(Directory.current.path, 'packages');
   if (!FileSystemEntity.isDirectorySync(packagesPath)) {
-    printStatus('Missing packages directory. Running `pub get` to work around\n' +
-               'https://github.com/dart-lang/sdk/issues/26362');
+    printStatus('Missing packages directory; running `pub get` (to work around https://github.com/dart-lang/sdk/issues/26362).');
     // We don't use [pubGet] because we explicitly want to avoid --no-package-symlinks.
     runCheckedSync(<String>[sdkBinaryName('pub'), 'get', '--no-precompile']);
   }
@@ -229,8 +253,10 @@
 
   genSnapshotCmd.add(mainPath);
 
-  printStatus('Building snapshot...');
-  runCheckedSync(genSnapshotCmd);
+  String typeName = path.basename(tools.getEngineArtifactsDirectory(platform, buildMode).path);
+  printStatus('Building snapshot in ${getModeName(buildMode)} mode ($typeName)...');
+
+  runCheckedSync(genSnapshotCmd, truncateCommand: true);
 
   // On iOS, we use Xcode to compile the snapshot into a static library that the
   // end-developer can link into their app.
diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart
index 702e8f3..caadd29 100644
--- a/packages/flutter_tools/lib/src/commands/run.dart
+++ b/packages/flutter_tools/lib/src/commands/run.dart
@@ -22,7 +22,7 @@
 
 abstract class RunCommandBase extends FlutterCommand {
   RunCommandBase() {
-    addBuildModeFlags();
+    addBuildModeFlags(defaultToRelease: false);
 
     argParser.addFlag('trace-startup',
         negatable: true,
@@ -99,6 +99,11 @@
       }
     }
 
+    if (deviceForCommand.isLocalEmulator && !isEmulatorBuildMode(getBuildMode())) {
+      printError('${toTitleCase(getModeName(getBuildMode()))} mode is not supported for emulators.');
+      return 1;
+    }
+
     DebuggingOptions options;
 
     if (getBuildMode() == BuildMode.release) {
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart
index 6f008e3..2917a5a 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -43,6 +43,8 @@
 
   bool get shouldRunPub => _usesPubOption && argResults['pub'];
 
+  BuildMode _defaultBuildMode;
+
   void usesTargetOption() {
     argParser.addOption('target',
       abbr: 't',
@@ -58,29 +60,31 @@
     _usesPubOption = true;
   }
 
-  void addBuildModeFlags() {
+  void addBuildModeFlags({ bool defaultToRelease: true }) {
+    _defaultBuildMode = defaultToRelease ? BuildMode.release : BuildMode.debug;
+
     argParser.addFlag('debug',
       negatable: false,
-      help: 'Build a debug version of your app (the default).');
+      help: 'Build a debug version of your app${defaultToRelease ? '' : ' (default mode)'}.');
     argParser.addFlag('profile',
       negatable: false,
-      help: 'Build a profile (ahead of time compilation) version of your app.');
+      help: 'Build a version of your app specialized for performance profiling.');
     argParser.addFlag('release',
       negatable: false,
-      help: 'Build a release version of your app.');
+      help: 'Build a release version of your app${defaultToRelease ? ' (default mode)' : ''}.');
   }
 
   BuildMode getBuildMode() {
     List<bool> modeFlags = <bool>[argResults['debug'], argResults['profile'], argResults['release']];
     if (modeFlags.where((bool flag) => flag).length > 1)
-      throw new UsageException('Only one of --debug, --profile, or --release should be specified.', null);
-
-    BuildMode mode = BuildMode.debug;
+      throw new UsageException('Only one of --debug, --profile, or --release can be specified.', null);
+    if (argResults['debug'])
+      return BuildMode.debug;
     if (argResults['profile'])
-      mode = BuildMode.profile;
+      return BuildMode.profile;
     if (argResults['release'])
-      mode = BuildMode.release;
-    return mode;
+      return BuildMode.release;
+    return _defaultBuildMode;
   }
 
   void _setupApplicationPackages() {