[flutter_tools] support all engine debugging options with FLUTTER_ENGINE_SWITCH environment variables (#67150)
Allow providing all debugging options to the desktop engine via the FLUTTER_ENGINE_SWITCH_ environment variables. Fixes #66532 Fixes #46005 Fixes #58882 The underling engine changes have already landed for Windows, macOS, but linux is still in progress
This commit is contained in:
parent
4ce2a7aa6d
commit
21bb29cc68
@ -111,8 +111,8 @@ abstract class DesktopDevice extends Device {
|
|||||||
ApplicationPackage package, {
|
ApplicationPackage package, {
|
||||||
String mainPath,
|
String mainPath,
|
||||||
String route,
|
String route,
|
||||||
DebuggingOptions debuggingOptions,
|
@required DebuggingOptions debuggingOptions,
|
||||||
Map<String, dynamic> platformArgs,
|
Map<String, dynamic> platformArgs = const <String, dynamic>{},
|
||||||
bool prebuiltApplication = false,
|
bool prebuiltApplication = false,
|
||||||
bool ipv6 = false,
|
bool ipv6 = false,
|
||||||
String userIdentifier,
|
String userIdentifier,
|
||||||
@ -120,13 +120,14 @@ abstract class DesktopDevice extends Device {
|
|||||||
if (!prebuiltApplication) {
|
if (!prebuiltApplication) {
|
||||||
await buildForDevice(
|
await buildForDevice(
|
||||||
package,
|
package,
|
||||||
buildInfo: debuggingOptions?.buildInfo,
|
buildInfo: debuggingOptions.buildInfo,
|
||||||
mainPath: mainPath,
|
mainPath: mainPath,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the executable is locatable.
|
// Ensure that the executable is locatable.
|
||||||
final BuildMode buildMode = debuggingOptions?.buildInfo?.mode;
|
final BuildMode buildMode = debuggingOptions?.buildInfo?.mode;
|
||||||
|
final bool traceStartup = platformArgs['trace-startup'] as bool ?? false;
|
||||||
final String executable = executablePathForDevice(package, buildMode);
|
final String executable = executablePathForDevice(package, buildMode);
|
||||||
if (executable == null) {
|
if (executable == null) {
|
||||||
_logger.printError('Unable to find executable to run');
|
_logger.printError('Unable to find executable to run');
|
||||||
@ -137,6 +138,7 @@ abstract class DesktopDevice extends Device {
|
|||||||
<String>[
|
<String>[
|
||||||
executable,
|
executable,
|
||||||
],
|
],
|
||||||
|
environment: _computeEnvironment(debuggingOptions, traceStartup, route),
|
||||||
);
|
);
|
||||||
_runningProcesses.add(process);
|
_runningProcesses.add(process);
|
||||||
unawaited(process.exitCode.then((_) => _runningProcesses.remove(process)));
|
unawaited(process.exitCode.then((_) => _runningProcesses.remove(process)));
|
||||||
@ -202,6 +204,92 @@ abstract class DesktopDevice extends Device {
|
|||||||
/// Called after a process is attached, allowing any device-specific extra
|
/// Called after a process is attached, allowing any device-specific extra
|
||||||
/// steps to be run.
|
/// steps to be run.
|
||||||
void onAttached(ApplicationPackage package, BuildMode buildMode, Process process) {}
|
void onAttached(ApplicationPackage package, BuildMode buildMode, Process process) {}
|
||||||
|
|
||||||
|
/// Computes a set of environment variables used to pass debugging information
|
||||||
|
/// to the engine without interfering with application level command line
|
||||||
|
/// arguments.
|
||||||
|
///
|
||||||
|
/// The format of the environment variables is:
|
||||||
|
/// * FLUTTER_ENGINE_SWITCHES to the number of switches.
|
||||||
|
/// * FLUTTER_ENGINE_SWITCH_<N> (indexing from 1) to the individual switches.
|
||||||
|
Map<String, String> _computeEnvironment(DebuggingOptions debuggingOptions, bool traceStartup, String route) {
|
||||||
|
int flags = 0;
|
||||||
|
final Map<String, String> environment = <String, String>{};
|
||||||
|
|
||||||
|
void addFlag(String value) {
|
||||||
|
flags += 1;
|
||||||
|
environment['FLUTTER_ENGINE_SWITCH_$flags'] = value;
|
||||||
|
}
|
||||||
|
void finish() {
|
||||||
|
environment['FLUTTER_ENGINE_SWITCHES'] = flags.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
addFlag('enable-dart-profiling=true');
|
||||||
|
addFlag('enable-background-compilation=true');
|
||||||
|
|
||||||
|
if (traceStartup) {
|
||||||
|
addFlag('trace-startup=true');
|
||||||
|
}
|
||||||
|
if (route != null) {
|
||||||
|
addFlag('route=$route');
|
||||||
|
}
|
||||||
|
if (debuggingOptions.enableSoftwareRendering) {
|
||||||
|
addFlag('enable-software-rendering=true');
|
||||||
|
}
|
||||||
|
if (debuggingOptions.skiaDeterministicRendering) {
|
||||||
|
addFlag('skia-deterministic-rendering=true');
|
||||||
|
}
|
||||||
|
if (debuggingOptions.traceSkia) {
|
||||||
|
addFlag('trace-skia=true');
|
||||||
|
}
|
||||||
|
if (debuggingOptions.traceAllowlist != null) {
|
||||||
|
addFlag('trace-allowlist=${debuggingOptions.traceAllowlist}');
|
||||||
|
}
|
||||||
|
if (debuggingOptions.traceSystrace) {
|
||||||
|
addFlag('trace-systrace=true');
|
||||||
|
}
|
||||||
|
if (debuggingOptions.endlessTraceBuffer) {
|
||||||
|
addFlag('endless-trace-buffer=true');
|
||||||
|
}
|
||||||
|
if (debuggingOptions.dumpSkpOnShaderCompilation) {
|
||||||
|
addFlag('dump-skp-on-shader-compilation=true');
|
||||||
|
}
|
||||||
|
if (debuggingOptions.cacheSkSL) {
|
||||||
|
addFlag('cache-sksl=true');
|
||||||
|
}
|
||||||
|
if (debuggingOptions.purgePersistentCache) {
|
||||||
|
addFlag('purge-persistent-cache=true');
|
||||||
|
}
|
||||||
|
// Options only supported when there is a VM Service connection between the
|
||||||
|
// tool and the device, usually in debug or profile mode.
|
||||||
|
if (debuggingOptions.debuggingEnabled) {
|
||||||
|
if (debuggingOptions.deviceVmServicePort != null) {
|
||||||
|
addFlag('observatory-port=${debuggingOptions.deviceVmServicePort}');
|
||||||
|
}
|
||||||
|
if (debuggingOptions.buildInfo.isDebug) {
|
||||||
|
addFlag('enable-checked-mode=true');
|
||||||
|
addFlag('verify-entry-points=true');
|
||||||
|
}
|
||||||
|
if (debuggingOptions.startPaused) {
|
||||||
|
addFlag('start-paused=true');
|
||||||
|
}
|
||||||
|
if (debuggingOptions.disableServiceAuthCodes) {
|
||||||
|
addFlag('disable-service-auth-codes=true');
|
||||||
|
}
|
||||||
|
final String dartVmFlags = computeDartVmFlags(debuggingOptions);
|
||||||
|
if (dartVmFlags.isNotEmpty) {
|
||||||
|
addFlag('dart-flags=$dartVmFlags');
|
||||||
|
}
|
||||||
|
if (debuggingOptions.useTestFonts) {
|
||||||
|
addFlag('use-test-fonts=true');
|
||||||
|
}
|
||||||
|
if (debuggingOptions.verboseSystemLogs) {
|
||||||
|
addFlag('verbose-logging=true');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
return environment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A log reader for desktop applications that delegates to a [Process] stdout
|
/// A log reader for desktop applications that delegates to a [Process] stdout
|
||||||
|
@ -80,7 +80,7 @@ void main() {
|
|||||||
final Completer<void> completer = Completer<void>();
|
final Completer<void> completer = Completer<void>();
|
||||||
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
|
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
|
||||||
FakeCommand(
|
FakeCommand(
|
||||||
command: const <String>['null'],
|
command: const <String>['debug'],
|
||||||
stdout: 'Observatory listening on http://127.0.0.1/0\n',
|
stdout: 'Observatory listening on http://127.0.0.1/0\n',
|
||||||
completer: completer,
|
completer: completer,
|
||||||
),
|
),
|
||||||
@ -89,7 +89,11 @@ void main() {
|
|||||||
final String executableName = device.executablePathForDevice(null, BuildMode.debug);
|
final String executableName = device.executablePathForDevice(null, BuildMode.debug);
|
||||||
fileSystem.file(executableName).writeAsStringSync('\n');
|
fileSystem.file(executableName).writeAsStringSync('\n');
|
||||||
final FakeAppplicationPackage package = FakeAppplicationPackage();
|
final FakeAppplicationPackage package = FakeAppplicationPackage();
|
||||||
final LaunchResult result = await device.startApp(package, prebuiltApplication: true);
|
final LaunchResult result = await device.startApp(
|
||||||
|
package,
|
||||||
|
prebuiltApplication: true,
|
||||||
|
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
|
||||||
|
);
|
||||||
|
|
||||||
expect(result.started, true);
|
expect(result.started, true);
|
||||||
expect(result.observatoryUri, Uri.parse('http://127.0.0.1/0'));
|
expect(result.observatoryUri, Uri.parse('http://127.0.0.1/0'));
|
||||||
@ -99,7 +103,11 @@ void main() {
|
|||||||
final BufferLogger logger = BufferLogger.test();
|
final BufferLogger logger = BufferLogger.test();
|
||||||
final DesktopDevice device = setUpDesktopDevice(nullExecutablePathForDevice: true, logger: logger);
|
final DesktopDevice device = setUpDesktopDevice(nullExecutablePathForDevice: true, logger: logger);
|
||||||
final FakeAppplicationPackage package = FakeAppplicationPackage();
|
final FakeAppplicationPackage package = FakeAppplicationPackage();
|
||||||
final LaunchResult result = await device.startApp(package, prebuiltApplication: true);
|
final LaunchResult result = await device.startApp(
|
||||||
|
package,
|
||||||
|
prebuiltApplication: true,
|
||||||
|
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
|
||||||
|
);
|
||||||
|
|
||||||
expect(result.started, false);
|
expect(result.started, false);
|
||||||
expect(logger.errorText, contains('Unable to find executable to run'));
|
expect(logger.errorText, contains('Unable to find executable to run'));
|
||||||
@ -109,20 +117,123 @@ void main() {
|
|||||||
final Completer<void> completer = Completer<void>();
|
final Completer<void> completer = Completer<void>();
|
||||||
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
|
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
|
||||||
FakeCommand(
|
FakeCommand(
|
||||||
command: const <String>['null'],
|
command: const <String>['debug'],
|
||||||
stdout: 'Observatory listening on http://127.0.0.1/0\n',
|
stdout: 'Observatory listening on http://127.0.0.1/0\n',
|
||||||
completer: completer,
|
completer: completer,
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
final FakeDesktopDevice device = setUpDesktopDevice(processManager: processManager);
|
final FakeDesktopDevice device = setUpDesktopDevice(processManager: processManager);
|
||||||
final FakeAppplicationPackage package = FakeAppplicationPackage();
|
final FakeAppplicationPackage package = FakeAppplicationPackage();
|
||||||
final LaunchResult result = await device.startApp(package, prebuiltApplication: true);
|
final LaunchResult result = await device.startApp(
|
||||||
|
package,
|
||||||
|
prebuiltApplication: true,
|
||||||
|
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
|
||||||
|
);
|
||||||
|
|
||||||
expect(result.started, true);
|
expect(result.started, true);
|
||||||
expect(await device.stopApp(package), true);
|
expect(await device.stopApp(package), true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWithoutContext('startApp supports DebuggingOptions through FLUTTER_ENGINE_SWITCH environment variables', () async {
|
||||||
|
final Completer<void> completer = Completer<void>();
|
||||||
|
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
|
||||||
|
FakeCommand(
|
||||||
|
command: const <String>['debug'],
|
||||||
|
stdout: 'Observatory listening on http://127.0.0.1/0\n',
|
||||||
|
completer: completer,
|
||||||
|
environment: const <String, String>{
|
||||||
|
'FLUTTER_ENGINE_SWITCH_1': 'enable-dart-profiling=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_2': 'enable-background-compilation=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_3': 'trace-startup=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_4': 'enable-software-rendering=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_5': 'skia-deterministic-rendering=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_6': 'trace-skia=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_7': 'trace-allowlist=foo,bar',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_8': 'trace-systrace=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_9': 'endless-trace-buffer=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_10': 'dump-skp-on-shader-compilation=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_11': 'cache-sksl=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_12': 'purge-persistent-cache=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_13': 'enable-checked-mode=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_14': 'verify-entry-points=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_15': 'start-paused=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_16': 'disable-service-auth-codes=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_17': 'dart-flags=--null_assertions',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_18': 'use-test-fonts=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_19': 'verbose-logging=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCHES': '19'
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
final FakeDesktopDevice device = setUpDesktopDevice(processManager: processManager);
|
||||||
|
final FakeAppplicationPackage package = FakeAppplicationPackage();
|
||||||
|
final LaunchResult result = await device.startApp(
|
||||||
|
package,
|
||||||
|
prebuiltApplication: true,
|
||||||
|
platformArgs: <String, Object>{
|
||||||
|
'trace-startup': true,
|
||||||
|
},
|
||||||
|
debuggingOptions: DebuggingOptions.enabled(
|
||||||
|
BuildInfo.debug,
|
||||||
|
startPaused: true,
|
||||||
|
disableServiceAuthCodes: true,
|
||||||
|
dartFlags: '',
|
||||||
|
enableSoftwareRendering: true,
|
||||||
|
skiaDeterministicRendering: true,
|
||||||
|
traceSkia: true,
|
||||||
|
traceAllowlist: 'foo,bar',
|
||||||
|
traceSystrace: true,
|
||||||
|
endlessTraceBuffer: true,
|
||||||
|
dumpSkpOnShaderCompilation: true,
|
||||||
|
cacheSkSL: true,
|
||||||
|
purgePersistentCache: true,
|
||||||
|
useTestFonts: true,
|
||||||
|
verboseSystemLogs: true,
|
||||||
|
initializePlatform: true,
|
||||||
|
nullAssertions: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.started, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWithoutContext('startApp supports DebuggingOptions through FLUTTER_ENGINE_SWITCH environment variables when debugging is disabled', () async {
|
||||||
|
final Completer<void> completer = Completer<void>();
|
||||||
|
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
|
||||||
|
FakeCommand(
|
||||||
|
command: const <String>['debug'],
|
||||||
|
stdout: 'Observatory listening on http://127.0.0.1/0\n',
|
||||||
|
completer: completer,
|
||||||
|
environment: const <String, String>{
|
||||||
|
'FLUTTER_ENGINE_SWITCH_1': 'enable-dart-profiling=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_2': 'enable-background-compilation=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_3': 'trace-startup=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_4': 'trace-allowlist=foo,bar',
|
||||||
|
'FLUTTER_ENGINE_SWITCH_5': 'cache-sksl=true',
|
||||||
|
'FLUTTER_ENGINE_SWITCHES': '5'
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
final FakeDesktopDevice device = setUpDesktopDevice(processManager: processManager);
|
||||||
|
final FakeAppplicationPackage package = FakeAppplicationPackage();
|
||||||
|
final LaunchResult result = await device.startApp(
|
||||||
|
package,
|
||||||
|
prebuiltApplication: true,
|
||||||
|
platformArgs: <String, Object>{
|
||||||
|
'trace-startup': true,
|
||||||
|
},
|
||||||
|
debuggingOptions: DebuggingOptions.disabled(
|
||||||
|
BuildInfo.debug,
|
||||||
|
traceAllowlist: 'foo,bar',
|
||||||
|
cacheSkSL: true,
|
||||||
|
initializePlatform: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.started, true);
|
||||||
|
});
|
||||||
|
|
||||||
testWithoutContext('Port forwarder is a no-op', () async {
|
testWithoutContext('Port forwarder is a no-op', () async {
|
||||||
final FakeDesktopDevice device = setUpDesktopDevice();
|
final FakeDesktopDevice device = setUpDesktopDevice();
|
||||||
final DevicePortForwarder portForwarder = device.portForwarder;
|
final DevicePortForwarder portForwarder = device.portForwarder;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user