Skip to content

Commit 1e4d9f8

Browse files
[flutter_tools] add --write-sksl-on-exit to flutter drive (flutter#58743)
Allow dumping sksl files on driver exit when a file path is provided to drive's --write-sksl-on-exit
1 parent 70f2d75 commit 1e4d9f8

File tree

4 files changed

+94
-38
lines changed

4 files changed

+94
-38
lines changed

packages/flutter_tools/lib/src/commands/drive.dart

+20-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import 'dart:async';
66
import 'dart:math' as math;
77

8+
import 'package:vm_service/vm_service_io.dart' as vm_service;
9+
import 'package:vm_service/vm_service.dart' as vm_service;
810
import 'package:meta/meta.dart';
911
import 'package:webdriver/async_io.dart' as async_io;
1012

@@ -21,6 +23,7 @@ import '../globals.dart' as globals;
2123
import '../project.dart';
2224
import '../resident_runner.dart';
2325
import '../runner/flutter_command.dart' show FlutterCommandResult;
26+
import '../vmservice.dart';
2427
import '../web/web_runner.dart';
2528
import 'run.dart';
2629

@@ -111,7 +114,12 @@ class DriveCommand extends RunCommandBase {
111114
'Works only if \'browser-name\' is set to \'android-chrome\'')
112115
..addOption('chrome-binary',
113116
help: 'Location of Chrome binary. '
114-
'Works only if \'browser-name\' is set to \'chrome\'');
117+
'Works only if \'browser-name\' is set to \'chrome\'')
118+
..addOption('write-sksl-on-exit',
119+
help:
120+
'Attempts to write an SkSL file when the drive process is finished '
121+
'to the provided file, overwriting it if necessary.',
122+
);
115123
}
116124

117125
@override
@@ -303,6 +311,17 @@ $ex
303311
} finally {
304312
await residentRunner?.exit();
305313
await driver?.quit();
314+
if (stringArg('write-sksl-on-exit') != null) {
315+
final File outputFile = globals.fs.file(stringArg('write-sksl-on-exit'));
316+
final vm_service.VmService vmService = await connectToVmService(
317+
Uri.parse(observatoryUri),
318+
);
319+
final FlutterView flutterView = (await vmService.getFlutterViews()).first;
320+
final Map<String, Object> result = await vmService.getSkSLs(
321+
viewId: flutterView.id
322+
);
323+
await sharedSkSlWriter(_device, result, outputFile: outputFile);
324+
}
306325
if (boolArg('keep-app-running') ?? (argResults['use-existing-app'] != null)) {
307326
globals.printStatus('Leaving the application running.');
308327
} else {

packages/flutter_tools/lib/src/resident_runner.dart

+1-37
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import 'bundle.dart';
2727
import 'cache.dart';
2828
import 'codegen.dart';
2929
import 'compile.dart';
30-
import 'convert.dart';
3130
import 'dart/package_map.dart';
3231
import 'devfs.dart';
3332
import 'device.dart';
@@ -850,43 +849,8 @@ abstract class ResidentRunner {
850849
final Map<String, Object> data = await flutterDevices.first.vmService.getSkSLs(
851850
viewId: views.first.id,
852851
);
853-
if (data.isEmpty) {
854-
globals.logger.printStatus(
855-
'No data was receieved. To ensure SkSL data can be generated use a '
856-
'physical device then:\n'
857-
' 1. Pass "--cache-sksl" as an argument to flutter run.\n'
858-
' 2. Interact with the application to force shaders to be compiled.\n'
859-
);
860-
return null;
861-
}
862-
final File outputFile = globals.fsUtils.getUniqueFile(
863-
globals.fs.currentDirectory,
864-
'flutter',
865-
'sksl.json',
866-
);
867852
final Device device = flutterDevices.first.device;
868-
869-
// Convert android sub-platforms to single target platform.
870-
TargetPlatform targetPlatform = await flutterDevices.first.device.targetPlatform;
871-
switch (targetPlatform) {
872-
case TargetPlatform.android_arm:
873-
case TargetPlatform.android_arm64:
874-
case TargetPlatform.android_x64:
875-
case TargetPlatform.android_x86:
876-
targetPlatform = TargetPlatform.android;
877-
break;
878-
default:
879-
break;
880-
}
881-
final Map<String, Object> manifest = <String, Object>{
882-
'platform': getNameForTargetPlatform(targetPlatform),
883-
'name': device.name,
884-
'engineRevision': globals.flutterVersion.engineRevision,
885-
'data': data,
886-
};
887-
outputFile.writeAsStringSync(json.encode(manifest));
888-
globals.logger.printStatus('Wrote SkSL data to ${outputFile.path}.');
889-
return outputFile.path;
853+
return sharedSkSlWriter(device, data);
890854
}
891855

892856
/// The resident runner API for interaction with the reloadMethod vmservice

packages/flutter_tools/lib/src/vmservice.dart

+49
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44

55
import 'dart:async';
66

7+
import 'package:file/file.dart';
78
import 'package:meta/meta.dart' show required, visibleForTesting;
89
import 'package:vm_service/vm_service.dart' as vm_service;
910

1011
import 'base/context.dart';
1112
import 'base/io.dart' as io;
13+
import 'build_info.dart';
14+
import 'convert.dart';
1215
import 'device.dart';
1316
import 'globals.dart' as globals;
1417
import 'version.dart';
@@ -800,3 +803,49 @@ bool isPauseEvent(String kind) {
800803
kind == vm_service.EventKind.kPausePostRequest ||
801804
kind == vm_service.EventKind.kNone;
802805
}
806+
807+
// TODO(jonahwilliams): either refactor drive to use the resident runner
808+
// or delete it.
809+
Future<String> sharedSkSlWriter(Device device, Map<String, Object> data, {
810+
File outputFile,
811+
}) async {
812+
if (data.isEmpty) {
813+
globals.logger.printStatus(
814+
'No data was receieved. To ensure SkSL data can be generated use a '
815+
'physical device then:\n'
816+
' 1. Pass "--cache-sksl" as an argument to flutter run.\n'
817+
' 2. Interact with the application to force shaders to be compiled.\n'
818+
);
819+
return null;
820+
}
821+
if (outputFile == null) {
822+
outputFile = globals.fsUtils.getUniqueFile(
823+
globals.fs.currentDirectory,
824+
'flutter',
825+
'sksl.json',
826+
);
827+
} else if (!outputFile.parent.existsSync()) {
828+
outputFile.parent.createSync(recursive: true);
829+
}
830+
// Convert android sub-platforms to single target platform.
831+
TargetPlatform targetPlatform = await device.targetPlatform;
832+
switch (targetPlatform) {
833+
case TargetPlatform.android_arm:
834+
case TargetPlatform.android_arm64:
835+
case TargetPlatform.android_x64:
836+
case TargetPlatform.android_x86:
837+
targetPlatform = TargetPlatform.android;
838+
break;
839+
default:
840+
break;
841+
}
842+
final Map<String, Object> manifest = <String, Object>{
843+
'platform': getNameForTargetPlatform(targetPlatform),
844+
'name': device.name,
845+
'engineRevision': globals.flutterVersion.engineRevision,
846+
'data': data,
847+
};
848+
outputFile.writeAsStringSync(json.encode(manifest));
849+
globals.logger.printStatus('Wrote SkSL data to ${outputFile.path}.');
850+
return outputFile.path;
851+
}

packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart

+24
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'dart:async';
66

77
import 'package:file/memory.dart';
8+
import 'package:file_testing/file_testing.dart';
89
import 'package:flutter_tools/src/android/android_device.dart';
910
import 'package:flutter_tools/src/base/common.dart';
1011
import 'package:flutter_tools/src/base/file_system.dart';
@@ -17,6 +18,7 @@ import 'package:flutter_tools/src/device.dart';
1718
import 'package:flutter_tools/src/globals.dart' as globals;
1819
import 'package:mockito/mockito.dart';
1920
import 'package:webdriver/sync_io.dart' as sync_io;
21+
import 'package:flutter_tools/src/vmservice.dart';
2022

2123
import '../../src/common.dart';
2224
import '../../src/context.dart';
@@ -729,6 +731,28 @@ void main() {
729731
expect(getDesiredCapabilities(Browser.androidChrome, false), expected);
730732
});
731733
});
734+
735+
testUsingContext('Can write SkSL file with provided output file', () async {
736+
final MockDevice device = MockDevice();
737+
when(device.name).thenReturn('foo');
738+
when(device.targetPlatform).thenAnswer((Invocation invocation) async {
739+
return TargetPlatform.android_arm;
740+
});
741+
final File outputFile = globals.fs.file('out/foo');
742+
743+
final String result = await sharedSkSlWriter(
744+
device,
745+
<String, Object>{'foo': 'bar'},
746+
outputFile: outputFile,
747+
);
748+
749+
expect(result, 'out/foo');
750+
expect(outputFile, exists);
751+
expect(outputFile.readAsStringSync(), '{"platform":"android","name":"foo","engineRevision":null,"data":{"foo":"bar"}}');
752+
}, overrides: <Type, Generator>{
753+
FileSystem: () => MemoryFileSystem.test(),
754+
ProcessManager: () => FakeProcessManager.any(),
755+
});
732756
}
733757

734758
class MockDevice extends Mock implements Device {

0 commit comments

Comments
 (0)