mirror of
https://github.com/flutter/flutter.git
synced 2026-02-11 21:33:08 +08:00
Refiling of #169273 (reverted in https://github.com/flutter/flutter/pull/170034), which is a refiling of #164094, which itself is a rebase of #159675. This PR adds bundling support for the experimental dart data asset feature: Dart packages with hooks can now emit data assets which the flutter tool will bundle. It relies on flutter's existing asset bundling mechanism (e.g. entries in AssetManifest.json, DevFS syncing in reload/restart, ...). The support is added under an experimental flag (similar to the existing native assets experimental flag). Also, kNativeAssets is removed to also bundle data assets on flutter build bundle. The chrome sandbox is disabled as per #165664. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
384 lines
12 KiB
Dart
384 lines
12 KiB
Dart
// 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.
|
|
|
|
/// @docImport 'flutter_features.dart';
|
|
library;
|
|
|
|
import 'package:meta/meta.dart';
|
|
|
|
import 'base/context.dart';
|
|
|
|
/// The current [FeatureFlags] implementation.
|
|
FeatureFlags get featureFlags => context.get<FeatureFlags>()!;
|
|
|
|
/// The interface used to determine if a particular [Feature] is enabled.
|
|
///
|
|
/// This class is extended in google3. Whenever a new flag is added,
|
|
/// google3 must also be updated using a g3fix.
|
|
///
|
|
/// See also:
|
|
///
|
|
/// * [FlutterFeatureFlags], Flutter's implementation of this class.
|
|
/// * https://github.com/flutter/flutter/blob/main/docs/contributing/Feature-flags.md,
|
|
/// docs on feature flags and how to add or use them.
|
|
abstract class FeatureFlags {
|
|
/// const constructor so that subclasses can be const.
|
|
const FeatureFlags();
|
|
|
|
/// Whether flutter desktop for linux is enabled.
|
|
bool get isLinuxEnabled;
|
|
|
|
/// Whether flutter desktop for macOS is enabled.
|
|
bool get isMacOSEnabled;
|
|
|
|
/// Whether flutter web is enabled.
|
|
bool get isWebEnabled;
|
|
|
|
/// Whether flutter desktop for Windows is enabled.
|
|
bool get isWindowsEnabled;
|
|
|
|
/// Whether android is enabled.
|
|
bool get isAndroidEnabled;
|
|
|
|
/// Whether iOS is enabled.
|
|
bool get isIOSEnabled;
|
|
|
|
/// Whether fuchsia is enabled.
|
|
bool get isFuchsiaEnabled;
|
|
|
|
/// Whether custom devices are enabled.
|
|
bool get areCustomDevicesEnabled;
|
|
|
|
/// Whether animations are used in the command line interface.
|
|
bool get isCliAnimationEnabled;
|
|
|
|
/// Whether native assets compilation and bundling is enabled.
|
|
bool get isNativeAssetsEnabled;
|
|
|
|
/// Whether dart data assets building and bundling is enabled.
|
|
bool get isDartDataAssetsEnabled => false;
|
|
|
|
/// Whether Swift Package Manager dependency management is enabled.
|
|
bool get isSwiftPackageManagerEnabled;
|
|
|
|
/// Whether to stop writing the `{FLUTTER_ROOT}/version` file.
|
|
///
|
|
/// Tracking removal: <https://github.com/flutter/flutter/issues/171900>.
|
|
bool get isOmitLegacyVersionFileEnabled;
|
|
|
|
/// Whether desktop windowing is enabled.
|
|
bool get isWindowingEnabled;
|
|
|
|
/// Whether physical iOS devices are debugging with LLDB.
|
|
bool get isLLDBDebuggingEnabled;
|
|
|
|
/// Whether a particular feature is enabled for the current channel.
|
|
///
|
|
/// Prefer using one of the specific getters above instead of this API.
|
|
bool isEnabled(Feature feature);
|
|
|
|
/// All current Flutter feature flags.
|
|
List<Feature> get allFeatures => const <Feature>[
|
|
flutterWebFeature,
|
|
flutterLinuxDesktopFeature,
|
|
flutterMacOSDesktopFeature,
|
|
flutterWindowsDesktopFeature,
|
|
flutterAndroidFeature,
|
|
flutterIOSFeature,
|
|
flutterFuchsiaFeature,
|
|
flutterCustomDevicesFeature,
|
|
cliAnimation,
|
|
nativeAssets,
|
|
dartDataAssets,
|
|
swiftPackageManager,
|
|
omitLegacyVersionFile,
|
|
windowingFeature,
|
|
lldbDebugging,
|
|
];
|
|
|
|
/// All current Flutter feature flags that can be configured.
|
|
///
|
|
/// [Feature.configSetting] is not `null`.
|
|
Iterable<Feature> get allConfigurableFeatures {
|
|
return allFeatures.where((Feature feature) => feature.configSetting != null);
|
|
}
|
|
|
|
/// All Flutter feature flags that are enabled.
|
|
// This member is overriden in google3.
|
|
Iterable<Feature> get allEnabledFeatures {
|
|
return allFeatures.where(isEnabled);
|
|
}
|
|
}
|
|
|
|
/// All current Flutter feature flags that can be configured.
|
|
///
|
|
/// [Feature.configSetting] is not `null`.
|
|
Iterable<Feature> get allConfigurableFeatures => featureFlags.allConfigurableFeatures;
|
|
|
|
/// The [Feature] for flutter web.
|
|
const flutterWebFeature = Feature.fullyEnabled(
|
|
name: 'Flutter for web',
|
|
configSetting: 'enable-web',
|
|
environmentOverride: 'FLUTTER_WEB',
|
|
);
|
|
|
|
/// The [Feature] for macOS desktop.
|
|
const flutterMacOSDesktopFeature = Feature.fullyEnabled(
|
|
name: 'support for desktop on macOS',
|
|
configSetting: 'enable-macos-desktop',
|
|
environmentOverride: 'FLUTTER_MACOS',
|
|
);
|
|
|
|
/// The [Feature] for Linux desktop.
|
|
const flutterLinuxDesktopFeature = Feature.fullyEnabled(
|
|
name: 'support for desktop on Linux',
|
|
configSetting: 'enable-linux-desktop',
|
|
environmentOverride: 'FLUTTER_LINUX',
|
|
);
|
|
|
|
/// The [Feature] for Windows desktop.
|
|
const flutterWindowsDesktopFeature = Feature.fullyEnabled(
|
|
name: 'support for desktop on Windows',
|
|
configSetting: 'enable-windows-desktop',
|
|
environmentOverride: 'FLUTTER_WINDOWS',
|
|
);
|
|
|
|
/// The [Feature] for Android devices.
|
|
const flutterAndroidFeature = Feature.fullyEnabled(
|
|
name: 'Flutter for Android',
|
|
configSetting: 'enable-android',
|
|
);
|
|
|
|
/// The [Feature] for iOS devices.
|
|
const flutterIOSFeature = Feature.fullyEnabled(
|
|
name: 'Flutter for iOS',
|
|
configSetting: 'enable-ios',
|
|
);
|
|
|
|
/// The [Feature] for Fuchsia support.
|
|
const flutterFuchsiaFeature = Feature(
|
|
name: 'Flutter for Fuchsia',
|
|
configSetting: 'enable-fuchsia',
|
|
environmentOverride: 'FLUTTER_FUCHSIA',
|
|
master: FeatureChannelSetting(available: true),
|
|
);
|
|
|
|
const flutterCustomDevicesFeature = Feature(
|
|
name: 'early support for custom device types',
|
|
configSetting: 'enable-custom-devices',
|
|
environmentOverride: 'FLUTTER_CUSTOM_DEVICES',
|
|
master: FeatureChannelSetting(available: true),
|
|
beta: FeatureChannelSetting(available: true),
|
|
stable: FeatureChannelSetting(available: true),
|
|
);
|
|
|
|
/// The [Feature] for CLI animations.
|
|
///
|
|
/// The TERM environment variable set to "dumb" turns this off.
|
|
const cliAnimation = Feature.fullyEnabled(
|
|
name: 'animations in the command line interface',
|
|
configSetting: 'cli-animations',
|
|
);
|
|
|
|
/// Enable native assets compilation and bundling.
|
|
const nativeAssets = Feature(
|
|
name: 'native assets compilation and bundling',
|
|
configSetting: 'enable-native-assets',
|
|
environmentOverride: 'FLUTTER_NATIVE_ASSETS',
|
|
master: FeatureChannelSetting(available: true, enabledByDefault: true),
|
|
beta: FeatureChannelSetting(available: true, enabledByDefault: true),
|
|
);
|
|
|
|
/// Enable Dart data assets building and bundling.
|
|
const dartDataAssets = Feature(
|
|
name: 'Dart data assets building and bundling',
|
|
configSetting: 'enable-dart-data-assets',
|
|
environmentOverride: 'FLUTTER_DART_DATA_ASSETS',
|
|
master: FeatureChannelSetting(available: true),
|
|
);
|
|
|
|
/// Enable Swift Package Manager as a darwin dependency manager.
|
|
const swiftPackageManager = Feature(
|
|
name: 'support for Swift Package Manager for iOS and macOS',
|
|
configSetting: 'enable-swift-package-manager',
|
|
environmentOverride: 'FLUTTER_SWIFT_PACKAGE_MANAGER',
|
|
master: FeatureChannelSetting(available: true),
|
|
beta: FeatureChannelSetting(available: true),
|
|
stable: FeatureChannelSetting(available: true),
|
|
);
|
|
|
|
/// Whether to continue writing the `{FLUTTER_ROOT}/version` legacy file.
|
|
///
|
|
/// Tracking removal: <https://github.com/flutter/flutter/issues/171900>.
|
|
const omitLegacyVersionFile = Feature.fullyEnabled(
|
|
name: 'stops writing the legacy version file',
|
|
configSetting: 'omit-legacy-version-file',
|
|
extraHelpText:
|
|
'If set, the file {FLUTTER_ROOT}/version is no longer written as part of '
|
|
'the flutter tool execution; a newer file format has existed for some '
|
|
'time in {FLUTTER_ROOT}/bin/cache/flutter.version.json.',
|
|
);
|
|
|
|
/// Whether desktop windowing is enabled.
|
|
///
|
|
/// See: https://github.com/flutter/flutter/issues/30701.
|
|
const windowingFeature = Feature(
|
|
name: 'support for windowing on macOS, Linux, and Windows',
|
|
configSetting: 'enable-windowing',
|
|
environmentOverride: 'FLUTTER_WINDOWING',
|
|
runtimeId: 'windowing',
|
|
master: FeatureChannelSetting(available: true),
|
|
);
|
|
|
|
/// Enable LLDB debugging for physical iOS devices. When LLDB debugging is off,
|
|
/// Xcode debugging is used instead.
|
|
///
|
|
/// Requires iOS 17+ and Xcode 26+. If those requirements are not met, the previous
|
|
/// default debugging method is used instead.
|
|
const lldbDebugging = Feature(
|
|
name: 'support for debugging with LLDB for physical iOS devices',
|
|
extraHelpText:
|
|
'If LLDB debugging is off, Xcode debugging is used instead. '
|
|
'Only available for iOS 17 or newer devices. Requires Xcode 26 or greater.',
|
|
configSetting: 'enable-lldb-debugging',
|
|
environmentOverride: 'FLUTTER_LLDB_DEBUGGING',
|
|
master: FeatureChannelSetting(available: true, enabledByDefault: true),
|
|
beta: FeatureChannelSetting(available: true, enabledByDefault: true),
|
|
stable: FeatureChannelSetting(available: true, enabledByDefault: true),
|
|
);
|
|
|
|
/// A [Feature] is a process for conditionally enabling tool features.
|
|
///
|
|
/// All settings are optional, and if not provided will generally default to
|
|
/// a "safe" value, such as being off.
|
|
///
|
|
/// The top level feature settings can be provided to apply to all channels.
|
|
/// Otherwise, more specific settings take precedence over higher level
|
|
/// settings.
|
|
class Feature {
|
|
/// Creates a [Feature].
|
|
const Feature({
|
|
required this.name,
|
|
this.environmentOverride,
|
|
this.configSetting,
|
|
this.runtimeId,
|
|
this.extraHelpText,
|
|
this.master = const FeatureChannelSetting(),
|
|
this.beta = const FeatureChannelSetting(),
|
|
this.stable = const FeatureChannelSetting(),
|
|
});
|
|
|
|
/// Creates a [Feature] that is fully enabled across channels.
|
|
const Feature.fullyEnabled({
|
|
required this.name,
|
|
this.environmentOverride,
|
|
this.configSetting,
|
|
this.runtimeId,
|
|
this.extraHelpText,
|
|
}) : master = const FeatureChannelSetting(available: true, enabledByDefault: true),
|
|
beta = const FeatureChannelSetting(available: true, enabledByDefault: true),
|
|
stable = const FeatureChannelSetting(available: true, enabledByDefault: true);
|
|
|
|
/// The user visible name for this feature.
|
|
final String name;
|
|
|
|
/// The settings for the master branch and other unknown channels.
|
|
final FeatureChannelSetting master;
|
|
|
|
/// The settings for the beta branch.
|
|
final FeatureChannelSetting beta;
|
|
|
|
/// The settings for the stable branch.
|
|
final FeatureChannelSetting stable;
|
|
|
|
/// The name of an environment variable that can override the setting.
|
|
///
|
|
/// The environment variable needs to be set to the value 'true'. This is
|
|
/// only intended for usage by CI and not as an advertised method to enable
|
|
/// a feature.
|
|
///
|
|
/// If not provided, defaults to `null` meaning there is no override.
|
|
final String? environmentOverride;
|
|
|
|
/// The name of a setting that can be used to enable this feature.
|
|
///
|
|
/// If not provided, defaults to `null` meaning there is no config setting.
|
|
final String? configSetting;
|
|
|
|
/// The unique identifier for this feature at runtime.
|
|
///
|
|
/// If not `null`, the Flutter framework's enabled feature flags will
|
|
/// contain this value if this feature is enabled.
|
|
final String? runtimeId;
|
|
|
|
/// Additional text to add to the end of the help message.
|
|
///
|
|
/// If not provided, defaults to `null` meaning there is no additional text.
|
|
final String? extraHelpText;
|
|
|
|
/// A help message for the `flutter config` command, or null if unsupported.
|
|
String? generateHelpMessage() {
|
|
if (configSetting == null) {
|
|
return null;
|
|
}
|
|
final buffer = StringBuffer('Enable or disable $name.');
|
|
final channels = <String>[
|
|
if (master.available) 'master',
|
|
if (beta.available) 'beta',
|
|
if (stable.available) 'stable',
|
|
];
|
|
// Add channel info for settings only on some channels.
|
|
if (channels.length == 1) {
|
|
buffer.write('\nThis setting applies only to the ${channels.single} channel.');
|
|
} else if (channels.length == 2) {
|
|
buffer.write('\nThis setting applies only to the ${channels.join(' and ')} channels.');
|
|
}
|
|
if (extraHelpText != null) {
|
|
buffer.write(' $extraHelpText');
|
|
}
|
|
return buffer.toString();
|
|
}
|
|
|
|
/// Retrieve the correct setting for the provided `channel`.
|
|
FeatureChannelSetting getSettingForChannel(String channel) {
|
|
return switch (channel) {
|
|
'stable' => stable,
|
|
'beta' => beta,
|
|
'master' || _ => master,
|
|
};
|
|
}
|
|
}
|
|
|
|
/// A description of the conditions to enable a feature for a particular channel.
|
|
@immutable
|
|
final class FeatureChannelSetting {
|
|
const FeatureChannelSetting({this.available = false, this.enabledByDefault = false});
|
|
|
|
/// Whether the feature is available on this channel.
|
|
///
|
|
/// If not provided, defaults to `false`. This implies that the feature
|
|
/// cannot be enabled even by the settings below.
|
|
final bool available;
|
|
|
|
/// Whether the feature is enabled by default.
|
|
///
|
|
/// If not provided, defaults to `false`.
|
|
final bool enabledByDefault;
|
|
|
|
@override
|
|
bool operator ==(Object other) {
|
|
return other is FeatureChannelSetting &&
|
|
available == other.available &&
|
|
enabledByDefault == other.enabledByDefault;
|
|
}
|
|
|
|
@override
|
|
int get hashCode => Object.hash(available, enabledByDefault);
|
|
|
|
@override
|
|
String toString() {
|
|
return 'FeatureChannelSetting <available: $available, enabledByDefault: $enabledByDefault>';
|
|
}
|
|
}
|