Unverified Commit 1e4d9f85 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] add --write-sksl-on-exit to flutter drive (#58743)

Allow dumping sksl files on driver exit when a file path is provided to drive's --write-sksl-on-exit
parent 70f2d757
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
import 'dart:async'; import 'dart:async';
import 'dart:math' as math; import 'dart:math' as math;
import 'package:vm_service/vm_service_io.dart' as vm_service;
import 'package:vm_service/vm_service.dart' as vm_service;
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:webdriver/async_io.dart' as async_io; import 'package:webdriver/async_io.dart' as async_io;
...@@ -21,6 +23,7 @@ import '../globals.dart' as globals; ...@@ -21,6 +23,7 @@ import '../globals.dart' as globals;
import '../project.dart'; import '../project.dart';
import '../resident_runner.dart'; import '../resident_runner.dart';
import '../runner/flutter_command.dart' show FlutterCommandResult; import '../runner/flutter_command.dart' show FlutterCommandResult;
import '../vmservice.dart';
import '../web/web_runner.dart'; import '../web/web_runner.dart';
import 'run.dart'; import 'run.dart';
...@@ -111,7 +114,12 @@ class DriveCommand extends RunCommandBase { ...@@ -111,7 +114,12 @@ class DriveCommand extends RunCommandBase {
'Works only if \'browser-name\' is set to \'android-chrome\'') 'Works only if \'browser-name\' is set to \'android-chrome\'')
..addOption('chrome-binary', ..addOption('chrome-binary',
help: 'Location of Chrome binary. ' help: 'Location of Chrome binary. '
'Works only if \'browser-name\' is set to \'chrome\''); 'Works only if \'browser-name\' is set to \'chrome\'')
..addOption('write-sksl-on-exit',
help:
'Attempts to write an SkSL file when the drive process is finished '
'to the provided file, overwriting it if necessary.',
);
} }
@override @override
...@@ -303,6 +311,17 @@ $ex ...@@ -303,6 +311,17 @@ $ex
} finally { } finally {
await residentRunner?.exit(); await residentRunner?.exit();
await driver?.quit(); await driver?.quit();
if (stringArg('write-sksl-on-exit') != null) {
final File outputFile = globals.fs.file(stringArg('write-sksl-on-exit'));
final vm_service.VmService vmService = await connectToVmService(
Uri.parse(observatoryUri),
);
final FlutterView flutterView = (await vmService.getFlutterViews()).first;
final Map<String, Object> result = await vmService.getSkSLs(
viewId: flutterView.id
);
await sharedSkSlWriter(_device, result, outputFile: outputFile);
}
if (boolArg('keep-app-running') ?? (argResults['use-existing-app'] != null)) { if (boolArg('keep-app-running') ?? (argResults['use-existing-app'] != null)) {
globals.printStatus('Leaving the application running.'); globals.printStatus('Leaving the application running.');
} else { } else {
......
...@@ -27,7 +27,6 @@ import 'bundle.dart'; ...@@ -27,7 +27,6 @@ import 'bundle.dart';
import 'cache.dart'; import 'cache.dart';
import 'codegen.dart'; import 'codegen.dart';
import 'compile.dart'; import 'compile.dart';
import 'convert.dart';
import 'dart/package_map.dart'; import 'dart/package_map.dart';
import 'devfs.dart'; import 'devfs.dart';
import 'device.dart'; import 'device.dart';
...@@ -850,43 +849,8 @@ abstract class ResidentRunner { ...@@ -850,43 +849,8 @@ abstract class ResidentRunner {
final Map<String, Object> data = await flutterDevices.first.vmService.getSkSLs( final Map<String, Object> data = await flutterDevices.first.vmService.getSkSLs(
viewId: views.first.id, viewId: views.first.id,
); );
if (data.isEmpty) {
globals.logger.printStatus(
'No data was receieved. To ensure SkSL data can be generated use a '
'physical device then:\n'
' 1. Pass "--cache-sksl" as an argument to flutter run.\n'
' 2. Interact with the application to force shaders to be compiled.\n'
);
return null;
}
final File outputFile = globals.fsUtils.getUniqueFile(
globals.fs.currentDirectory,
'flutter',
'sksl.json',
);
final Device device = flutterDevices.first.device; final Device device = flutterDevices.first.device;
return sharedSkSlWriter(device, data);
// Convert android sub-platforms to single target platform.
TargetPlatform targetPlatform = await flutterDevices.first.device.targetPlatform;
switch (targetPlatform) {
case TargetPlatform.android_arm:
case TargetPlatform.android_arm64:
case TargetPlatform.android_x64:
case TargetPlatform.android_x86:
targetPlatform = TargetPlatform.android;
break;
default:
break;
}
final Map<String, Object> manifest = <String, Object>{
'platform': getNameForTargetPlatform(targetPlatform),
'name': device.name,
'engineRevision': globals.flutterVersion.engineRevision,
'data': data,
};
outputFile.writeAsStringSync(json.encode(manifest));
globals.logger.printStatus('Wrote SkSL data to ${outputFile.path}.');
return outputFile.path;
} }
/// The resident runner API for interaction with the reloadMethod vmservice /// The resident runner API for interaction with the reloadMethod vmservice
......
...@@ -4,11 +4,14 @@ ...@@ -4,11 +4,14 @@
import 'dart:async'; import 'dart:async';
import 'package:file/file.dart';
import 'package:meta/meta.dart' show required, visibleForTesting; import 'package:meta/meta.dart' show required, visibleForTesting;
import 'package:vm_service/vm_service.dart' as vm_service; import 'package:vm_service/vm_service.dart' as vm_service;
import 'base/context.dart'; import 'base/context.dart';
import 'base/io.dart' as io; import 'base/io.dart' as io;
import 'build_info.dart';
import 'convert.dart';
import 'device.dart'; import 'device.dart';
import 'globals.dart' as globals; import 'globals.dart' as globals;
import 'version.dart'; import 'version.dart';
...@@ -800,3 +803,49 @@ bool isPauseEvent(String kind) { ...@@ -800,3 +803,49 @@ bool isPauseEvent(String kind) {
kind == vm_service.EventKind.kPausePostRequest || kind == vm_service.EventKind.kPausePostRequest ||
kind == vm_service.EventKind.kNone; kind == vm_service.EventKind.kNone;
} }
// TODO(jonahwilliams): either refactor drive to use the resident runner
// or delete it.
Future<String> sharedSkSlWriter(Device device, Map<String, Object> data, {
File outputFile,
}) async {
if (data.isEmpty) {
globals.logger.printStatus(
'No data was receieved. To ensure SkSL data can be generated use a '
'physical device then:\n'
' 1. Pass "--cache-sksl" as an argument to flutter run.\n'
' 2. Interact with the application to force shaders to be compiled.\n'
);
return null;
}
if (outputFile == null) {
outputFile = globals.fsUtils.getUniqueFile(
globals.fs.currentDirectory,
'flutter',
'sksl.json',
);
} else if (!outputFile.parent.existsSync()) {
outputFile.parent.createSync(recursive: true);
}
// Convert android sub-platforms to single target platform.
TargetPlatform targetPlatform = await device.targetPlatform;
switch (targetPlatform) {
case TargetPlatform.android_arm:
case TargetPlatform.android_arm64:
case TargetPlatform.android_x64:
case TargetPlatform.android_x86:
targetPlatform = TargetPlatform.android;
break;
default:
break;
}
final Map<String, Object> manifest = <String, Object>{
'platform': getNameForTargetPlatform(targetPlatform),
'name': device.name,
'engineRevision': globals.flutterVersion.engineRevision,
'data': data,
};
outputFile.writeAsStringSync(json.encode(manifest));
globals.logger.printStatus('Wrote SkSL data to ${outputFile.path}.');
return outputFile.path;
}
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'dart:async'; import 'dart:async';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/android/android_device.dart'; import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
...@@ -17,6 +18,7 @@ import 'package:flutter_tools/src/device.dart'; ...@@ -17,6 +18,7 @@ import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/globals.dart' as globals; import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:webdriver/sync_io.dart' as sync_io; import 'package:webdriver/sync_io.dart' as sync_io;
import 'package:flutter_tools/src/vmservice.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/context.dart'; import '../../src/context.dart';
...@@ -729,6 +731,28 @@ void main() { ...@@ -729,6 +731,28 @@ void main() {
expect(getDesiredCapabilities(Browser.androidChrome, false), expected); expect(getDesiredCapabilities(Browser.androidChrome, false), expected);
}); });
}); });
testUsingContext('Can write SkSL file with provided output file', () async {
final MockDevice device = MockDevice();
when(device.name).thenReturn('foo');
when(device.targetPlatform).thenAnswer((Invocation invocation) async {
return TargetPlatform.android_arm;
});
final File outputFile = globals.fs.file('out/foo');
final String result = await sharedSkSlWriter(
device,
<String, Object>{'foo': 'bar'},
outputFile: outputFile,
);
expect(result, 'out/foo');
expect(outputFile, exists);
expect(outputFile.readAsStringSync(), '{"platform":"android","name":"foo","engineRevision":null,"data":{"foo":"bar"}}');
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
});
} }
class MockDevice extends Mock implements Device { class MockDevice extends Mock implements Device {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment