You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[ios] guideline on iOS engine feature flags: Info.plist vs cmd flag #172183
There are currently 2 ways of setting the flag on iOS: via cmd line flags or via Info.plist. It's unclear to me which one to use, as I see pros and cons on both.
Also there's an inconsistent practice: on android, systrace is enabled via cmd flag(see), but on iOS it's enabled via Info.plist (see)
changed the title [-]guideline on iOS engine feature flags: Info.plist vs cmd flag[/-][+][ios] guideline on iOS engine feature flags: Info.plist vs cmd flag[/+]on Jul 15, 2025
There is currently no way to configure the iOS engine using feature flags (and support is not immediately planned), or configure any embedder. For example, --enable-impeller is not a feature flag (not a FeatureFlag), and there is no path (today) to converting it to one.
If you're asking a more general question of "should someone configure a flag, that is possible to use flutter config for, using flutter config --enable-x or flutter: config: enable-x: true, I'd recommend the pubspec.yaml route, but we're keeping both around.
The cross-platform flags are more convenient for app developers as they are already familiar with the flutter tool and the .pubspec file. On the other hand, app developers are less familiar with platform-specific configuration files like Info.plist.
However, Flutter's cross-platform feature flags can only be used in the Flutter tool and Flutter framework. If the embedder or engine needs to know the value of a feature flag before the Dart isolate is launched, you should continue to use platform-specific configuration files like Info.plist.
I'll update our feature flags guidance to explain this!
"Trace early application lifecycle. Automatically switches to an "
"endless trace buffer.")
DEF_SWITCH(TraceSkia,
"trace-skia",
"Trace Skia calls. This is useful when debugging the GPU threed."
"By default, Skia tracing is not enabled to reduce the number of "
"traced events")
DEF_SWITCH(TraceSkiaAllowlist,
"trace-skia-allowlist",
"Filters out all Skia trace event categories except those that are "
"specified in this comma separated list.")
DEF_SWITCH(
TraceAllowlist,
"trace-allowlist",
"Filters out all trace events except those that are specified in this "
"comma separated list of allowed prefixes.")
DEF_SWITCH(DumpSkpOnShaderCompilation,
"dump-skp-on-shader-compilation",
"Automatically dump the skp that triggers new shader compilations. "
"This is useful for writing custom ShaderWarmUp to reduce jank. "
"By default, this is not enabled to reduce the overhead. ")
DEF_SWITCH(CacheSkSL,
"cache-sksl",
"Only cache the shader in SkSL instead of binary or GLSL. This "
"should only be used during development phases. The generated SkSLs "
"can later be used in the release build for shader precompilation "
"at launch in order to eliminate the shader-compile jank.")
DEF_SWITCH(PurgePersistentCache,
"purge-persistent-cache",
"Remove all existing persistent cache. This is mainly for debugging "
"purposes such as reproducing the shader compilation jank.")
DEF_SWITCH(
TraceSystrace,
"trace-systrace",
"Trace to the system tracer (instead of the timeline) on platforms where "
"such a tracer is available. Currently only supported on Android and "
"Fuchsia.")
DEF_SWITCH(TraceToFile,
"trace-to-file",
"Write the timeline trace to a file at the specified path. The file "
"will be in Perfetto's proto format; it will be possible to load "
"the file into Perfetto's trace viewer.")
DEF_SWITCH(ProfileMicrotasks,
"profile-microtasks",
"Enable collection of information about each microtask. Information "
"about completed microtasks will be written to the \"Microtask\""
"timeline stream. Information about queued microtasks will be "
"accessible from Dart / Flutter DevTools.")
DEF_SWITCH(UseTestFonts,
"use-test-fonts",
"Running tests that layout and measure text will not yield "
"consistent results across various platforms. Enabling this option "
"will make font resolution default to the Ahem test font on all "
"platforms (See https://www.w3.org/Style/CSS/Test/Fonts/Ahem/). "
"This option is only available on the desktop test shells.")
DEF_SWITCH(DisableAssetFonts,
"disable-asset-fonts",
"Prevents usage of any non-test fonts unless they were explicitly "
"Loaded via dart:ui font APIs. This option is only available on the "
"desktop test shells.")
DEF_SWITCH(PrefetchedDefaultFontManager,
"prefetched-default-font-manager",
"Indicates whether the embedding started a prefetch of the "
"default font manager before creating the engine.")
DEF_SWITCH(VerboseLogging,
"verbose-logging",
"By default, only errors are logged. This flag enabled logging at "
"all severity levels. This is NOT a per shell flag and affect log "
"levels for all shells in the process.")
DEF_SWITCH(RunForever,
"run-forever",
"In non-interactive mode, keep the shell running after the Dart "
"script has completed.")
DEF_SWITCH(DisableDartAsserts,
"disable-dart-asserts",
"Dart code runs with assertions enabled when the runtime mode is "
"debug. In profile and release product modes, assertions are "
"disabled. This flag may be specified if the user wishes to run "
"with assertions disabled in the debug product mode (i.e. with JIT "
"or DBC).")
DEF_SWITCH(EnableSerialGC,
"enable-serial-gc",
"On low power devices with low core counts, running concurrent "
"GC tasks on threads can cause them to contend with the UI thread "
"which could potentially lead to jank. This option turns off all "
"concurrent GC activities")
DEF_SWITCH(DisallowInsecureConnections,
"disallow-insecure-connections",
"By default, dart:io allows all socket connections. If this switch "
"is set, all insecure connections are rejected.")
DEF_SWITCH(DomainNetworkPolicy,
"domain-network-policy",
"JSON encoded network policy per domain. This overrides the "
"DisallowInsecureConnections switch. Embedder can specify whether "
"to allow or disallow insecure connections at a domain level.")
DEF_SWITCH(
ForceMultithreading,
"force-multithreading",
"Uses separate threads for the platform, UI, GPU and IO task runners. "
"By default, a single thread is used for all task runners. Only available "
"in the flutter_tester.")
DEF_SWITCH(OldGenHeapSize,
"old-gen-heap-size",
"The size limit in megabytes for the Dart VM old gen heap space.")
DEF_SWITCH(ResourceCacheMaxBytesThreshold,
"resource-cache-max-bytes-threshold",
"The max bytes threshold of resource cache, or 0 for unlimited.")
DEF_SWITCH(EnableImpeller,
"enable-impeller",
"Enable the Impeller renderer on supported platforms. Ignored if "
"Impeller is not supported on the platform.")
DEF_SWITCH(ImpellerBackend,
"impeller-backend",
"Requests a particular Impeller backend on platforms that support "
"multiple backends. (ex `opengles` or `vulkan`)")
DEF_SWITCH(EnableVulkanValidation,
"enable-vulkan-validation",
"Enable loading Vulkan validation layers. The layers must be "
"available to the application and loadable. On non-Vulkan backends, "
"this flag does nothing.")
DEF_SWITCH(EnableOpenGLGPUTracing,
"enable-opengl-gpu-tracing",
"Enable tracing of GPU execution time when using the Impeller "
"OpenGLES backend.")
DEF_SWITCH(EnableVulkanGPUTracing,
"enable-vulkan-gpu-tracing",
"Enable tracing of GPU execution time when using the Impeller "
"Vulkan backend.")
DEF_SWITCH(LeakVM,
"leak-vm",
"When the last shell shuts down, the shared VM is leaked by default "
"(the leak_vm in VM settings is true). To clean up the leak VM, set "
"this value to false.")
DEF_SWITCH(EnableEmbedderAPI,
"enable-embedder-api",
"Enable the embedder api. Defaults to false. iOS only.")
DEF_SWITCH(EnablePlatformIsolates,
"enable-platform-isolates",
"Enable support for isolates that run on the platform thread.")
DEF_SWITCH(MergedPlatformUIThread,
"merged-platform-ui-thread",
"Sets whether the ui thread and platform thread should be merged.")
// This is a legacy flag that has been superseded by merged-platform-ui-thread.
// TODO(163064): remove this when users have been migrated.
DEF_SWITCH(DisableMergedPlatformUIThread,
"no-enable-merged-platform-ui-thread",
"Merge the ui thread and platform thread.")
DEF_SWITCH(EnableAndroidSurfaceControl,
"enable-surface-control",
"Enable the SurfaceControl backed swapchain when supported.")
DEF_SWITCH(EnableFlutterGPU,
"enable-flutter-gpu",
"Whether Flutter GPU is enabled.")
DEF_SWITCH(ImpellerLazyShaderMode,
"impeller-lazy-shader-mode",
"Whether to defer initialization of all required PSOs for the "
"Impeller backend. Defaults to false.")
DEF_SWITCH(ImpellerAntialiasLines,
"impeller-antialias-lines",
"Experimental flag to test drawing lines with antialiasing.")
DEF_SWITCHES_END
Feature flags could hypothetically be passed through to the engine like this too, but it would need to be setup manually for each flag.
The reason you would want to put a setting in the Info.plist rather than as a flag is if you wanted it to persist for the project (get checked into git). Hypothetically with feature flags being able to get added to the pubspec now, that could be another way to do it. Again, feature flags would still need to be passed through to the engine.
The reason you would want to put a setting in the Info.plist rather than as a flag is if you wanted it to persist for the project (get checked into git). Hypothetically with feature flags being able to get added to the pubspec now, that could be another way to do it.
One caveat: this "tool to embedder" approach only works at development time, not at deployment time. For example, the embedder would get the correct value if I do flutter run -d macos, but not if if I flutter build macos and then launch the built app. That's why Impeller and thread merging both went with the platform-specific config option for their opt-outs.
This same concern doesn't apply to the framework's feature flags as the tool uses Dart defines to stamp the feature flags into your Dart application. (The embedder and engine can't use this trick as reading these Dart defines requires launching the Dart isolate).
There is currently no way to configure the iOS engine using feature flags
@matanlurey By "feature flag" I simply mean a flag to enable or disable things (for example, the 2 code links in my original post). With this info, is the question still confusing?
flowchart TD
A[Does the embedder need the flag at startup?] -- Yes --> flutterflagsifdevtime
A -- No --> B
B[Does the engine need the flag at startup?] -- Yes --> flutterflagsifdevtime
B -- No --> flutterflags
flutterflagsifdevtime[Is the flag only for development time?] -- Yes --> flutterflags
flutterflagsifdevtime -- No --> platformconfig
flutterflags["Use Flutter's feature flags (flutter config --enable-foo)"]
platformconfig["Use platform-specific config (Info.plist or AndroidManifest.xml)"]
Activity
[-]guideline on iOS engine feature flags: Info.plist vs cmd flag[/-][+][ios] guideline on iOS engine feature flags: Info.plist vs cmd flag[/+]jmagman commentedon Jul 17, 2025
Now that experimental flags can be set per-project #167667, is there a plan to add guidance for this question, @matanlurey and @loic-sharma?
matanlurey commentedon Jul 17, 2025
I don't understand the question.
There is currently no way to configure the iOS engine using feature flags (and support is not immediately planned), or configure any embedder. For example,
--enable-impelleris not a feature flag (not aFeatureFlag), and there is no path (today) to converting it to one.If you're asking a more general question of "should someone configure a flag, that is possible to use
flutter configfor, usingflutter config --enable-xorflutter: config: enable-x: true, I'd recommend thepubspec.yamlroute, but we're keeping both around.loic-sharma commentedon Jul 17, 2025
Here's the guidance on feature flags: https://github.com/flutter/flutter/blob/master/docs/contributing/Feature-flags.md
When possible, you should not use
Info.plistflags. Instead, you should prefer Flutter's cross-platform feature flags.The cross-platform flags are more convenient for app developers as they are already familiar with the
fluttertool and the.pubspecfile. On the other hand, app developers are less familiar with platform-specific configuration files likeInfo.plist.However, Flutter's cross-platform feature flags can only be used in the Flutter tool and Flutter framework. If the embedder or engine needs to know the value of a feature flag before the Dart isolate is launched, you should continue to use platform-specific configuration files like
Info.plist.I'll update our feature flags guidance to explain this!
vashworth commentedon Jul 17, 2025
So the Flutter tool has multiple flags that it passes from the command line to the engine:
flutter/packages/flutter_tools/lib/src/device.dart
Lines 1192 to 1244 in b2d4210
flutter/engine/src/flutter/shell/common/switches.h
Lines 28 to 297 in b2d4210
Feature flags could hypothetically be passed through to the engine like this too, but it would need to be setup manually for each flag.
The reason you would want to put a setting in the Info.plist rather than as a flag is if you wanted it to persist for the project (get checked into git). Hypothetically with feature flags being able to get added to the pubspec now, that could be another way to do it. Again, feature flags would still need to be passed through to the engine.
loic-sharma commentedon Jul 17, 2025
One caveat: this "tool to embedder" approach only works at development time, not at deployment time. For example, the embedder would get the correct value if I do
flutter run -d macos, but not if if Iflutter build macosand then launch the built app. That's why Impeller and thread merging both went with the platform-specific config option for their opt-outs.This same concern doesn't apply to the framework's feature flags as the tool uses Dart defines to stamp the feature flags into your Dart application. (The embedder and engine can't use this trick as reading these Dart defines requires launching the Dart isolate).
hellohuanlin commentedon Jul 18, 2025
@matanlurey By "feature flag" I simply mean a flag to enable or disable things (for example, the 2 code links in my original post). With this info, is the question still confusing?
Recommend using Flutter feature flags over platform-specific configs (#…
loic-sharma commentedon Jul 19, 2025
Decision flowchart summarizing this conversation:
flowchart TD A[Does the embedder need the flag at startup?] -- Yes --> flutterflagsifdevtime A -- No --> B B[Does the engine need the flag at startup?] -- Yes --> flutterflagsifdevtime B -- No --> flutterflags flutterflagsifdevtime[Is the flag only for development time?] -- Yes --> flutterflags flutterflagsifdevtime -- No --> platformconfig flutterflags["Use Flutter's feature flags (flutter config --enable-foo)"] platformconfig["Use platform-specific config (Info.plist or AndroidManifest.xml)"]hellohuanlin commentedon Jul 22, 2025
Nice chart! Where do you put
systraceflag in this graph?Recommend using Flutter feature flags over platform-specific configs (f…
Recommend using Flutter feature flags over platform-specific configs (f…
Recommend using Flutter feature flags over platform-specific configs (f…
Recommend using Flutter feature flags over platform-specific configs (f…
Recommend using Flutter feature flags over platform-specific configs …