Unverified Commit ee60eeea authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] Allow providing dart-defines to Android, iOS, macOS builds (#51714)

parent aed96199
// Copyright 2014 The Flutter 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:async';
import 'package:flutter_devicelab/framework/adb.dart';
import 'package:flutter_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/tasks/defines_task.dart';
/// Verify that dart defines work on Android.
Future<void> main() async {
deviceOperatingSystem = DeviceOperatingSystem.android;
await task(runDartDefinesTask);
}
// Copyright 2014 The Flutter 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:async';
import 'package:flutter_devicelab/framework/adb.dart';
import 'package:flutter_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/tasks/defines_task.dart';
/// Verify that dart defines work on iOS.
Future<void> main() async {
deviceOperatingSystem = DeviceOperatingSystem.ios;
await task(runDartDefinesTask);
}
// Copyright 2014 The Flutter 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:async';
import 'dart:io';
import '../framework/adb.dart';
import '../framework/framework.dart';
import '../framework/utils.dart';
Future<TaskResult> runDartDefinesTask() async {
final Device device = await devices.workingDevice;
await device.unlock();
final String deviceId = device.deviceId;
final Directory testDirectory = dir('${flutterDirectory.path}/dev/integration_tests/ui');
await inDirectory<void>(testDirectory, () async {
await flutter('packages', options: <String>['get']);
await flutter('drive', options: <String>[
'--verbose',
'-d',
deviceId,
'--dart-define=test.value=ExampleValue',
'lib/defines.dart',
]);
});
return TaskResult.success(<String, dynamic>{});
}
......@@ -323,6 +323,13 @@ tasks:
stage: devicelab
required_agent_capabilities: ["mac/android"]
android_defines_test:
description: >
Builds an APK with a --dart-define and verifies it can be used as a constant
stage: devicelab
flaky: true
required_agent_capabilities: ["linux/android"]
android_obfuscate_test:
description: >
Builds an obfuscated APK and verifies a dart identifier cannot be found
......@@ -400,6 +407,13 @@ tasks:
# iOS on-device tests
ios_defines_test:
description: >
Builds a Framework with a --dart-define and verifies it can be used as a constant
stage: devicelab
flaky: true
required_agent_capabilities: ["mac/ios"]
ios_content_validation_test:
description: >
Builds an obfuscated app and verifies contents and structure
......
// Copyright 2014 The Flutter 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/widgets.dart';
import 'package:flutter_driver/driver_extension.dart';
/// This application displays text passed through a --dart-define.
void main() {
enableFlutterDriverExtension();
runApp(
const Center(
child: Text(
String.fromEnvironment('test.value'),
textDirection: TextDirection.ltr,
),
),
);
}
// Copyright 2014 The Flutter 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_driver/flutter_driver.dart';
import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
void main() {
FlutterDriver driver;
setUpAll(() async {
driver = await FlutterDriver.connect();
});
tearDownAll(() async {
await driver.close();
});
test('Can run with --dart-deinfe', () async {
await driver.waitFor(find.text('ExampleValue'));
});
}
......@@ -83,6 +83,7 @@ RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics \
-dTreeShakeIcons="${icon_tree_shaker_flag}" \
-dDartObfuscation="${dart_obfuscation_flag}" \
-dSplitDebugInfo="${SPLIT_DEBUG_INFO}" \
-dDartDefines="${DART_DEFINES}" \
--build-inputs="${build_inputs_path}" \
--build-outputs="${build_outputs_path}" \
--output="${ephemeral_dir}" \
......
......@@ -186,6 +186,7 @@ BuildApp() {
-dTrackWidgetCreation="${track_widget_creation_flag}" \
-dDartObfuscation="${dart_obfuscation_flag}" \
-dEnableBitcode="${bitcode_flag}" \
-dDartDefines="${DART_DEFINES}" \
"${build_mode}_ios_bundle_flutter_assets"
if [[ $? -ne 0 ]]; then
......
......@@ -615,6 +615,10 @@ class FlutterPlugin implements Plugin<Project> {
if (project.hasProperty('tree-shake-icons')) {
treeShakeIconsOptionsValue = project.property('tree-shake-icons').toBoolean()
}
String dartDefinesValue = null
if (project.hasProperty('dart-defines')) {
dartDefinesValue = project.property('dart-defines')
}
def targetPlatforms = getTargetPlatforms()
def addFlutterDeps = { variant ->
if (shouldSplitPerAbi()) {
......@@ -652,6 +656,7 @@ class FlutterPlugin implements Plugin<Project> {
splitDebugInfo splitDebugInfoValue
treeShakeIcons treeShakeIconsOptionsValue
dartObfuscation dartObfuscationValue
dartDefines dartDefinesValue
doLast {
project.exec {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
......@@ -799,6 +804,8 @@ abstract class BaseFlutterTask extends DefaultTask {
Boolean treeShakeIcons
@Optional @Input
Boolean dartObfuscation
@Optional @Input
String dartDefines
@OutputFiles
FileCollection getDependenciesFiles() {
......@@ -864,6 +871,9 @@ abstract class BaseFlutterTask extends DefaultTask {
if (dartObfuscation == true) {
args "-dDartObfuscation=true"
}
if (dartDefines != null) {
args "-dDartDefines=${dartDefines}"
}
if (extraGenSnapshotOptions != null) {
args "--ExtraGenSnapshotOptions=${extraGenSnapshotOptions}"
}
......
......@@ -19,6 +19,7 @@ import '../base/terminal.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../cache.dart';
import '../convert.dart';
import '../flutter_manifest.dart';
import '../globals.dart' as globals;
import '../project.dart';
......@@ -329,6 +330,9 @@ Future<void> buildGradleApp({
if (androidBuildInfo.shrink) {
command.add('-Pshrink=true');
}
if (androidBuildInfo.buildInfo.dartDefines?.isNotEmpty ?? false) {
command.add('-Pdart-defines=${jsonEncode(androidBuildInfo.buildInfo.dartDefines)}');
}
if (shouldBuildPluginAsAar) {
// Pass a system flag instead of a project flag, so this flag can be
// read from include_flutter.groovy.
......
......@@ -22,7 +22,7 @@ class AotBuilder {
Future<void> build({
@required TargetPlatform platform,
@required String outputPath,
@required BuildMode buildMode,
@required BuildInfo buildInfo,
@required String mainDartFile,
bool bitcode = kBitcodeEnabledDefault,
bool quiet = true,
......@@ -30,8 +30,6 @@ class AotBuilder {
Iterable<DarwinArch> iosBuildArchs = defaultIOSArchs,
List<String> extraFrontEndOptions,
List<String> extraGenSnapshotOptions,
@required List<String> dartDefines,
@required bool treeShakeIcons,
}) async {
if (platform == null) {
throwToolExit('No AOT build platform specified');
......@@ -41,14 +39,14 @@ class AotBuilder {
if (platform != TargetPlatform.ios) {
throwToolExit('Bitcode is only supported on iOS (TargetPlatform is $platform).');
}
await validateBitcode(buildMode, platform);
await validateBitcode(buildInfo.mode, platform);
}
Status status;
if (!quiet) {
final String typeName = globals.artifacts.getEngineType(platform, buildMode);
final String typeName = globals.artifacts.getEngineType(platform, buildInfo.mode);
status = globals.logger.startProgress(
'Building AOT snapshot in ${getFriendlyModeName(buildMode)} mode ($typeName)...',
'Building AOT snapshot in ${getFriendlyModeName(buildInfo.mode)} mode ($typeName)...',
timeout: timeoutConfiguration.slowOperation,
);
}
......@@ -58,13 +56,13 @@ class AotBuilder {
// Compile to kernel.
final String kernelOut = await snapshotter.compileKernel(
platform: platform,
buildMode: buildMode,
buildMode: buildInfo.mode,
mainPath: mainDartFile,
packagesPath: PackageMap.globalPackagesPath,
trackWidgetCreation: false,
trackWidgetCreation: buildInfo.trackWidgetCreation,
outputPath: outputPath,
extraFrontEndOptions: extraFrontEndOptions,
dartDefines: dartDefines,
dartDefines: buildInfo.dartDefines
);
if (kernelOut == null) {
throwToolExit('Compiler terminated unexpectedly.');
......@@ -85,7 +83,7 @@ class AotBuilder {
exitCodes[iosArch] = snapshotter.build(
platform: platform,
darwinArch: iosArch,
buildMode: buildMode,
buildMode: buildInfo.mode,
mainPath: kernelOut,
packagesPath: PackageMap.globalPackagesPath,
outputPath: outputPath,
......@@ -124,7 +122,7 @@ class AotBuilder {
// Android AOT snapshot.
final int snapshotExitCode = await snapshotter.build(
platform: platform,
buildMode: buildMode,
buildMode: buildInfo.mode,
mainPath: kernelOut,
packagesPath: PackageMap.globalPackagesPath,
outputPath: outputPath,
......
......@@ -23,6 +23,7 @@ class BuildInfo {
this.buildName,
this.splitDebugInfoPath,
this.dartObfuscation = false,
this.dartDefines = const <String>[],
@required this.treeShakeIcons,
});
......@@ -46,10 +47,10 @@ class BuildInfo {
final bool trackWidgetCreation;
/// Extra command-line options for front-end.
final String extraFrontEndOptions;
final List<String> extraFrontEndOptions;
/// Extra command-line options for gen_snapshot.
final String extraGenSnapshotOptions;
final List<String> extraGenSnapshotOptions;
/// Internal version number (not displayed to users).
/// Each build must have a unique number to differentiate it from previous builds.
......@@ -72,6 +73,12 @@ class BuildInfo {
/// Whether to apply dart source code obfuscation.
final bool dartObfuscation;
/// Additional constant values to be made available in the Dart program.
///
/// These values can be used with the const `fromEnvironment` constructors of
/// [bool], [String], [int], and [double].
final List<String> dartDefines;
static const BuildInfo debug = BuildInfo(BuildMode.debug, null, treeShakeIcons: false);
static const BuildInfo profile = BuildInfo(BuildMode.profile, null, treeShakeIcons: kIconTreeShakerEnabledDefault);
static const BuildInfo jitRelease = BuildInfo(BuildMode.jitRelease, null, treeShakeIcons: kIconTreeShakerEnabledDefault);
......
......@@ -48,7 +48,6 @@ class DwdsWebRunnerFactory extends WebRunnerFactory {
@required FlutterProject flutterProject,
@required bool ipv6,
@required DebuggingOptions debuggingOptions,
@required List<String> dartDefines,
@required UrlTunneller urlTunneller,
}) {
return _ResidentWebRunner(
......@@ -58,7 +57,6 @@ class DwdsWebRunnerFactory extends WebRunnerFactory {
debuggingOptions: debuggingOptions,
ipv6: ipv6,
stayResident: stayResident,
dartDefines: dartDefines,
urlTunneller: urlTunneller,
);
}
......@@ -77,7 +75,6 @@ abstract class ResidentWebRunner extends ResidentRunner {
@required bool ipv6,
@required DebuggingOptions debuggingOptions,
bool stayResident = true,
@required this.dartDefines,
}) : super(
<FlutterDevice>[device],
target: target ?? globals.fs.path.join('lib', 'main.dart'),
......@@ -88,7 +85,6 @@ abstract class ResidentWebRunner extends ResidentRunner {
FlutterDevice get device => flutterDevices.first;
final FlutterProject flutterProject;
final List<String> dartDefines;
DateTime firstBuildTime;
// Used with the new compiler to generate a bootstrap file containing plugins
......@@ -358,7 +354,6 @@ class _ResidentWebRunner extends ResidentWebRunner {
@required bool ipv6,
@required DebuggingOptions debuggingOptions,
bool stayResident = true,
@required List<String> dartDefines,
@required this.urlTunneller,
}) : super(
device,
......@@ -367,7 +362,6 @@ class _ResidentWebRunner extends ResidentWebRunner {
debuggingOptions: debuggingOptions,
ipv6: ipv6,
stayResident: stayResident,
dartDefines: dartDefines,
);
final UrlTunneller urlTunneller;
......@@ -432,7 +426,6 @@ class _ResidentWebRunner extends ResidentWebRunner {
target,
debuggingOptions.buildInfo,
debuggingOptions.initializePlatform,
dartDefines,
false,
);
}
......@@ -498,7 +491,6 @@ class _ResidentWebRunner extends ResidentWebRunner {
target,
debuggingOptions.buildInfo,
debuggingOptions.initializePlatform,
dartDefines,
false,
);
} on ToolExit {
......
......@@ -381,7 +381,7 @@ abstract class CopyFlutterAotBundle extends Target {
/// Dart defines are encoded inside [Environment] as a JSON array.
List<String> parseDartDefines(Environment environment) {
if (!environment.defines.containsKey(kDartDefines)) {
if (!environment.defines.containsKey(kDartDefines) || environment.defines[kDartDefines].isEmpty) {
return const <String>[];
}
......@@ -389,7 +389,7 @@ List<String> parseDartDefines(Environment environment) {
try {
final List<Object> parsedDefines = jsonDecode(dartDefinesJson) as List<Object>;
return parsedDefines.cast<String>();
} on FormatException catch (_) {
} on FormatException {
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'
......
......@@ -17,6 +17,7 @@ import 'build_system/depfile.dart';
import 'build_system/targets/dart.dart';
import 'build_system/targets/icon_tree_shaker.dart';
import 'cache.dart';
import 'convert.dart';
import 'dart/package_map.dart';
import 'devfs.dart';
import 'globals.dart' as globals;
......@@ -54,7 +55,7 @@ class BundleBuilder {
/// The default `manifestPath` is `pubspec.yaml`
Future<void> build({
@required TargetPlatform platform,
BuildMode buildMode,
BuildInfo buildInfo,
String mainPath,
String manifestPath = defaultManifestPath,
String applicationKernelFilePath,
......@@ -77,7 +78,7 @@ class BundleBuilder {
packagesPath ??= globals.fs.path.absolute(PackageMap.globalPackagesPath);
final FlutterProject flutterProject = FlutterProject.current();
await buildWithAssemble(
buildMode: buildMode ?? BuildMode.debug,
buildMode: buildInfo.mode,
targetPlatform: platform,
mainPath: mainPath,
flutterProject: flutterProject,
......@@ -86,6 +87,7 @@ class BundleBuilder {
precompiled: precompiledSnapshot,
trackWidgetCreation: trackWidgetCreation,
treeShakeIcons: treeShakeIcons,
dartDefines: buildInfo.dartDefines,
);
// Work around for flutter_tester placing kernel artifacts in odd places.
if (applicationKernelFilePath != null) {
......@@ -111,6 +113,7 @@ Future<void> buildWithAssemble({
@required bool precompiled,
bool trackWidgetCreation,
@required bool treeShakeIcons,
List<String> dartDefines,
}) async {
// If the precompiled flag was not passed, force us into debug mode.
buildMode = precompiled ? buildMode : BuildMode.debug;
......@@ -126,6 +129,8 @@ Future<void> buildWithAssemble({
kTargetPlatform: getNameForTargetPlatform(targetPlatform),
kTrackWidgetCreation: trackWidgetCreation?.toString(),
kIconTreeShakerFlag: treeShakeIcons ? 'true' : null,
if (dartDefines != null && dartDefines.isNotEmpty)
kDartDefines: jsonEncode(dartDefines),
},
);
final Target target = buildMode == BuildMode.debug
......
......@@ -61,7 +61,7 @@ class AttachCommand extends FlutterCommand {
usesIpv6Flag();
usesFilesystemOptions(hide: !verboseHelp);
usesFuchsiaOptions(hide: !verboseHelp);
usesDartDefines();
usesDartDefineOption();
argParser
..addOption(
'debug-port',
......@@ -201,7 +201,6 @@ class AttachCommand extends FlutterCommand {
stdoutCommandResponse,
notifyingLogger: NotifyingLogger(),
logToStdout: true,
dartDefines: dartDefines,
)
: null;
......@@ -348,14 +347,12 @@ class AttachCommand extends FlutterCommand {
final FlutterDevice flutterDevice = await FlutterDevice.create(
device,
flutterProject: flutterProject,
trackWidgetCreation: boolArg('track-widget-creation'),
fileSystemRoots: stringsArg('filesystem-root'),
fileSystemScheme: stringArg('filesystem-scheme'),
viewFilter: stringArg('isolate-filter'),
target: stringArg('target'),
targetModel: TargetModel(stringArg('target-model')),
buildMode: getBuildMode(),
dartDefines: dartDefines,
buildInfo: getBuildInfo(),
);
flutterDevice.observatoryUris = observatoryUris;
final List<FlutterDevice> flutterDevices = <FlutterDevice>[flutterDevice];
......
......@@ -19,7 +19,7 @@ class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmen
usesTargetOption();
addBuildModeFlags();
usesPubOption();
usesDartDefines();
usesDartDefineOption();
argParser
..addOption('output-dir', defaultsTo: getAotBuildDirectory())
..addOption('target-platform',
......@@ -42,10 +42,6 @@ class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmen
splitCommas: true,
hide: true,
)
..addMultiOption(FlutterOptions.kExtraGenSnapshotOptions,
splitCommas: true,
hide: true,
)
..addFlag('bitcode',
defaultsTo: kBitcodeEnabledDefault,
help: 'Build the AOT bundle with bitcode. Requires a compatible bitcode engine.',
......@@ -70,7 +66,7 @@ class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmen
final String targetPlatform = stringArg('target-platform');
final TargetPlatform platform = getTargetPlatformForName(targetPlatform);
final String outputPath = stringArg('output-dir') ?? getAotBuildDirectory();
final BuildMode buildMode = getBuildMode();
final BuildInfo buildInfo = getBuildInfo();
if (platform == null) {
throwToolExit('Unknown platform: $targetPlatform');
}
......@@ -80,16 +76,13 @@ class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmen
await aotBuilder.build(
platform: platform,
outputPath: outputPath,
buildMode: buildMode,
buildInfo: buildInfo,
mainDartFile: findMainDartFile(targetFile),
bitcode: boolArg('bitcode'),
quiet: boolArg('quiet'),
reportTimings: boolArg('report-timings'),
iosBuildArchs: stringsArg('ios-arch').map<DarwinArch>(getIOSArchForName),
extraFrontEndOptions: stringsArg(FlutterOptions.kExtraFrontEndOptions),
extraGenSnapshotOptions: stringsArg(FlutterOptions.kExtraGenSnapshotOptions),
dartDefines: dartDefines,
treeShakeIcons: boolArg('tree-shake-icons'),
);
return FlutterCommandResult.success();
}
......
......@@ -28,6 +28,7 @@ class BuildApkCommand extends BuildSubCommand {
addShrinkingFlag();
addSplitDebugInfoOption();
addDartObfuscationOption();
usesDartDefineOption();
argParser
..addFlag('split-per-abi',
negatable: false,
......
......@@ -26,7 +26,7 @@ class BuildAppBundleCommand extends BuildSubCommand {
addShrinkingFlag();
addSplitDebugInfoOption();
addDartObfuscationOption();
usesDartDefineOption();
argParser
..addFlag('track-widget-creation', negatable: false, hide: !verboseHelp)
..addMultiOption('target-platform',
......
......@@ -53,11 +53,11 @@ class BuildBundleCommand extends BuildSubCommand {
splitCommas: true,
hide: true,
)
..addOption('asset-dir', defaultsTo: getAssetBuildDirectory())
..addMultiOption(FlutterOptions.kExtraGenSnapshotOptions,
splitCommas: true,
hide: true,
)
..addOption('asset-dir', defaultsTo: getAssetBuildDirectory())
..addFlag('report-licensed-packages',
help: 'Whether to report the names of all the packages that are included '
"in the application's LICENSE file.",
......@@ -122,11 +122,11 @@ class BuildBundleCommand extends BuildSubCommand {
break;
}
final BuildMode buildMode = getBuildMode();
final BuildInfo buildInfo = getBuildInfo();
await bundleBuilder.build(
platform: platform,
buildMode: buildMode,
buildInfo: buildInfo,
mainPath: targetFile,
manifestPath: stringArg('manifest'),
depfilePath: stringArg('depfile'),
......@@ -135,8 +135,8 @@ class BuildBundleCommand extends BuildSubCommand {
precompiledSnapshot: boolArg('precompiled'),
reportLicensedPackages: boolArg('report-licensed-packages'),
trackWidgetCreation: boolArg('track-widget-creation'),
extraFrontEndOptions: stringsArg(FlutterOptions.kExtraFrontEndOptions),
extraGenSnapshotOptions: stringsArg(FlutterOptions.kExtraGenSnapshotOptions),
extraFrontEndOptions: buildInfo.extraFrontEndOptions,
extraGenSnapshotOptions: buildInfo.extraGenSnapshotOptions,
fileSystemScheme: stringArg('filesystem-scheme'),
fileSystemRoots: stringsArg('filesystem-root'),
treeShakeIcons: boolArg('tree-shake-icons'),
......
......@@ -27,6 +27,7 @@ class BuildIOSCommand extends BuildSubCommand {
usesBuildNumberOption();
usesBuildNameOption();
addDartObfuscationOption();
usesDartDefineOption();
argParser
..addFlag('simulator',
help: 'Build for the iOS simulator instead of the device.',
......
......@@ -48,7 +48,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
usesTargetOption();
usesFlavorOption();
usesPubOption();
usesDartDefines();
usesDartDefineOption();
addSplitDebugInfoOption();
addDartObfuscationOption();
argParser
......@@ -120,17 +120,17 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
FlutterProject _project;
List<BuildMode> get buildModes {
final List<BuildMode> buildModes = <BuildMode>[];
List<BuildInfo> get buildInfos {
final List<BuildInfo> buildModes = <BuildInfo>[];
if (boolArg('debug')) {
buildModes.add(BuildMode.debug);
buildModes.add(BuildInfo.debug);
}
if (boolArg('profile')) {
buildModes.add(BuildMode.profile);
buildModes.add(BuildInfo.profile);
}
if (boolArg('release')) {
buildModes.add(BuildMode.release);
buildModes.add(BuildInfo.release);
}
return buildModes;
......@@ -154,7 +154,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
if (boolArg('xcframework') && globals.xcode.majorVersion < 11) {
throwToolExit('--xcframework requires Xcode 11.');
}
if (buildModes.isEmpty) {
if (buildInfos.isEmpty) {
throwToolExit('At least one of "--debug" or "--profile", or "--release" is required.');
}
}
......@@ -177,9 +177,9 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
final Directory outputDirectory = globals.fs.directory(globals.fs.path.absolute(globals.fs.path.normalize(outputArgument)));
final String productBundleIdentifier = await _project.ios.productBundleIdentifier;
for (final BuildMode mode in buildModes) {
globals.printStatus('Building frameworks for $productBundleIdentifier in ${getNameForBuildMode(mode)} mode...');
final String xcodeBuildConfiguration = toTitleCase(getNameForBuildMode(mode));
for (final BuildInfo buildInfo in buildInfos) {
globals.printStatus('Building frameworks for $productBundleIdentifier in ${getNameForBuildMode(buildInfo.mode)} mode...');
final String xcodeBuildConfiguration = toTitleCase(getNameForBuildMode(buildInfo.mode));
final Directory modeDirectory = outputDirectory.childDirectory(xcodeBuildConfiguration);
if (modeDirectory.existsSync()) {
......@@ -191,19 +191,19 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
if (boolArg('cocoapods')) {
// FlutterVersion.instance kicks off git processing which can sometimes fail, so don't try it until needed.
_flutterVersion ??= globals.flutterVersion;
produceFlutterPodspec(mode, modeDirectory, force: boolArg('force'));
produceFlutterPodspec(buildInfo.mode, modeDirectory, force: boolArg('force'));
} else {
// Copy Flutter.framework.
await _produceFlutterFramework(mode, modeDirectory);
await _produceFlutterFramework(buildInfo, modeDirectory);
}
// Build aot, create module.framework and copy.
await _produceAppFramework(mode, iPhoneBuildOutput, simulatorBuildOutput, modeDirectory);
await _produceAppFramework(buildInfo, iPhoneBuildOutput, simulatorBuildOutput, modeDirectory);
// Build and copy plugins.
await processPodsIfNeeded(_project.ios, getIosBuildDirectory(), mode);
await processPodsIfNeeded(_project.ios, getIosBuildDirectory(), buildInfo.mode);
if (hasPlugins(_project)) {
await _producePlugins(mode, xcodeBuildConfiguration, iPhoneBuildOutput, simulatorBuildOutput, modeDirectory, outputDirectory);
await _producePlugins(buildInfo.mode, xcodeBuildConfiguration, iPhoneBuildOutput, simulatorBuildOutput, modeDirectory, outputDirectory);
}
final Status status = globals.logger.startProgress(
......@@ -285,7 +285,7 @@ end
}
Future<void> _produceFlutterFramework(
BuildMode mode,
BuildInfo buildInfo,
Directory modeDirectory,
) async {
final Status status = globals.logger.startProgress(
......@@ -295,7 +295,7 @@ end
final String engineCacheFlutterFrameworkDirectory = globals.artifacts.getArtifactPath(
Artifact.flutterFramework,
platform: TargetPlatform.ios,
mode: mode,
mode: buildInfo.mode,
);
final String flutterFrameworkFileName = globals.fs.path.basename(
engineCacheFlutterFrameworkDirectory,
......@@ -311,7 +311,7 @@ end
fatFlutterFrameworkCopy,
);
if (mode != BuildMode.debug) {
if (buildInfo.mode != BuildMode.debug) {
final File fatFlutterFrameworkBinary = fatFlutterFrameworkCopy.childFile('Flutter');
// Remove simulator architecture in profile and release mode.
......@@ -331,7 +331,7 @@ end
if (lipoResult.exitCode != 0) {
throwToolExit(
'Unable to remove simulator architecture in $mode: ${lipoResult.stderr}',
'Unable to remove simulator architecture in ${buildInfo.mode}: ${lipoResult.stderr}',
);
}
}
......@@ -339,23 +339,23 @@ end
status.stop();
}
await _produceXCFramework(mode, fatFlutterFrameworkCopy);
await _produceXCFramework(buildInfo, fatFlutterFrameworkCopy);
}
Future<void> _produceAppFramework(BuildMode mode, Directory iPhoneBuildOutput, Directory simulatorBuildOutput, Directory modeDirectory) async {
Future<void> _produceAppFramework(BuildInfo buildInfo, Directory iPhoneBuildOutput, Directory simulatorBuildOutput, Directory modeDirectory) async {
const String appFrameworkName = 'App.framework';
final Directory destinationAppFrameworkDirectory = modeDirectory.childDirectory(appFrameworkName);
if (mode == BuildMode.debug) {
if (buildInfo.mode == BuildMode.debug) {
final Status status = globals.logger.startProgress(' ├─Adding placeholder App.framework for debug...', timeout: timeoutConfiguration.fastOperation);
try {
destinationAppFrameworkDirectory.createSync(recursive: true);
await _produceStubAppFrameworkIfNeeded(mode, iPhoneBuildOutput, simulatorBuildOutput, destinationAppFrameworkDirectory);
await _produceStubAppFrameworkIfNeeded(buildInfo, iPhoneBuildOutput, simulatorBuildOutput, destinationAppFrameworkDirectory);
} finally {
status.stop();
}
} else {
await _produceAotAppFrameworkIfNeeded(mode, modeDirectory);
await _produceAotAppFrameworkIfNeeded(buildInfo, modeDirectory);
}
final File sourceInfoPlist = _project.ios.hostAppRoot.childDirectory('Flutter').childFile('AppFrameworkInfo.plist');
......@@ -368,21 +368,21 @@ end
try {
await _bundleBuilder.build(
platform: TargetPlatform.ios,
buildMode: mode,
buildInfo: buildInfo,
// Relative paths show noise in the compiler https://github.com/dart-lang/sdk/issues/37978.
mainPath: globals.fs.path.absolute(targetFile),
assetDirPath: destinationAppFrameworkDirectory.childDirectory('flutter_assets').path,
precompiledSnapshot: mode != BuildMode.debug,
precompiledSnapshot: buildInfo.mode != BuildMode.debug,
treeShakeIcons: boolArg('tree-shake-icons')
);
} finally {
status.stop();
}
await _produceXCFramework(mode, destinationAppFrameworkDirectory);
await _produceXCFramework(buildInfo, destinationAppFrameworkDirectory);
}
Future<void> _produceStubAppFrameworkIfNeeded(BuildMode mode, Directory iPhoneBuildOutput, Directory simulatorBuildOutput, Directory destinationAppFrameworkDirectory) async {
if (mode != BuildMode.debug) {
Future<void> _produceStubAppFrameworkIfNeeded(BuildInfo buildInfo, Directory iPhoneBuildOutput, Directory simulatorBuildOutput, Directory destinationAppFrameworkDirectory) async {
if (buildInfo.mode != BuildMode.debug) {
return;
}
const String appFrameworkName = 'App.framework';
......@@ -417,10 +417,10 @@ end
}
Future<void> _produceAotAppFrameworkIfNeeded(
BuildMode mode,
BuildInfo buildInfo,
Directory destinationDirectory,
) async {
if (mode == BuildMode.debug) {
if (buildInfo.mode == BuildMode.debug) {
return;
}
final Status status = globals.logger.startProgress(
......@@ -431,15 +431,13 @@ end
await _aotBuilder.build(
platform: TargetPlatform.ios,
outputPath: destinationDirectory.path,
buildMode: mode,
buildInfo: buildInfo,
// Relative paths show noise in the compiler https://github.com/dart-lang/sdk/issues/37978.
mainDartFile: globals.fs.path.absolute(targetFile),
quiet: true,
bitcode: true,
reportTimings: false,
iosBuildArchs: <DarwinArch>[DarwinArch.armv7, DarwinArch.arm64],
dartDefines: dartDefines,
treeShakeIcons: boolArg('tree-shake-icons'),
);
} finally {
status.stop();
......@@ -609,7 +607,7 @@ end
}
}
Future<void> _produceXCFramework(BuildMode mode, Directory fatFramework) async {
Future<void> _produceXCFramework(BuildInfo buildInfo, Directory fatFramework) async {
if (boolArg('xcframework')) {
final String frameworkBinaryName = globals.fs.path.basenameWithoutExtension(
fatFramework.basename);
......@@ -619,10 +617,10 @@ end
timeout: timeoutConfiguration.slowOperation,
);
try {
if (mode == BuildMode.debug) {
if (buildInfo.mode == BuildMode.debug) {
await _produceDebugXCFramework(fatFramework, frameworkBinaryName);
} else {
await _produceNonDebugXCFramework(mode, fatFramework, frameworkBinaryName);
await _produceNonDebugXCFramework(buildInfo, fatFramework, frameworkBinaryName);
}
} finally {
status.stop();
......@@ -731,7 +729,7 @@ end
}
Future<void> _produceNonDebugXCFramework(
BuildMode mode,
BuildInfo buildInfo,
Directory fatFramework,
String frameworkBinaryName,
) async {
......
......@@ -19,7 +19,7 @@ class BuildWebCommand extends BuildSubCommand {
usesTargetOption();
usesPubOption();
addBuildModeFlags(excludeDebug: true);
usesDartDefines();
usesDartDefineOption();
argParser.addFlag('web-initialize-platform',
defaultsTo: true,
negatable: true,
......@@ -65,8 +65,7 @@ class BuildWebCommand extends BuildSubCommand {
target,
buildInfo,
boolArg('web-initialize-platform'),
dartDefines,
boolArg('csp')
boolArg('csp'),
);
return FlutterCommandResult.success();
}
......
......@@ -35,9 +35,7 @@ const String protocolVersion = '0.5.3';
/// It can be shutdown with a `daemon.shutdown` command (or by killing the
/// process).
class DaemonCommand extends FlutterCommand {
DaemonCommand({ this.hidden = false }) {
usesDartDefines();
}
DaemonCommand({ this.hidden = false });
@override
final String name = 'daemon';
......@@ -62,7 +60,6 @@ class DaemonCommand extends FlutterCommand {
final Daemon daemon = Daemon(
stdinCommandStream, stdoutCommandResponse,
notifyingLogger: notifyingLogger,
dartDefines: dartDefines,
);
final int code = await daemon.onExit;
......@@ -88,15 +85,7 @@ class Daemon {
this.sendCommand, {
this.notifyingLogger,
this.logToStdout = false,
@required this.dartDefines,
}) {
if (dartDefines == null) {
throw Exception(
'dartDefines must not be null. This is a bug in Flutter.\n'
'Please file an issue at https://github.com/flutter/flutter/issues/new/choose',
);
}
// Set up domains.
_registerDomain(daemonDomain = DaemonDomain(this));
_registerDomain(appDomain = AppDomain(this));
......@@ -125,7 +114,6 @@ class Daemon {
final DispatchCommand sendCommand;
final NotifyingLogger notifyingLogger;
final bool logToStdout;
final List<String> dartDefines;
final Completer<int> _onExitCompleter = Completer<int>();
final Map<String, Domain> _domainMap = <String, Domain>{};
......@@ -481,11 +469,9 @@ class AppDomain extends Domain {
final FlutterDevice flutterDevice = await FlutterDevice.create(
device,
flutterProject: flutterProject,
trackWidgetCreation: trackWidgetCreation,
viewFilter: isolateFilter,
target: target,
buildMode: options.buildInfo.mode,
dartDefines: daemon.dartDefines,
buildInfo: options.buildInfo,
);
ResidentRunner runner;
......@@ -498,7 +484,6 @@ class AppDomain extends Domain {
debuggingOptions: options,
ipv6: ipv6,
stayResident: true,
dartDefines: daemon.dartDefines,
urlTunneller: options.webEnableExposeUrl ? daemon.daemonDomain.exposeUrl : null,
);
} else if (enableHotReload) {
......
......@@ -144,11 +144,12 @@ class DriveCommand extends RunCommandBase {
String observatoryUri;
ResidentRunner residentRunner;
final BuildInfo buildInfo = getBuildInfo();
final bool isWebPlatform = await device.targetPlatform == TargetPlatform.web_javascript;
if (argResults['use-existing-app'] == null) {
globals.printStatus('Starting application: $targetFile');
if (getBuildInfo().isRelease && !isWebPlatform) {
if (buildInfo.isRelease && !isWebPlatform) {
// This is because we need VM service to be able to drive the app.
// For Flutter Web, testing in release mode is allowed.
throwToolExit(
......@@ -159,7 +160,7 @@ class DriveCommand extends RunCommandBase {
);
}
if (isWebPlatform && getBuildInfo().isDebug) {
if (isWebPlatform && buildInfo.isDebug) {
// TODO(angjieli): remove this once running against
// target under test_driver in debug mode is supported
throwToolExit(
......@@ -178,18 +179,16 @@ class DriveCommand extends RunCommandBase {
final FlutterDevice flutterDevice = await FlutterDevice.create(
device,
flutterProject: flutterProject,
trackWidgetCreation: boolArg('track-widget-creation'),
target: targetFile,
buildMode: getBuildMode()
buildInfo: buildInfo
);
residentRunner = webRunnerFactory.createWebRunner(
flutterDevice,
target: targetFile,
flutterProject: flutterProject,
ipv6: ipv6,
debuggingOptions: DebuggingOptions.enabled(getBuildInfo()),
debuggingOptions: DebuggingOptions.enabled(buildInfo),
stayResident: false,
dartDefines: dartDefines,
urlTunneller: null,
);
final Completer<void> appStartedCompleter = Completer<void>.sync();
......
......@@ -30,7 +30,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
// Used by run and drive commands.
RunCommandBase({ bool verboseHelp = false }) {
addBuildModeFlags(defaultToRelease: false, verboseHelp: verboseHelp);
usesDartDefines();
usesDartDefineOption();
usesFlavorOption();
argParser
..addFlag('trace-startup',
......@@ -204,7 +204,6 @@ class RunCommand extends RunCommandBase {
'cannot be paired with --use-application-binary.'
)
..addOption(FlutterOptions.kExtraFrontEndOptions, hide: true)
..addOption(FlutterOptions.kExtraGenSnapshotOptions, hide: true)
..addMultiOption(FlutterOptions.kEnableExperiment,
splitCommas: true,
hide: true,
......@@ -403,7 +402,6 @@ class RunCommand extends RunCommandBase {
stdoutCommandResponse,
notifyingLogger: NotifyingLogger(),
logToStdout: true,
dartDefines: dartDefines,
);
AppInstance app;
try {
......@@ -483,14 +481,12 @@ class RunCommand extends RunCommandBase {
await FlutterDevice.create(
device,
flutterProject: flutterProject,
trackWidgetCreation: boolArg('track-widget-creation'),
fileSystemRoots: stringsArg('filesystem-root'),
fileSystemScheme: stringArg('filesystem-scheme'),
viewFilter: stringArg('isolate-filter'),
experimentalFlags: expFlags,
target: stringArg('target'),
buildMode: getBuildMode(),
dartDefines: dartDefines,
buildInfo: getBuildInfo(),
),
];
// Only support "web mode" with a single web device due to resident runner
......@@ -524,7 +520,6 @@ class RunCommand extends RunCommandBase {
ipv6: ipv6,
debuggingOptions: _createDebuggingOptions(),
stayResident: stayResident,
dartDefines: dartDefines,
urlTunneller: null,
);
} else {
......
......@@ -5,8 +5,6 @@
import 'dart:async';
import 'dart:math' as math;
import 'package:meta/meta.dart';
import '../application_package.dart';
import '../base/common.dart';
import '../base/context.dart';
......@@ -15,7 +13,6 @@ import '../base/io.dart';
import '../base/process.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../bundle.dart';
import '../convert.dart';
import '../device.dart';
import '../globals.dart' as globals;
......@@ -420,20 +417,13 @@ class IOSSimulator extends Device {
}
Future<void> _setupUpdatedApplicationBundle(covariant BuildableIOSApp app, BuildInfo buildInfo, String mainPath) async {
await sideloadUpdatedAssetsForInstalledApplicationBundle(buildInfo, mainPath);
// Step 1: Build the Xcode project.
// The build mode for the simulator is always debug.
final BuildInfo debugBuildInfo = BuildInfo(BuildMode.debug, buildInfo.flavor,
trackWidgetCreation: buildInfo.trackWidgetCreation,
extraFrontEndOptions: buildInfo.extraFrontEndOptions,
extraGenSnapshotOptions: buildInfo.extraGenSnapshotOptions,
treeShakeIcons: buildInfo.treeShakeIcons);
assert(buildInfo.isDebug);
final XcodeBuildResult buildResult = await buildXcodeProject(
app: app,
buildInfo: debugBuildInfo,
buildInfo: buildInfo,
targetOverride: mainPath,
buildForDevice: false,
);
......@@ -452,19 +442,6 @@ class IOSSimulator extends Device {
await SimControl.instance.install(id, globals.fs.path.absolute(bundle.path));
}
@visibleForTesting
Future<void> sideloadUpdatedAssetsForInstalledApplicationBundle(BuildInfo buildInfo, String mainPath) {
// Run compiler to produce kernel file for the application.
return BundleBuilder().build(
platform: TargetPlatform.ios,
mainPath: mainPath,
precompiledSnapshot: false,
buildMode: buildInfo.mode,
trackWidgetCreation: buildInfo.trackWidgetCreation,
treeShakeIcons: false,
);
}
@override
Future<bool> stopApp(ApplicationPackage app) async {
// Currently we don't have a way to stop an app running on iOS.
......
......@@ -19,6 +19,7 @@ import '../base/terminal.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../cache.dart';
import '../convert.dart';
import '../flutter_manifest.dart';
import '../globals.dart' as globals;
import '../project.dart';
......@@ -235,6 +236,10 @@ List<String> _xcodeBuildSettingsLines({
xcodeBuildSettings.add('TREE_SHAKE_ICONS=true');
}
if (buildInfo.dartDefines?.isNotEmpty ?? false) {
xcodeBuildSettings.add('DART_DEFINES=${jsonEncode(buildInfo.dartDefines)}');
}
return xcodeBuildSettings;
}
......
......@@ -33,7 +33,7 @@ import 'vmservice.dart';
class FlutterDevice {
FlutterDevice(
this.device, {
@required this.trackWidgetCreation,
@required this.buildInfo,
this.fileSystemRoots,
this.fileSystemScheme,
this.viewFilter,
......@@ -41,38 +41,34 @@ class FlutterDevice {
TargetPlatform targetPlatform,
List<String> experimentalFlags,
ResidentCompiler generator,
@required BuildMode buildMode,
List<String> dartDefines,
}) : assert(trackWidgetCreation != null),
}) : assert(buildInfo.trackWidgetCreation != null),
generator = generator ?? ResidentCompiler(
globals.artifacts.getArtifactPath(
Artifact.flutterPatchedSdkPath,
platform: targetPlatform,
mode: buildMode,
mode: buildInfo.mode,
),
buildMode: buildMode,
trackWidgetCreation: trackWidgetCreation,
buildMode: buildInfo.mode,
trackWidgetCreation: buildInfo.trackWidgetCreation,
fileSystemRoots: fileSystemRoots ?? <String>[],
fileSystemScheme: fileSystemScheme,
targetModel: targetModel,
experimentalFlags: experimentalFlags,
dartDefines: dartDefines,
dartDefines: buildInfo.dartDefines,
);
/// Create a [FlutterDevice] with optional code generation enabled.
static Future<FlutterDevice> create(
Device device, {
@required FlutterProject flutterProject,
@required bool trackWidgetCreation,
@required String target,
@required BuildMode buildMode,
@required BuildInfo buildInfo,
List<String> fileSystemRoots,
String fileSystemScheme,
String viewFilter,
TargetModel targetModel = TargetModel.flutter,
List<String> experimentalFlags,
ResidentCompiler generator,
List<String> dartDefines,
}) async {
ResidentCompiler generator;
final TargetPlatform targetPlatform = await device.targetPlatform;
......@@ -81,9 +77,9 @@ class FlutterDevice {
}
if (targetPlatform == TargetPlatform.web_javascript) {
generator = ResidentCompiler(
globals.artifacts.getArtifactPath(Artifact.flutterWebSdk, mode: buildMode),
buildMode: buildMode,
trackWidgetCreation: trackWidgetCreation,
globals.artifacts.getArtifactPath(Artifact.flutterWebSdk, mode: buildInfo.mode),
buildMode: buildInfo.mode,
trackWidgetCreation: buildInfo.trackWidgetCreation,
fileSystemRoots: fileSystemRoots ?? <String>[],
// Override the filesystem scheme so that the frontend_server can find
// the generated entrypoint code.
......@@ -91,9 +87,9 @@ class FlutterDevice {
targetModel: TargetModel.dartdevc,
experimentalFlags: experimentalFlags,
platformDill: globals.fs.file(globals.artifacts
.getArtifactPath(Artifact.webPlatformKernelDill, mode: buildMode))
.getArtifactPath(Artifact.webPlatformKernelDill, mode: buildInfo.mode))
.absolute.uri.toString(),
dartDefines: dartDefines,
dartDefines: buildInfo.dartDefines,
librariesSpec: globals.fs.file(globals.artifacts
.getArtifactPath(Artifact.flutterWebLibrariesJson)).uri.toString()
);
......@@ -102,15 +98,15 @@ class FlutterDevice {
globals.artifacts.getArtifactPath(
Artifact.flutterPatchedSdkPath,
platform: targetPlatform,
mode: buildMode,
mode: buildInfo.mode,
),
buildMode: buildMode,
trackWidgetCreation: trackWidgetCreation,
buildMode: buildInfo.mode,
trackWidgetCreation: buildInfo.trackWidgetCreation,
fileSystemRoots: fileSystemRoots,
fileSystemScheme: fileSystemScheme,
targetModel: targetModel,
experimentalFlags: experimentalFlags,
dartDefines: dartDefines,
dartDefines: buildInfo.dartDefines,
);
}
......@@ -123,7 +119,6 @@ class FlutterDevice {
return FlutterDevice(
device,
trackWidgetCreation: trackWidgetCreation,
fileSystemRoots: fileSystemRoots,
fileSystemScheme:fileSystemScheme,
viewFilter: viewFilter,
......@@ -131,13 +126,13 @@ class FlutterDevice {
targetModel: targetModel,
targetPlatform: targetPlatform,
generator: generator,
buildMode: buildMode,
dartDefines: dartDefines,
buildInfo: buildInfo,
);
}
final Device device;
final ResidentCompiler generator;
final BuildInfo buildInfo;
Stream<Uri> observatoryUris;
VMService vmService;
DevFS devFS;
......@@ -147,7 +142,6 @@ class FlutterDevice {
StreamSubscription<String> _loggingSubscription;
bool _isListeningForObservatoryUri;
final String viewFilter;
final bool trackWidgetCreation;
/// Whether the stream [observatoryUris] is still open.
bool get isWaitingForObservatory => _isListeningForObservatoryUri ?? false;
......@@ -562,7 +556,7 @@ class FlutterDevice {
generator: generator,
fullRestart: fullRestart,
dillOutputPath: dillOutputPath,
trackWidgetCreation: trackWidgetCreation,
trackWidgetCreation: buildInfo.trackWidgetCreation,
projectRootPath: projectRootPath,
pathToReload: pathToReload,
invalidatedFiles: invalidatedFiles,
......
......@@ -342,7 +342,7 @@ class HotRunner extends ResidentRunner {
mainPath,
<Uri>[],
outputPath: dillOutputPath ??
getDefaultApplicationKernelPath(trackWidgetCreation: device.trackWidgetCreation),
getDefaultApplicationKernelPath(trackWidgetCreation: debuggingOptions.buildInfo.trackWidgetCreation),
packagesFilePath : packagesFilePath,
).then((CompilerOutput output) => output?.errorCount == 0)
);
......
......@@ -109,6 +109,7 @@ class FlutterOptions {
static const String kFileSystemScheme = 'filesystem-scheme';
static const String kSplitDebugInfoOption = 'split-debug-info';
static const String kDartObfuscationOption = 'obfuscate';
static const String kDartDefinesOption = 'dart-define';
}
abstract class FlutterCommand extends Command<void> {
......@@ -336,20 +337,17 @@ abstract class FlutterCommand extends Command<void> {
valueHelp: 'x.y.z');
}
void usesDartDefines() {
void usesDartDefineOption() {
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'
FlutterOptions.kDartDefinesOption,
help: 'Additional key-value pairs that will be available as constants '
'from the String.fromEnvironment, bool.fromEnvironment, int.fromEnvironment, '
'and double.fromEnvironment constructors.\n'
'Multiple defines can be passed by repeating --dart-define multiple times.',
valueHelp: 'FOO=bar',
hide: true,
valueHelp: 'foo=bar',
);
}
/// The values passed via the `--dart-define` option.
List<String> get dartDefines => stringsArg('dart-define');
void usesIsolateFilterOption({ @required bool hide }) {
argParser.addOption('isolate-filter',
defaultsTo: null,
......@@ -508,19 +506,15 @@ abstract class FlutterCommand extends Command<void> {
? stringArg('build-number')
: null;
String extraFrontEndOptions =
final List<String> extraFrontEndOptions =
argParser.options.containsKey(FlutterOptions.kExtraFrontEndOptions)
? stringArg(FlutterOptions.kExtraFrontEndOptions)
: null;
? stringsArg(FlutterOptions.kExtraFrontEndOptions)
: <String>[];
if (argParser.options.containsKey(FlutterOptions.kEnableExperiment) &&
argResults[FlutterOptions.kEnableExperiment] != null) {
for (final String expFlag in stringsArg(FlutterOptions.kEnableExperiment)) {
final String flag = '--enable-experiment=' + expFlag;
if (extraFrontEndOptions != null) {
extraFrontEndOptions += ',' + flag;
} else {
extraFrontEndOptions = flag;
}
extraFrontEndOptions.add(flag);
}
}
......@@ -543,9 +537,11 @@ abstract class FlutterCommand extends Command<void> {
? stringArg('flavor')
: null,
trackWidgetCreation: trackWidgetCreation,
extraFrontEndOptions: extraFrontEndOptions,
extraFrontEndOptions: extraFrontEndOptions?.isNotEmpty ?? false
? extraFrontEndOptions
: null,
extraGenSnapshotOptions: argParser.options.containsKey(FlutterOptions.kExtraGenSnapshotOptions)
? stringArg(FlutterOptions.kExtraGenSnapshotOptions)
? stringsArg(FlutterOptions.kExtraGenSnapshotOptions)
: null,
fileSystemRoots: argParser.options.containsKey(FlutterOptions.kFileSystemRoot)
? stringsArg(FlutterOptions.kFileSystemRoot)
......@@ -562,6 +558,9 @@ abstract class FlutterCommand extends Command<void> {
: kIconTreeShakerEnabledDefault,
splitDebugInfoPath: splitDebugInfoPath,
dartObfuscation: dartObfuscation,
dartDefines: argParser.options.containsKey(FlutterOptions.kDartDefinesOption)
? stringsArg(FlutterOptions.kDartDefinesOption)
: const <String>[],
);
}
......
......@@ -144,7 +144,7 @@ class FlutterTesterDevice extends Device {
trackWidgetCreation: buildInfo.trackWidgetCreation,
);
await BundleBuilder().build(
buildMode: buildInfo.mode,
buildInfo: buildInfo,
mainPath: mainPath,
assetDirPath: assetDirPath,
applicationKernelFilePath: applicationKernelFilePath,
......
......@@ -28,7 +28,6 @@ Future<void> buildWeb(
String target,
BuildInfo buildInfo,
bool initializePlatform,
List<String> dartDefines,
bool csp,
) async {
if (!flutterProject.web.existsSync()) {
......@@ -51,7 +50,7 @@ Future<void> buildWeb(
kTargetFile: target,
kInitializePlatform: initializePlatform.toString(),
kHasWebPlugins: hasWebPlugins.toString(),
kDartDefines: jsonEncode(dartDefines),
kDartDefines: jsonEncode(buildInfo.dartDefines),
kCspMode: csp.toString(),
kIconTreeShakerFlag: buildInfo.treeShakeIcons.toString(),
},
......
......@@ -24,7 +24,6 @@ abstract class WebRunnerFactory {
@required FlutterProject flutterProject,
@required bool ipv6,
@required DebuggingOptions debuggingOptions,
@required List<String> dartDefines,
@required UrlTunneller urlTunneller,
});
}
......@@ -57,7 +57,6 @@ void main() {
fileSystem.path.join('lib', 'main.dart'),
BuildInfo.debug,
false,
const <String>[],
false,
), throwsToolExit());
}, overrides: <Type, Generator>{
......@@ -77,7 +76,6 @@ void main() {
ipv6: false,
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
stayResident: true,
dartDefines: const <String>[],
urlTunneller: null,
) as ResidentWebRunner;
expect(await runner.run(), 1);
......
......@@ -41,7 +41,6 @@ void main() {
commands.stream,
responses.add,
notifyingLogger: notifyingLogger,
dartDefines: const <String>[],
);
commands.add(<String, dynamic>{'id': 0, 'method': 'daemon.version'});
final Map<String, dynamic> response = await responses.stream.firstWhere(_notEvent);
......@@ -59,7 +58,6 @@ void main() {
commands.stream,
responses.add,
notifyingLogger: notifyingLogger,
dartDefines: const <String>[],
);
globals.printError('daemon.logMessage test');
final Map<String, dynamic> response = await responses.stream.firstWhere((Map<String, dynamic> map) {
......@@ -87,7 +85,6 @@ void main() {
responses.add,
notifyingLogger: notifyingLogger,
logToStdout: true,
dartDefines: const <String>[],
);
globals.printStatus('daemon.logMessage test');
// Service the event loop.
......@@ -108,7 +105,6 @@ void main() {
commands.stream,
responses.add,
notifyingLogger: notifyingLogger,
dartDefines: const <String>[],
);
commands.add(<String, dynamic>{'id': 0, 'method': 'daemon.shutdown'});
return daemon.onExit.then<void>((int code) async {
......@@ -124,7 +120,6 @@ void main() {
commands.stream,
responses.add,
notifyingLogger: notifyingLogger,
dartDefines: const <String>[],
);
commands.add(<String, dynamic>{'id': 0, 'method': 'app.restart'});
......@@ -142,7 +137,6 @@ void main() {
commands.stream,
responses.add,
notifyingLogger: notifyingLogger,
dartDefines: const <String>[],
);
commands.add(<String, dynamic>{
......@@ -166,7 +160,6 @@ void main() {
commands.stream,
responses.add,
notifyingLogger: notifyingLogger,
dartDefines: const <String>[],
);
commands.add(<String, dynamic>{'id': 0, 'method': 'app.stop'});
......@@ -184,7 +177,6 @@ void main() {
commands.stream,
responses.add,
notifyingLogger: notifyingLogger,
dartDefines: const <String>[],
);
commands.add(<String, dynamic>{'id': 0, 'method': 'device.getDevices'});
final Map<String, dynamic> response = await responses.stream.firstWhere(_notEvent);
......@@ -201,7 +193,6 @@ void main() {
commands.stream,
responses.add,
notifyingLogger: notifyingLogger,
dartDefines: const <String>[],
);
final MockPollingDeviceDiscovery discoverer = MockPollingDeviceDiscovery();
daemon.deviceDomain.addDeviceDiscoverer(discoverer);
......@@ -223,7 +214,6 @@ void main() {
commands.stream,
responses.add,
notifyingLogger: notifyingLogger,
dartDefines: const <String>[],
);
final MockPollingDeviceDiscovery discoverer = MockPollingDeviceDiscovery();
......@@ -253,7 +243,6 @@ void main() {
commands.stream,
responses.add,
notifyingLogger: notifyingLogger,
dartDefines: const <String>[],
);
commands.add(<String, dynamic>{'id': 0, 'method': 'emulator.launch'});
......@@ -271,7 +260,6 @@ void main() {
commands.stream,
responses.add,
notifyingLogger: notifyingLogger,
dartDefines: const <String>[],
);
commands.add(<String, dynamic>{'id': 0, 'method': 'emulator.getEmulators'});
final Map<String, dynamic> response = await responses.stream.firstWhere(_notEvent);
......@@ -291,7 +279,6 @@ void main() {
input.stream,
output.add,
notifyingLogger: notifyingLogger,
dartDefines: const <String>[],
);
// Respond to any requests from the daemon to expose a URL.
......
......@@ -654,10 +654,9 @@ class MockWebRunnerFactory extends Mock implements WebRunnerFactory {
FlutterProject flutterProject,
bool ipv6,
DebuggingOptions debuggingOptions,
List<String> dartDefines,
UrlTunneller urlTunneller,
}) {
_dartDefines = dartDefines;
_dartDefines = debuggingOptions.buildInfo.dartDefines;
return MockWebRunner();
}
}
......
......@@ -33,7 +33,7 @@ void main() {
when(
mockBundleBuilder.build(
platform: anyNamed('platform'),
buildMode: anyNamed('buildMode'),
buildInfo: anyNamed('buildInfo'),
mainPath: anyNamed('mainPath'),
manifestPath: anyNamed('manifestPath'),
applicationKernelFilePath: anyNamed('applicationKernelFilePath'),
......
......@@ -173,7 +173,7 @@ class TestFlutterDevice extends FlutterDevice {
@required this.exception,
@required ResidentCompiler generator,
}) : assert(exception != null),
super(device, buildMode: BuildMode.debug, generator: generator, trackWidgetCreation: false);
super(device, buildInfo: BuildInfo.debug, generator: generator);
/// The exception to throw when the connect method is called.
final Exception exception;
......
......@@ -135,7 +135,7 @@ void main() {
when(mockDevice.targetPlatform).thenAnswer((Invocation _) async => TargetPlatform.tester);
// Trigger hot restart.
final List<FlutterDevice> devices = <FlutterDevice>[
FlutterDevice(mockDevice, generator: residentCompiler, trackWidgetCreation: false, buildMode: BuildMode.debug)..devFS = mockDevFs,
FlutterDevice(mockDevice, generator: residentCompiler, buildInfo: BuildInfo.debug)..devFS = mockDevFs,
];
final OperationResult result = await HotRunner(devices).restart(fullRestart: true);
// Expect hot restart failed.
......@@ -156,8 +156,8 @@ void main() {
when(mockHotDevice.supportsHotRestart).thenReturn(true);
// Trigger hot restart.
final List<FlutterDevice> devices = <FlutterDevice>[
FlutterDevice(mockDevice, generator: residentCompiler, trackWidgetCreation: false, buildMode: BuildMode.debug)..devFS = mockDevFs,
FlutterDevice(mockHotDevice, generator: residentCompiler, trackWidgetCreation: false, buildMode: BuildMode.debug)..devFS = mockDevFs,
FlutterDevice(mockDevice, generator: residentCompiler, buildInfo: BuildInfo.debug)..devFS = mockDevFs,
FlutterDevice(mockHotDevice, generator: residentCompiler, buildInfo: BuildInfo.debug)..devFS = mockDevFs,
];
final OperationResult result = await HotRunner(devices).restart(fullRestart: true);
// Expect hot restart failed.
......@@ -178,8 +178,8 @@ void main() {
when(mockHotDevice.supportsHotRestart).thenReturn(true);
// Trigger a restart.
final List<FlutterDevice> devices = <FlutterDevice>[
FlutterDevice(mockDevice, generator: residentCompiler, trackWidgetCreation: false, buildMode: BuildMode.debug)..devFS = mockDevFs,
FlutterDevice(mockHotDevice, generator: residentCompiler, trackWidgetCreation: false, buildMode: BuildMode.debug)..devFS = mockDevFs,
FlutterDevice(mockDevice, generator: residentCompiler, buildInfo: BuildInfo.debug)..devFS = mockDevFs,
FlutterDevice(mockHotDevice, generator: residentCompiler, buildInfo: BuildInfo.debug)..devFS = mockDevFs,
];
final HotRunner hotRunner = HotRunner(devices);
final OperationResult result = await hotRunner.restart(fullRestart: true);
......@@ -198,7 +198,7 @@ void main() {
when(mockDevice.supportsHotRestart).thenReturn(true);
when(mockDevice.targetPlatform).thenAnswer((Invocation _) async => TargetPlatform.tester);
final List<FlutterDevice> devices = <FlutterDevice>[
FlutterDevice(mockDevice, generator: residentCompiler, trackWidgetCreation: false, buildMode: BuildMode.debug),
FlutterDevice(mockDevice, generator: residentCompiler, buildInfo: BuildInfo.debug),
];
final OperationResult result = await HotRunner(devices).restart(fullRestart: true);
expect(result.isOk, false);
......@@ -216,7 +216,7 @@ void main() {
when(mockDevice.targetPlatform).thenAnswer((Invocation _) async => TargetPlatform.tester);
// Trigger hot restart.
final List<FlutterDevice> devices = <FlutterDevice>[
FlutterDevice(mockDevice, generator: residentCompiler, trackWidgetCreation: false, buildMode: BuildMode.debug)..devFS = mockDevFs,
FlutterDevice(mockDevice, generator: residentCompiler, buildInfo: BuildInfo.debug)..devFS = mockDevFs,
];
final HotRunner hotRunner = HotRunner(devices);
final OperationResult result = await hotRunner.restart(fullRestart: true);
......@@ -244,7 +244,7 @@ void main() {
when(mockDevice.supportsHotRestart).thenReturn(true);
when(mockDevice.supportsFlutterExit).thenReturn(false);
final List<FlutterDevice> devices = <FlutterDevice>[
FlutterDevice(mockDevice, generator: residentCompiler, trackWidgetCreation: false, buildMode: BuildMode.debug),
FlutterDevice(mockDevice, generator: residentCompiler, buildInfo: BuildInfo.debug),
];
await HotRunner(devices).cleanupAfterSignal();
expect(shutdownTestingConfig.shutdownHookCalled, true);
......@@ -259,7 +259,7 @@ void main() {
when(mockDevice.supportsHotRestart).thenReturn(true);
when(mockDevice.supportsFlutterExit).thenReturn(false);
final List<FlutterDevice> devices = <FlutterDevice>[
FlutterDevice(mockDevice, generator: residentCompiler, trackWidgetCreation: false, buildMode: BuildMode.debug),
FlutterDevice(mockDevice, generator: residentCompiler, buildInfo: BuildInfo.debug),
];
await HotRunner(devices).preExit();
expect(shutdownTestingConfig.shutdownHookCalled, true);
......@@ -386,7 +386,7 @@ class TestFlutterDevice extends FlutterDevice {
@required this.exception,
@required ResidentCompiler generator,
}) : assert(exception != null),
super(device, buildMode: BuildMode.debug, generator: generator, trackWidgetCreation: false);
super(device, buildInfo: BuildInfo.debug, generator: generator);
/// The exception to throw when the connect method is called.
final Exception exception;
......
......@@ -9,8 +9,6 @@ import 'package:file/file.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/targets/dart.dart';
import 'package:flutter_tools/src/build_system/targets/icon_tree_shaker.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/base/file_system.dart';
......@@ -206,26 +204,6 @@ void main() {
});
});
testUsingContext('builds with targetPlatform', () async {
final IOSSimulator simulator = IOSSimulator('x', name: 'iPhone X');
when(buildSystem.build(any, any)).thenAnswer((Invocation invocation) async {
return BuildResult(success: true);
});
await simulator.sideloadUpdatedAssetsForInstalledApplicationBundle(BuildInfo.debug, 'lib/main.dart');
final VerificationResult result = verify(buildSystem.build(any, captureAny));
final Environment environment = result.captured.single as Environment;
expect(environment.defines, <String, String>{
kTargetFile: 'lib/main.dart',
kTargetPlatform: 'ios',
kBuildMode: 'debug',
kTrackWidgetCreation: 'false',
kIconTreeShakerFlag: null,
});
}, overrides: <Type, Generator>{
BuildSystem: () => MockBuildSystem(),
});
group('Simulator screenshot', () {
MockXcode mockXcode;
MockProcessManager mockProcessManager;
......
......@@ -559,7 +559,7 @@ Information about project "Runner":
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: TargetPlatform.ios, mode: anyNamed('mode'))).thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm'));
const BuildInfo buildInfo = BuildInfo(BuildMode.debug, null, treeShakeIcons: false);
const BuildInfo buildInfo = BuildInfo(BuildMode.debug, null, treeShakeIcons: false, trackWidgetCreation: false);
final FlutterProject project = FlutterProject.fromPath('path/to/project');
await updateGeneratedXcodeProperties(
project: project,
......
......@@ -682,10 +682,9 @@ void main() {
final DefaultResidentCompiler residentCompiler = (await FlutterDevice.create(
mockDevice,
buildMode: BuildMode.debug,
buildInfo: BuildInfo.debug,
flutterProject: FlutterProject.current(),
target: null,
trackWidgetCreation: true,
)).generator as DefaultResidentCompiler;
expect(residentCompiler.librariesSpec,
......@@ -747,7 +746,7 @@ class MockProcessManager extends Mock implements ProcessManager {}
class MockServiceEvent extends Mock implements ServiceEvent {}
class TestFlutterDevice extends FlutterDevice {
TestFlutterDevice(Device device, this.views, { Stream<Uri> observatoryUris })
: super(device, buildMode: BuildMode.debug, trackWidgetCreation: false) {
: super(device, buildInfo: BuildInfo.debug) {
_observatoryUris = observatoryUris;
}
......
......@@ -52,7 +52,6 @@ void main() {
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
ipv6: true,
stayResident: true,
dartDefines: const <String>[],
urlTunneller: null,
) as ResidentWebRunner;
},
......
......@@ -77,7 +77,6 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
ipv6: true,
stayResident: true,
dartDefines: const <String>[],
urlTunneller: null,
) as ResidentWebRunner;
globals.fs.currentDirectory.childFile('.packages')
......@@ -139,7 +138,6 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
ipv6: true,
stayResident: true,
dartDefines: const <String>[],
urlTunneller: null,
) as ResidentWebRunner;
......@@ -158,7 +156,6 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, startPaused: true),
ipv6: true,
stayResident: true,
dartDefines: <String>[],
urlTunneller: null,
);
......@@ -174,7 +171,6 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile),
ipv6: true,
stayResident: true,
dartDefines: const <String>[],
urlTunneller: null,
);
......@@ -234,7 +230,6 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
ipv6: true,
stayResident: false,
dartDefines: const <String>[],
urlTunneller: null,
) as ResidentWebRunner;
......@@ -271,7 +266,6 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, startPaused: true),
ipv6: true,
stayResident: true,
dartDefines: const <String>[],
urlTunneller: null,
) as ResidentWebRunner;
_setupMocks();
......@@ -779,7 +773,6 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
ipv6: true,
stayResident: true,
dartDefines: const <String>[],
urlTunneller: null,
) as ResidentWebRunner;
......@@ -820,7 +813,6 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
ipv6: true,
stayResident: true,
dartDefines: const <String>[],
urlTunneller: null,
) as ResidentWebRunner;
......
......@@ -18,7 +18,17 @@ void main() {
// TODO(jacobr): make these tests run with `trackWidgetCreation: true` as
// well as the default flags.
return TestRunner(
<FlutterDevice>[FlutterDevice(MockDevice(), trackWidgetCreation: false, buildMode: BuildMode.debug)],
<FlutterDevice>[
FlutterDevice(
MockDevice(),
buildInfo: const BuildInfo(
BuildMode.debug,
null,
trackWidgetCreation: false,
treeShakeIcons: false,
),
),
],
);
}
......
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