mirror of
https://github.com/flutter/flutter
synced 2024-10-12 19:23:02 +00:00
[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, {
|
||||
String mainPath,
|
||||
String route,
|
||||
DebuggingOptions debuggingOptions,
|
||||
Map<String, dynamic> platformArgs,
|
||||
@required DebuggingOptions debuggingOptions,
|
||||
Map<String, dynamic> platformArgs = const <String, dynamic>{},
|
||||
bool prebuiltApplication = false,
|
||||
bool ipv6 = false,
|
||||
String userIdentifier,
|
||||
|
@ -120,13 +120,14 @@ abstract class DesktopDevice extends Device {
|
|||
if (!prebuiltApplication) {
|
||||
await buildForDevice(
|
||||
package,
|
||||
buildInfo: debuggingOptions?.buildInfo,
|
||||
buildInfo: debuggingOptions.buildInfo,
|
||||
mainPath: mainPath,
|
||||
);
|
||||
}
|
||||
|
||||
// Ensure that the executable is locatable.
|
||||
final BuildMode buildMode = debuggingOptions?.buildInfo?.mode;
|
||||
final bool traceStartup = platformArgs['trace-startup'] as bool ?? false;
|
||||
final String executable = executablePathForDevice(package, buildMode);
|
||||
if (executable == null) {
|
||||
_logger.printError('Unable to find executable to run');
|
||||
|
@ -137,6 +138,7 @@ abstract class DesktopDevice extends Device {
|
|||
<String>[
|
||||
executable,
|
||||
],
|
||||
environment: _computeEnvironment(debuggingOptions, traceStartup, route),
|
||||
);
|
||||
_runningProcesses.add(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
|
||||
/// steps to be run.
|
||||
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
|
||||
|
|
|
@ -80,7 +80,7 @@ void main() {
|
|||
final Completer<void> completer = Completer<void>();
|
||||
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
|
||||
FakeCommand(
|
||||
command: const <String>['null'],
|
||||
command: const <String>['debug'],
|
||||
stdout: 'Observatory listening on http://127.0.0.1/0\n',
|
||||
completer: completer,
|
||||
),
|
||||
|
@ -89,7 +89,11 @@ void main() {
|
|||
final String executableName = device.executablePathForDevice(null, BuildMode.debug);
|
||||
fileSystem.file(executableName).writeAsStringSync('\n');
|
||||
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.observatoryUri, Uri.parse('http://127.0.0.1/0'));
|
||||
|
@ -99,7 +103,11 @@ void main() {
|
|||
final BufferLogger logger = BufferLogger.test();
|
||||
final DesktopDevice device = setUpDesktopDevice(nullExecutablePathForDevice: true, logger: logger);
|
||||
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(logger.errorText, contains('Unable to find executable to run'));
|
||||
|
@ -109,20 +117,123 @@ void main() {
|
|||
final Completer<void> completer = Completer<void>();
|
||||
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
|
||||
FakeCommand(
|
||||
command: const <String>['null'],
|
||||
command: const <String>['debug'],
|
||||
stdout: 'Observatory listening on http://127.0.0.1/0\n',
|
||||
completer: completer,
|
||||
),
|
||||
]);
|
||||
final FakeDesktopDevice device = setUpDesktopDevice(processManager: processManager);
|
||||
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(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 {
|
||||
final FakeDesktopDevice device = setUpDesktopDevice();
|
||||
final DevicePortForwarder portForwarder = device.portForwarder;
|
||||
|
|
Loading…
Reference in a new issue