add --dart-defines option (#44083)

diff --git a/packages/flutter_tools/lib/src/aot.dart b/packages/flutter_tools/lib/src/aot.dart
index 71e1558..50be745 100644
--- a/packages/flutter_tools/lib/src/aot.dart
+++ b/packages/flutter_tools/lib/src/aot.dart
@@ -34,6 +34,7 @@
     Iterable<DarwinArch> iosBuildArchs = defaultIOSArchs,
     List<String> extraFrontEndOptions,
     List<String> extraGenSnapshotOptions,
+    @required List<String> dartDefines,
   }) async {
     if (platform == null) {
       throwToolExit('No AOT build platform specified');
@@ -78,6 +79,7 @@
         trackWidgetCreation: false,
         outputPath: outputPath,
         extraFrontEndOptions: extraFrontEndOptions,
+        dartDefines: dartDefines,
       );
       if (kernelOut == null) {
         throwToolExit('Compiler terminated unexpectedly.');
diff --git a/packages/flutter_tools/lib/src/base/build.dart b/packages/flutter_tools/lib/src/base/build.dart
index d0f1642..9a70a94 100644
--- a/packages/flutter_tools/lib/src/base/build.dart
+++ b/packages/flutter_tools/lib/src/base/build.dart
@@ -285,6 +285,7 @@
     @required String packagesPath,
     @required String outputPath,
     @required bool trackWidgetCreation,
+    @required List<String> dartDefines,
     List<String> extraFrontEndOptions = const <String>[],
   }) async {
     final FlutterProject flutterProject = FlutterProject.current();
@@ -315,6 +316,7 @@
       aot: true,
       buildMode: buildMode,
       trackWidgetCreation: trackWidgetCreation,
+      dartDefines: dartDefines,
     ));
 
     // Write path to frontend_server, since things need to be re-generated when that changes.
diff --git a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
index 36537c3..3613dad 100644
--- a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
+++ b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
@@ -46,6 +46,7 @@
     @required FlutterProject flutterProject,
     @required bool ipv6,
     @required DebuggingOptions debuggingOptions,
+    @required List<String> dartDefines,
   }) {
     if (featureFlags.isWebIncrementalCompilerEnabled) {
       return _ExperimentalResidentWebRunner(
@@ -55,6 +56,7 @@
         debuggingOptions: debuggingOptions,
         ipv6: ipv6,
         stayResident: stayResident,
+        dartDefines: dartDefines,
       );
     }
     return _DwdsResidentWebRunner(
@@ -64,6 +66,7 @@
       debuggingOptions: debuggingOptions,
       ipv6: ipv6,
       stayResident: stayResident,
+      dartDefines: dartDefines,
     );
   }
 }
@@ -77,6 +80,7 @@
     @required bool ipv6,
     @required DebuggingOptions debuggingOptions,
     bool stayResident = true,
+    @required this.dartDefines,
   }) : super(
           <FlutterDevice>[],
           target: target ?? fs.path.join('lib', 'main.dart'),
@@ -87,6 +91,7 @@
 
   final FlutterDevice device;
   final FlutterProject flutterProject;
+  final List<String> dartDefines;
   DateTime firstBuildTime;
 
   // Only the debug builds of the web support the service protocol.
@@ -348,6 +353,7 @@
     @required bool ipv6,
     @required DebuggingOptions debuggingOptions,
     bool stayResident = true,
+    @required List<String> dartDefines,
   }) : super(
           device,
           flutterProject: flutterProject,
@@ -355,6 +361,7 @@
           debuggingOptions: debuggingOptions,
           ipv6: ipv6,
           stayResident: stayResident,
+          dartDefines: dartDefines,
         );
 
   @override
@@ -540,6 +547,7 @@
     @required bool ipv6,
     @required DebuggingOptions debuggingOptions,
     bool stayResident = true,
+    @required List<String> dartDefines,
   }) : super(
           device,
           flutterProject: flutterProject,
@@ -547,6 +555,7 @@
           debuggingOptions: debuggingOptions,
           ipv6: ipv6,
           stayResident: stayResident,
+          dartDefines: dartDefines,
         );
 
   @override
@@ -594,6 +603,7 @@
           hostname: debuggingOptions.hostname,
           port: debuggingOptions.port,
           skipDwds: device is WebServerDevice || !debuggingOptions.buildInfo.isDebug,
+          dartDefines: dartDefines,
         );
         // When connecting to a browser, update the message with a seemsSlow notification
         // to handle the case where we fail to connect.
diff --git a/packages/flutter_tools/lib/src/build_runner/web_fs.dart b/packages/flutter_tools/lib/src/build_runner/web_fs.dart
index da25e08..688d2d3 100644
--- a/packages/flutter_tools/lib/src/build_runner/web_fs.dart
+++ b/packages/flutter_tools/lib/src/build_runner/web_fs.dart
@@ -81,6 +81,7 @@
   @required bool initializePlatform,
   @required String hostname,
   @required String port,
+  @required List<String> dartDefines,
 });
 
 /// The dev filesystem responsible for building and serving  web applications.
@@ -97,6 +98,7 @@
     this._target,
     this._buildInfo,
     this._initializePlatform,
+    this._dartDefines,
   );
 
   /// The server uri.
@@ -111,6 +113,7 @@
   final String _target;
   final BuildInfo _buildInfo;
   final bool _initializePlatform;
+  final List<String> _dartDefines;
   StreamSubscription<void> _connectedApps;
 
   static const String _kHostName = 'localhost';
@@ -146,7 +149,7 @@
   /// Recompile the web application and return whether this was successful.
   Future<bool> recompile() async {
     if (!_useBuildRunner) {
-      await buildWeb(_flutterProject, _target, _buildInfo, _initializePlatform);
+      await buildWeb(_flutterProject, _target, _buildInfo, _initializePlatform, _dartDefines);
       return true;
     }
     _client.startBuild();
@@ -173,6 +176,7 @@
     @required bool initializePlatform,
     @required String hostname,
     @required String port,
+    @required List<String> dartDefines,
   }) async {
     // workaround for https://github.com/flutter/flutter/issues/38290
     if (!flutterProject.dartTool.existsSync()) {
@@ -302,7 +306,7 @@
         handler = pipeline.addHandler(proxyHandler('http://localhost:$daemonAssetPort/web/'));
       }
     } else {
-      await buildWeb(flutterProject, target, buildInfo, initializePlatform);
+      await buildWeb(flutterProject, target, buildInfo, initializePlatform, dartDefines);
       firstBuildCompleter.complete(true);
     }
 
@@ -325,6 +329,7 @@
       target,
       buildInfo,
       initializePlatform,
+      dartDefines,
     );
     if (!await firstBuildCompleter.future) {
       throw const BuildException();
diff --git a/packages/flutter_tools/lib/src/build_system/targets/dart.dart b/packages/flutter_tools/lib/src/build_system/targets/dart.dart
index 8f00e82..392cc34 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/dart.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/dart.dart
@@ -7,6 +7,7 @@
 import '../../base/file_system.dart';
 import '../../build_info.dart';
 import '../../compile.dart';
+import '../../convert.dart';
 import '../../globals.dart';
 import '../../project.dart';
 import '../build_system.dart';
@@ -50,6 +51,9 @@
 /// If provided, must be used along with [kFileSystemScheme].
 const String kFileSystemRoots = 'FileSystemRoots';
 
+/// Defines specified via the `--dart-define` command-line option.
+const String kDartDefines = 'DartDefines';
+
 /// The define to control what iOS architectures are built for.
 ///
 /// This is expected to be a comma-separated list of architectures. If not
@@ -208,6 +212,7 @@
       extraFrontEndOptions: extraFrontEndOptions,
       fileSystemRoots: fileSystemRoots,
       fileSystemScheme: fileSystemScheme,
+      dartDefines: parseDartDefines(environment),
     );
     if (output == null || output.errorCount != 0) {
       throw Exception('Errors during snapshot creation: $output');
@@ -357,3 +362,22 @@
     AotElfRelease(),
   ];
 }
+
+/// Dart defines are encoded inside [Environment] as a JSON array.
+List<String> parseDartDefines(Environment environment) {
+  if (!environment.defines.containsKey(kDartDefines)) {
+    return const <String>[];
+  }
+
+  final String dartDefinesJson = environment.defines[kDartDefines];
+  try {
+    final List<Object> parsedDefines = jsonDecode(dartDefinesJson);
+    return parsedDefines.cast<String>();
+  } on FormatException catch (_) {
+    throw Exception(
+      'The value of -D$kDartDefines is not formatted correctly.\n'
+      'The value must be a JSON-encoded list of strings but was:\n'
+      '$dartDefinesJson'
+    );
+  }
+}
diff --git a/packages/flutter_tools/lib/src/build_system/targets/web.dart b/packages/flutter_tools/lib/src/build_system/targets/web.dart
index 4c4946f..11b01ec 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/web.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/web.dart
@@ -130,6 +130,7 @@
       ? PackageMap.globalGeneratedPackagesPath
       : PackageMap.globalPackagesPath;
     final File outputFile = environment.buildDir.childFile('main.dart.js');
+
     final ProcessResult result = await processManager.run(<String>[
       artifacts.getArtifactPath(Artifact.engineDartBinary),
       artifacts.getArtifactPath(Artifact.dart2jsSnapshot),
@@ -147,6 +148,8 @@
         '-Ddart.vm.profile=true'
       else
         '-Ddart.vm.product=true',
+      for (String dartDefine in parseDartDefines(environment))
+        '-D$dartDefine',
       environment.buildDir.childFile('main.dart').path,
     ]);
     if (result.exitCode != 0) {
diff --git a/packages/flutter_tools/lib/src/codegen.dart b/packages/flutter_tools/lib/src/codegen.dart
index bd66869..a85bd86 100644
--- a/packages/flutter_tools/lib/src/codegen.dart
+++ b/packages/flutter_tools/lib/src/codegen.dart
@@ -109,6 +109,7 @@
     TargetModel targetModel = TargetModel.flutter,
     String initializeFromDill,
     String platformDill,
+    List<String> dartDefines,
   }) async {
     if (fileSystemRoots != null || fileSystemScheme != null || depFilePath != null || targetModel != null || sdkRoot != null || packagesPath != null) {
       printTrace('fileSystemRoots, fileSystemScheme, depFilePath, targetModel,'
@@ -147,6 +148,7 @@
       depFilePath: depFilePath,
       targetModel: targetModel,
       initializeFromDill: initializeFromDill,
+      dartDefines: dartDefines,
     );
   }
 }
@@ -172,6 +174,7 @@
     String initializeFromDill,
     bool runCold = false,
     TargetPlatform targetPlatform,
+    @required List<String> dartDefines,
   }) async {
     codeGenerator.updatePackages(flutterProject);
     final ResidentCompiler residentCompiler = ResidentCompiler(
@@ -191,6 +194,7 @@
       targetModel: TargetModel.flutter,
       unsafePackageSerialization: unsafePackageSerialization,
       initializeFromDill: initializeFromDill,
+      dartDefines: dartDefines,
     );
     if (runCold) {
       return residentCompiler;
diff --git a/packages/flutter_tools/lib/src/commands/attach.dart b/packages/flutter_tools/lib/src/commands/attach.dart
index d6aec17..b9f35b5 100644
--- a/packages/flutter_tools/lib/src/commands/attach.dart
+++ b/packages/flutter_tools/lib/src/commands/attach.dart
@@ -61,6 +61,7 @@
     usesIpv6Flag();
     usesFilesystemOptions(hide: !verboseHelp);
     usesFuchsiaOptions(hide: !verboseHelp);
+    usesDartDefines();
     argParser
       ..addOption(
         'debug-port',
@@ -274,6 +275,7 @@
         target: argResults['target'],
         targetModel: TargetModel(argResults['target-model']),
         buildMode: getBuildMode(),
+        dartDefines: dartDefines,
       );
       flutterDevice.observatoryUris = <Uri>[ observatoryUri ];
       final List<FlutterDevice> flutterDevices =  <FlutterDevice>[flutterDevice];
diff --git a/packages/flutter_tools/lib/src/commands/build_aot.dart b/packages/flutter_tools/lib/src/commands/build_aot.dart
index b69b1bc..92a8f86 100644
--- a/packages/flutter_tools/lib/src/commands/build_aot.dart
+++ b/packages/flutter_tools/lib/src/commands/build_aot.dart
@@ -18,6 +18,7 @@
     usesTargetOption();
     addBuildModeFlags();
     usesPubOption();
+    usesDartDefines();
     argParser
       ..addOption('output-dir', defaultsTo: getAotBuildDirectory())
       ..addOption('target-platform',
@@ -86,6 +87,7 @@
       iosBuildArchs: argResults['ios-arch'].map<DarwinArch>(getIOSArchForName),
       extraFrontEndOptions: argResults[FlutterOptions.kExtraFrontEndOptions],
       extraGenSnapshotOptions: argResults[FlutterOptions.kExtraGenSnapshotOptions],
+      dartDefines: dartDefines,
     );
     return null;
   }
diff --git a/packages/flutter_tools/lib/src/commands/build_ios_framework.dart b/packages/flutter_tools/lib/src/commands/build_ios_framework.dart
index 12d9f36..07e8199 100644
--- a/packages/flutter_tools/lib/src/commands/build_ios_framework.dart
+++ b/packages/flutter_tools/lib/src/commands/build_ios_framework.dart
@@ -35,6 +35,7 @@
     usesTargetOption();
     usesFlavorOption();
     usesPubOption();
+    usesDartDefines();
     argParser
       ..addFlag('debug',
         negatable: true,
@@ -294,6 +295,7 @@
       quiet: true,
       reportTimings: false,
       iosBuildArchs: <DarwinArch>[DarwinArch.armv7, DarwinArch.arm64],
+      dartDefines: dartDefines,
     );
 
     const String appFrameworkName = 'App.framework';
diff --git a/packages/flutter_tools/lib/src/commands/build_web.dart b/packages/flutter_tools/lib/src/commands/build_web.dart
index e731150..60b5863 100644
--- a/packages/flutter_tools/lib/src/commands/build_web.dart
+++ b/packages/flutter_tools/lib/src/commands/build_web.dart
@@ -18,6 +18,7 @@
     usesTargetOption();
     usesPubOption();
     addBuildModeFlags(excludeDebug: true);
+    usesDartDefines();
     argParser.addFlag('web-initialize-platform',
         defaultsTo: true,
         negatable: true,
@@ -53,7 +54,13 @@
     if (buildInfo.isDebug) {
       throwToolExit('debug builds cannot be built directly for the web. Try using "flutter run"');
     }
-    await buildWeb(flutterProject, target, buildInfo, argResults['web-initialize-platform']);
+    await buildWeb(
+      flutterProject,
+      target,
+      buildInfo,
+      argResults['web-initialize-platform'],
+      dartDefines,
+    );
     return null;
   }
 }
diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart
index d37bfe0..fed2bd0 100644
--- a/packages/flutter_tools/lib/src/commands/daemon.dart
+++ b/packages/flutter_tools/lib/src/commands/daemon.dart
@@ -424,6 +424,7 @@
       viewFilter: isolateFilter,
       target: target,
       buildMode: options.buildInfo.mode,
+      dartDefines: command?.dartDefines,
     );
 
     ResidentRunner runner;
@@ -436,6 +437,7 @@
         debuggingOptions: options,
         ipv6: ipv6,
         stayResident: true,
+        dartDefines: command?.dartDefines,
       );
     } else if (enableHotReload) {
       runner = HotRunner(
diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart
index b410da2..6f10357 100644
--- a/packages/flutter_tools/lib/src/commands/run.dart
+++ b/packages/flutter_tools/lib/src/commands/run.dart
@@ -31,6 +31,7 @@
   // Used by run and drive commands.
   RunCommandBase({ bool verboseHelp = false }) {
     addBuildModeFlags(defaultToRelease: false, verboseHelp: verboseHelp);
+    usesDartDefines();
     usesFlavorOption();
     argParser
       ..addFlag('trace-startup',
@@ -426,6 +427,7 @@
           experimentalFlags: expFlags,
           target: argResults['target'],
           buildMode: getBuildMode(),
+          dartDefines: dartDefines,
         ),
     ];
     // Only support "web mode" with a single web device due to resident runner
@@ -459,6 +461,7 @@
         ipv6: ipv6,
         debuggingOptions: _createDebuggingOptions(),
         stayResident: stayResident,
+        dartDefines: dartDefines,
       );
     } else {
       runner = ColdRunner(
diff --git a/packages/flutter_tools/lib/src/compile.dart b/packages/flutter_tools/lib/src/compile.dart
index 4dfeba8..d31d1d0 100644
--- a/packages/flutter_tools/lib/src/compile.dart
+++ b/packages/flutter_tools/lib/src/compile.dart
@@ -288,6 +288,7 @@
     String fileSystemScheme,
     String initializeFromDill,
     String platformDill,
+    @required List<String> dartDefines,
   }) async {
     final String frontendServer = artifacts.getArtifactPath(
       Artifact.frontendServerSnapshotForEngineDartSdk
@@ -316,6 +317,8 @@
       sdkRoot,
       '--target=$targetModel',
       '-Ddart.developer.causal_async_stacks=$causalAsyncStacks',
+      for (Object dartDefine in dartDefines)
+        '-D$dartDefine',
       ..._buildModeOptions(buildMode),
       if (trackWidgetCreation) '--track-widget-creation',
       if (!linkPlatformKernelIn) '--no-link-platform',
@@ -464,6 +467,7 @@
     bool unsafePackageSerialization,
     List<String> experimentalFlags,
     String platformDill,
+    List<String> dartDefines,
   }) = DefaultResidentCompiler;
 
 
@@ -524,8 +528,10 @@
     this.unsafePackageSerialization,
     this.experimentalFlags,
     this.platformDill,
+    List<String> dartDefines,
   }) : assert(sdkRoot != null),
        _stdoutHandler = StdoutHandler(consumer: compilerMessageConsumer),
+       dartDefines = dartDefines ?? const <String>[],
        // This is a URI, not a file path, so the forward slash is correct even on Windows.
        sdkRoot = sdkRoot.endsWith('/') ? sdkRoot : '$sdkRoot/';
 
@@ -539,6 +545,7 @@
   final String initializeFromDill;
   final bool unsafePackageSerialization;
   final List<String> experimentalFlags;
+  final List<String> dartDefines;
 
   /// The path to the root of the Dart SDK used to compile.
   ///
@@ -594,9 +601,9 @@
 
     if (_server == null) {
       return _compile(
-          _mapFilename(request.mainPath, packageUriMapper),
-          request.outputPath,
-          _mapFilename(request.packagesFilePath ?? packagesPath, /* packageUriMapper= */ null),
+        _mapFilename(request.mainPath, packageUriMapper),
+        request.outputPath,
+        _mapFilename(request.packagesFilePath ?? packagesPath, /* packageUriMapper= */ null),
       );
     }
 
@@ -648,6 +655,8 @@
       '--incremental',
       '--target=$targetModel',
       '-Ddart.developer.causal_async_stacks=$causalAsyncStacks',
+      for (Object dartDefine in dartDefines)
+        '-D$dartDefine',
       if (outputPath != null) ...<String>[
         '--output-dill',
         outputPath,
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart
index 0e465b7..9b3ebb6 100644
--- a/packages/flutter_tools/lib/src/resident_runner.dart
+++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -41,6 +41,7 @@
     List<String> experimentalFlags,
     ResidentCompiler generator,
     @required BuildMode buildMode,
+    List<String> dartDefines,
   }) : assert(trackWidgetCreation != null),
        generator = generator ?? ResidentCompiler(
          artifacts.getArtifactPath(
@@ -54,6 +55,7 @@
          fileSystemScheme: fileSystemScheme,
          targetModel: targetModel,
          experimentalFlags: experimentalFlags,
+         dartDefines: dartDefines,
        );
 
   /// Create a [FlutterDevice] with optional code generation enabled.
@@ -69,6 +71,7 @@
     TargetModel targetModel = TargetModel.flutter,
     List<String> experimentalFlags,
     ResidentCompiler generator,
+    List<String> dartDefines,
   }) async {
     ResidentCompiler generator;
     final TargetPlatform targetPlatform = await device.targetPlatform;
@@ -86,12 +89,14 @@
         targetModel: TargetModel.dartdevc,
         experimentalFlags: experimentalFlags,
         platformDill: artifacts.getArtifactPath(Artifact.webPlatformKernelDill, mode: buildMode),
+        dartDefines: dartDefines,
       );
     } else if (flutterProject.hasBuilders) {
       generator = await CodeGeneratingResidentCompiler.create(
         targetPlatform: targetPlatform,
         buildMode: buildMode,
         flutterProject: flutterProject,
+        dartDefines: dartDefines,
       );
     } else {
       generator = ResidentCompiler(
@@ -106,6 +111,7 @@
         fileSystemScheme: fileSystemScheme,
         targetModel: targetModel,
         experimentalFlags: experimentalFlags,
+        dartDefines: dartDefines,
       );
     }
     return FlutterDevice(
@@ -119,6 +125,7 @@
       targetPlatform: targetPlatform,
       generator: generator,
       buildMode: buildMode,
+      dartDefines: dartDefines,
     );
   }
 
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart
index cdbad2d..81ec070 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -269,6 +269,20 @@
         valueHelp: 'x.y.z');
   }
 
+  void usesDartDefines() {
+    argParser.addMultiOption(
+      'dart-define',
+      help: 'Passed to the Dart compiler building this application as a -D flag.\n'
+            'Values supported by this option are compiler implementation specific.\n'
+            'Multiple defines can be passed by repeating --dart-define multiple times.',
+      valueHelp: 'FOO=bar',
+      hide: true,
+    );
+  }
+
+  /// The values passed via the `--dart-define` option.
+  List<String> get dartDefines => argResults['dart-define'];
+
   void usesIsolateFilterOption({ @required bool hide }) {
     argParser.addOption('isolate-filter',
       defaultsTo: null,
diff --git a/packages/flutter_tools/lib/src/test/test_compiler.dart b/packages/flutter_tools/lib/src/test/test_compiler.dart
index 8bb3a65..dd37a5f 100644
--- a/packages/flutter_tools/lib/src/test/test_compiler.dart
+++ b/packages/flutter_tools/lib/src/test/test_compiler.dart
@@ -103,6 +103,7 @@
         // We already ran codegen once at the start, we only need to
         // configure builders.
         runCold: true,
+        dartDefines: const <String>[],
       );
     }
     return ResidentCompiler(
@@ -113,6 +114,7 @@
       compilerMessageConsumer: _reportCompilerMessage,
       initializeFromDill: testFilePath,
       unsafePackageSerialization: false,
+      dartDefines: const <String>[],
     );
   }
 
diff --git a/packages/flutter_tools/lib/src/web/compile.dart b/packages/flutter_tools/lib/src/web/compile.dart
index 51413ad..f0d9524 100644
--- a/packages/flutter_tools/lib/src/web/compile.dart
+++ b/packages/flutter_tools/lib/src/web/compile.dart
@@ -12,6 +12,7 @@
 import '../build_system/build_system.dart';
 import '../build_system/targets/dart.dart';
 import '../build_system/targets/web.dart';
+import '../convert.dart';
 import '../globals.dart';
 import '../platform_plugins.dart';
 import '../plugins.dart';
@@ -21,7 +22,13 @@
 /// The [WebCompilationProxy] instance.
 WebCompilationProxy get webCompilationProxy => context.get<WebCompilationProxy>();
 
-Future<void> buildWeb(FlutterProject flutterProject, String target, BuildInfo buildInfo, bool initializePlatform) async {
+Future<void> buildWeb(
+  FlutterProject flutterProject,
+  String target,
+  BuildInfo buildInfo,
+  bool initializePlatform,
+  List<String> dartDefines,
+) async {
   if (!flutterProject.web.existsSync()) {
     throwToolExit('Missing index.html.');
   }
@@ -42,6 +49,7 @@
         kTargetFile: target,
         kInitializePlatform: initializePlatform.toString(),
         kHasWebPlugins: hasWebPlugins.toString(),
+        kDartDefines: jsonEncode(dartDefines),
       },
     ));
     if (!result.success) {
diff --git a/packages/flutter_tools/lib/src/web/web_runner.dart b/packages/flutter_tools/lib/src/web/web_runner.dart
index 09402a3..ad41c5e 100644
--- a/packages/flutter_tools/lib/src/web/web_runner.dart
+++ b/packages/flutter_tools/lib/src/web/web_runner.dart
@@ -23,5 +23,6 @@
     @required FlutterProject flutterProject,
     @required bool ipv6,
     @required DebuggingOptions debuggingOptions,
+    @required List<String> dartDefines,
   });
 }