blob: 286725b60481b18f0306d5f275265fe50f6bb7fa [file] [log] [blame]
// 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 '../base/utils.dart';
abstract class WebCompilerConfig {
const WebCompilerConfig();
/// Returns `true` if `this` represents configuration for the Wasm compiler.
///
/// Otherwise, `false`–represents the JavaScript compiler.
bool get isWasm;
Map<String, String> toBuildSystemEnvironment();
Map<String, Object> get buildEventAnalyticsValues => <String, Object>{
'wasm-compile': isWasm,
};
}
/// Configuration for the Dart-to-Javascript compiler (dart2js).
class JsCompilerConfig extends WebCompilerConfig {
const JsCompilerConfig({
required this.csp,
required this.dumpInfo,
required this.nativeNullAssertions,
required this.optimizationLevel,
required this.noFrequencyBasedMinification,
required this.sourceMaps,
});
/// Instantiates [JsCompilerConfig] suitable for the `flutter run` command.
const JsCompilerConfig.run({required bool nativeNullAssertions})
: this(
csp: false,
dumpInfo: false,
nativeNullAssertions: nativeNullAssertions,
noFrequencyBasedMinification: false,
optimizationLevel: kDart2jsDefaultOptimizationLevel,
sourceMaps: true,
);
/// Creates a new [JsCompilerConfig] from build system environment values.
///
/// Should correspond exactly with [toBuildSystemEnvironment].
factory JsCompilerConfig.fromBuildSystemEnvironment(
Map<String, String> defines) =>
JsCompilerConfig(
csp: defines[kCspMode] == 'true',
dumpInfo: defines[kDart2jsDumpInfo] == 'true',
nativeNullAssertions: defines[kNativeNullAssertions] == 'true',
optimizationLevel: defines[kDart2jsOptimization] ?? kDart2jsDefaultOptimizationLevel,
noFrequencyBasedMinification: defines[kDart2jsNoFrequencyBasedMinification] == 'true',
sourceMaps: defines[kSourceMapsEnabled] == 'true',
);
/// The default optimization level for dart2js.
///
/// Maps to [kDart2jsOptimization].
static const String kDart2jsDefaultOptimizationLevel = 'O4';
/// Build environment flag for [optimizationLevel].
static const String kDart2jsOptimization = 'Dart2jsOptimization';
/// Build environment flag for [dumpInfo].
static const String kDart2jsDumpInfo = 'Dart2jsDumpInfo';
/// Build environment flag for [noFrequencyBasedMinification].
static const String kDart2jsNoFrequencyBasedMinification =
'Dart2jsNoFrequencyBasedMinification';
/// Build environment flag for [csp].
static const String kCspMode = 'cspMode';
/// Build environment flag for [sourceMaps].
static const String kSourceMapsEnabled = 'SourceMaps';
/// Build environment flag for [nativeNullAssertions].
static const String kNativeNullAssertions = 'NativeNullAssertions';
/// Whether to disable dynamic generation code to satisfy CSP policies.
final bool csp;
/// If `--dump-info` should be passed to the compiler.
final bool dumpInfo;
/// Whether native null assertions are enabled.
final bool nativeNullAssertions;
// If `--no-frequency-based-minification` should be passed to dart2js
// TODO(kevmoo): consider renaming this to be "positive". Double negatives are confusing.
final bool noFrequencyBasedMinification;
/// The compiler optimization level.
///
/// Valid values are O1 (lowest, profile default) to O4 (highest, release default).
// TODO(kevmoo): consider storing this as an [int] and validating it!
final String optimizationLevel;
/// `true` if the JavaScript compiler build should output source maps.
final bool sourceMaps;
@override
bool get isWasm => false;
@override
Map<String, String> toBuildSystemEnvironment() => <String, String>{
kCspMode: csp.toString(),
kDart2jsDumpInfo: dumpInfo.toString(),
kNativeNullAssertions: nativeNullAssertions.toString(),
kDart2jsNoFrequencyBasedMinification: noFrequencyBasedMinification.toString(),
kDart2jsOptimization: optimizationLevel,
kSourceMapsEnabled: sourceMaps.toString(),
};
/// Arguments to use in both phases: full JS compile and CFE-only.
List<String> toSharedCommandOptions() => <String>[
if (nativeNullAssertions) '--native-null-assertions',
if (!sourceMaps) '--no-source-maps',
];
/// Arguments to use in the full JS compile, but not CFE-only.
///
/// Includes the contents of [toSharedCommandOptions].
List<String> toCommandOptions() => <String>[
...toSharedCommandOptions(),
'-$optimizationLevel',
if (dumpInfo) '--dump-info',
if (noFrequencyBasedMinification) '--no-frequency-based-minification',
if (csp) '--csp',
];
}
/// Configuration for the Wasm compiler.
class WasmCompilerConfig extends WebCompilerConfig {
const WasmCompilerConfig({
required this.omitTypeChecks,
required this.wasmOpt,
});
/// Creates a new [WasmCompilerConfig] from build system environment values.
///
/// Should correspond exactly with [toBuildSystemEnvironment].
factory WasmCompilerConfig.fromBuildSystemEnvironment(
Map<String, String> defines) =>
WasmCompilerConfig(
omitTypeChecks: defines[kOmitTypeChecks] == 'true',
wasmOpt: WasmOptLevel.values.byName(defines[kRunWasmOpt]!),
);
/// Build environment for [omitTypeChecks].
static const String kOmitTypeChecks = 'WasmOmitTypeChecks';
/// Build environment for [wasmOpt].
static const String kRunWasmOpt = 'RunWasmOpt';
/// If `omit-type-checks` should be passed to `dart2wasm`.
final bool omitTypeChecks;
/// Run wasm-opt on the resulting module.
final WasmOptLevel wasmOpt;
@override
bool get isWasm => true;
bool get runWasmOpt => wasmOpt == WasmOptLevel.full || wasmOpt == WasmOptLevel.debug;
@override
Map<String, String> toBuildSystemEnvironment() => <String, String>{
kOmitTypeChecks: omitTypeChecks.toString(),
kRunWasmOpt: wasmOpt.name,
};
List<String> toCommandOptions() => <String>[
if (omitTypeChecks) '--omit-type-checks',
];
@override
Map<String, Object> get buildEventAnalyticsValues => <String, Object>{
...super.buildEventAnalyticsValues,
...toBuildSystemEnvironment(),
};
}
enum WasmOptLevel implements CliEnum {
full,
debug,
none;
static const WasmOptLevel defaultValue = WasmOptLevel.full;
@override
String get cliName => name;
@override
String get helpText => switch (this) {
WasmOptLevel.none => 'wasm-opt is not run. Fastest build; bigger, slower output.',
WasmOptLevel.debug => 'Similar to `${WasmOptLevel.full.name}`, but member names are preserved. Debugging is easier, but size is a bit bigger.',
WasmOptLevel.full => 'wasm-opt is run. Build time is slower, but output is smaller and faster.',
};
}