compiler_config.dart 6.78 KB
Newer Older
1 2 3 4
// 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.

5 6
import '../base/utils.dart';

7 8 9 10 11 12 13 14 15
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();
16 17 18 19

  Map<String, Object> get buildEventAnalyticsValues => <String, Object>{
        'wasm-compile': isWasm,
      };
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
}

/// 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 {
137 138
  const WasmCompilerConfig({
    required this.omitTypeChecks,
139
    required this.wasmOpt,
140 141 142 143 144 145 146 147 148
  });

  /// 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',
149
        wasmOpt: WasmOptLevel.values.byName(defines[kRunWasmOpt]!),
150 151
      );

152
  /// Build environment for [omitTypeChecks].
153
  static const String kOmitTypeChecks = 'WasmOmitTypeChecks';
154

155
  /// Build environment for [wasmOpt].
156
  static const String kRunWasmOpt = 'RunWasmOpt';
157 158 159

  /// If `omit-type-checks` should be passed to `dart2wasm`.
  final bool omitTypeChecks;
160

161
  /// Run wasm-opt on the resulting module.
162
  final WasmOptLevel wasmOpt;
163

164 165 166
  @override
  bool get isWasm => true;

167 168
  bool get runWasmOpt => wasmOpt == WasmOptLevel.full || wasmOpt == WasmOptLevel.debug;

169
  @override
170 171
  Map<String, String> toBuildSystemEnvironment() => <String, String>{
    kOmitTypeChecks: omitTypeChecks.toString(),
172
    kRunWasmOpt: wasmOpt.name,
173 174 175 176 177
  };

  List<String> toCommandOptions() => <String>[
    if (omitTypeChecks) '--omit-type-checks',
  ];
178 179 180 181

  @override
  Map<String, Object> get buildEventAnalyticsValues => <String, Object>{
    ...super.buildEventAnalyticsValues,
182
    ...toBuildSystemEnvironment(),
183
  };
184
}
185 186 187 188 189 190 191 192 193 194 195 196

enum WasmOptLevel implements CliEnum {
  full,
  debug,
  none;

  static const WasmOptLevel defaultValue = WasmOptLevel.full;

  @override
  String get cliName => name;

  @override
197
  String get helpText => switch (this) {
198
    WasmOptLevel.none => 'wasm-opt is not run. Fastest build; bigger, slower output.',
199
    WasmOptLevel.debug => 'Similar to `${WasmOptLevel.full.name}`, but member names are preserved. Debugging is easier, but size is a bit bigger.',
200 201 202
    WasmOptLevel.full => 'wasm-opt is run. Build time is slower, but output is smaller and faster.',
  };
}