Loïc Sharma d8c4fc0bc6
[SwiftPM] Turn on by default (#161275)
This turns on Swift Package Manager by default:

1. New apps will have Swift Package Manager integration
2. New plugins will support Swift Package Manager
3. Existing apps will continue to use CocoaPods. They can migrate to
SwiftPM using `flutter config --enable-swift-package-manager-migration`.

See this mini design doc:
https://github.com/flutter/flutter/issues/151567#issuecomment-2455941279

Here's the PR that updates the SwiftPM docs:
https://github.com/flutter/website/pull/11495

Part of https://github.com/flutter/flutter/issues/151567

## 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.
- [ ] 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
2025-01-08 21:15:57 +00:00

320 lines
11 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.
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.
///
/// The rest of the tools code should use this class instead of looking up
/// features directly. To facilitate rolls to google3 and other clients, all
/// flags should be provided with a default implementation here. Clients that
/// use this class should extent instead of implement, so that new flags are
/// picked up automatically.
abstract class FeatureFlags {
/// const constructor so that subclasses can be const.
const FeatureFlags();
/// Whether flutter desktop for linux is enabled.
bool get isLinuxEnabled => false;
/// Whether flutter desktop for macOS is enabled.
bool get isMacOSEnabled => false;
/// Whether flutter web is enabled.
bool get isWebEnabled => false;
/// Whether flutter desktop for Windows is enabled.
bool get isWindowsEnabled => false;
/// Whether android is enabled.
bool get isAndroidEnabled => true;
/// Whether iOS is enabled.
bool get isIOSEnabled => true;
/// Whether fuchsia is enabled.
bool get isFuchsiaEnabled => true;
/// Whether custom devices are enabled.
bool get areCustomDevicesEnabled => false;
/// Whether animations are used in the command line interface.
bool get isCliAnimationEnabled => true;
/// Whether native assets compilation and bundling is enabled.
bool get isNativeAssetsEnabled => false;
/// Whether native assets compilation and bundling is enabled.
bool get isPreviewDeviceEnabled => true;
/// Whether Swift Package Manager dependency management is enabled.
bool get isSwiftPackageManagerEnabled => true;
/// Whether apps are automatically migrated to add Swift Package Manager
/// integration. Requires [isSwiftPackageManagerEnabled].
bool get isSwiftPackageManagerMigrationEnabled => false;
/// Whether explicit package dependency management is enabled.
bool get isExplicitPackageDependenciesEnabled => false;
/// 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.
const List<Feature> allFeatures = <Feature>[
flutterWebFeature,
flutterLinuxDesktopFeature,
flutterMacOSDesktopFeature,
flutterWindowsDesktopFeature,
flutterAndroidFeature,
flutterIOSFeature,
flutterFuchsiaFeature,
flutterCustomDevicesFeature,
cliAnimation,
nativeAssets,
previewDevice,
swiftPackageManager,
swiftPackageManagerMigration,
explicitPackageDependencies,
];
/// All current Flutter feature flags that can be configured.
///
/// [Feature.configSetting] is not `null`.
Iterable<Feature> get allConfigurableFeatures =>
allFeatures.where((Feature feature) => feature.configSetting != null);
/// The [Feature] for flutter web.
const Feature flutterWebFeature = Feature.fullyEnabled(
name: 'Flutter for web',
configSetting: 'enable-web',
environmentOverride: 'FLUTTER_WEB',
);
/// The [Feature] for macOS desktop.
const Feature flutterMacOSDesktopFeature = Feature.fullyEnabled(
name: 'support for desktop on macOS',
configSetting: 'enable-macos-desktop',
environmentOverride: 'FLUTTER_MACOS',
);
/// The [Feature] for Linux desktop.
const Feature flutterLinuxDesktopFeature = Feature.fullyEnabled(
name: 'support for desktop on Linux',
configSetting: 'enable-linux-desktop',
environmentOverride: 'FLUTTER_LINUX',
);
/// The [Feature] for Windows desktop.
const Feature flutterWindowsDesktopFeature = Feature.fullyEnabled(
name: 'support for desktop on Windows',
configSetting: 'enable-windows-desktop',
environmentOverride: 'FLUTTER_WINDOWS',
);
/// The [Feature] for Android devices.
const Feature flutterAndroidFeature = Feature.fullyEnabled(
name: 'Flutter for Android',
configSetting: 'enable-android',
);
/// The [Feature] for iOS devices.
const Feature flutterIOSFeature = Feature.fullyEnabled(
name: 'Flutter for iOS',
configSetting: 'enable-ios',
);
/// The [Feature] for Fuchsia support.
const Feature flutterFuchsiaFeature = Feature(
name: 'Flutter for Fuchsia',
configSetting: 'enable-fuchsia',
environmentOverride: 'FLUTTER_FUCHSIA',
master: FeatureChannelSetting(available: true),
);
const Feature 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 Feature cliAnimation = Feature.fullyEnabled(
name: 'animations in the command line interface',
configSetting: 'cli-animations',
);
/// Enable native assets compilation and bundling.
const Feature nativeAssets = Feature(
name: 'native assets compilation and bundling',
configSetting: 'enable-native-assets',
environmentOverride: 'FLUTTER_NATIVE_ASSETS',
master: FeatureChannelSetting(available: true),
);
/// Enable Flutter preview prebuilt device.
const Feature previewDevice = Feature(
name: 'Flutter preview prebuilt device',
configSetting: 'enable-flutter-preview',
environmentOverride: 'FLUTTER_PREVIEW_DEVICE',
master: FeatureChannelSetting(available: true),
beta: FeatureChannelSetting(available: true),
);
/// Enable Swift Package Manager as a darwin dependency manager.
const Feature swiftPackageManager = Feature.fullyEnabled(
name: 'support for Swift Package Manager for iOS and macOS',
configSetting: 'enable-swift-package-manager',
environmentOverride: 'FLUTTER_SWIFT_PACKAGE_MANAGER',
);
/// Enable migrating iOS and macOS apps to add Swift Package Manager integration.
const Feature swiftPackageManagerMigration = Feature(
name: 'migrate iOS and macOS apps to add Swift Package Manager integration',
configSetting: 'enable-swift-package-manager-migration',
environmentOverride: 'FLUTTER_SWIFT_PACKAGE_MANAGER_MIGRATION',
master: FeatureChannelSetting(available: true),
beta: FeatureChannelSetting(available: true),
stable: FeatureChannelSetting(available: true),
);
/// Enable explicit resolution and generation of package dependencies.
const Feature explicitPackageDependencies = Feature(
name: 'support for dev_dependency plugins',
configSetting: 'explicit-package-dependencies',
extraHelpText:
'Plugins that are resolved as result of being in "dev_dependencies" of a '
'package are not included in release builds of an app. By enabling this '
'feature, the synthetic "package:flutter_gen" can no longer be generated '
'and the legacy ".flutter-plugins" tool artifact is no longer generated.\n'
'\n'
'See also:\n'
'* https://flutter.dev/to/flutter-plugins-configuration.\n'
'* https://flutter.dev/to/flutter-gen-deprecation.',
master: FeatureChannelSetting(available: true),
beta: FeatureChannelSetting(available: true),
stable: FeatureChannelSetting(available: 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.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.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;
/// 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 StringBuffer buffer = StringBuffer('Enable or disable $name.');
final List<String> 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.
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;
}