[ DDS ] Create an arg parser for the DDS snapshot

Preparation for shipping DDS as part of the SDK instead of as a Pub
package.

TEST=Existing VM service, DDS, and dartdev tests

Change-Id: I38ec47f4ebf003d3d3c813af40a313403f23280c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/356580
Reviewed-by: Derek Xu <derekx@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
This commit is contained in:
Ben Konyi 2024-03-11 19:54:47 +00:00 committed by Commit Queue
parent e253c2d1b5
commit d58f6a1ce3
4 changed files with 109 additions and 82 deletions

View file

@ -4,7 +4,6 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:path/path.dart';
@ -14,32 +13,6 @@ import 'sdk.dart';
class DDSRunner {
Uri? ddsUri;
Future<bool> startForCurrentProcess({
required String ddsHost,
required String ddsPort,
required bool disableServiceAuthCodes,
required bool enableDevTools,
required bool debugDds,
required bool enableServicePortFallback,
}) async {
ServiceProtocolInfo serviceInfo = await Service.getInfo();
// Wait for VM service to publish its connection info.
while (serviceInfo.serverUri == null) {
await Future.delayed(Duration(milliseconds: 10));
serviceInfo = await Service.getInfo();
}
return await start(
vmServiceUri: serviceInfo.serverUri!,
ddsHost: ddsHost,
ddsPort: ddsPort,
disableServiceAuthCodes: disableServiceAuthCodes,
enableDevTools: enableDevTools,
debugDds: debugDds,
enableServicePortFallback: enableServicePortFallback,
);
}
Future<bool> start({
required Uri vmServiceUri,
required String ddsHost,
@ -51,8 +24,6 @@ class DDSRunner {
}) async {
final sdkDir = dirname(sdk.dart);
final fullSdk = sdkDir.endsWith('bin');
final devToolsBinaries =
fullSdk ? sdk.devToolsBinaries : absolute(sdkDir, 'devtools');
String snapshotName = fullSdk
? sdk.ddsAotSnapshot
: absolute(sdkDir, 'dds_aot.dart.snapshot');
@ -79,14 +50,13 @@ class DDSRunner {
[
if (debugDds) '--enable-vm-service=0',
snapshotName,
vmServiceUri.toString(),
ddsHost,
ddsPort,
disableServiceAuthCodes.toString(),
enableDevTools.toString(),
devToolsBinaries,
debugDds.toString(),
enableServicePortFallback.toString(),
'--vm-service-uri=$vmServiceUri',
'--bind-address=$ddsHost',
'--bind-port=$ddsPort',
if (disableServiceAuthCodes) '--disable-service-auth-codes',
if (enableDevTools) '--serve-devtools',
if (debugDds) '--enable-logging',
if (enableServicePortFallback) '--enable-service-port-fallback',
],
mode: ProcessStartMode.detachedWithStdio,
);

View file

@ -5,45 +5,112 @@
import 'dart:convert';
import 'dart:io';
import 'package:args/args.dart';
import 'package:dds/dds.dart';
/// A simple program which starts a [DartDevelopmentService] instance with a
/// basic configuration.
///
/// Takes the following positional arguments:
/// - VM service URI
/// - DDS bind address
/// - DDS port
/// - Disable service authentication codes
/// - Start DevTools
/// - DevTools build directory
/// - Enable logging
/// - Enable service port fallback
abstract class DartDevelopmentServiceOptions {
static const vmServiceUriOption = 'vm-service-uri';
static const bindAddressOption = 'bind-address';
static const bindPortOption = 'bind-port';
static const disableServiceAuthCodesFlag = 'disable-service-auth-codes';
static const serveDevToolsFlag = 'serve-devtools';
static const enableServicePortFallbackFlag = 'enable-service-port-fallback';
static ArgParser createArgParser() {
return ArgParser()
..addOption(
vmServiceUriOption,
help: 'The VM service URI DDS will connect to.',
valueHelp: 'uri',
mandatory: true,
)
..addOption(bindAddressOption,
help: 'The address DDS should bind to.',
valueHelp: 'address',
defaultsTo: 'localhost')
..addOption(
bindPortOption,
help: 'The port DDS should be served on.',
valueHelp: 'port',
defaultsTo: '0',
)
..addFlag(
disableServiceAuthCodesFlag,
help: 'Disables authentication codes.',
)
..addFlag(
serveDevToolsFlag,
help: 'If provided, DDS will serve DevTools.',
)
..addFlag(
enableServicePortFallbackFlag,
help: 'Bind to a random port if DDS fails to bind to the provided '
'port.',
)
..addFlag('help', negatable: false);
}
}
Uri _getDevToolsAssetPath() {
final dartPath = Uri.parse(Platform.resolvedExecutable);
final dartDir = [
'', // Include leading '/'
...dartPath.pathSegments.sublist(
0,
dartPath.pathSegments.length - 1,
),
].join('/');
final fullSdk = dartDir.endsWith('bin');
return Uri.parse(
[
dartDir,
if (fullSdk) 'resources',
'devtools',
].join('/'),
);
}
Future<void> main(List<String> args) async {
if (args.isEmpty) return;
final argParser = DartDevelopmentServiceOptions.createArgParser();
final argResults = argParser.parse(args);
if (args.isEmpty || argResults.wasParsed('help')) {
print('''
Starts a Dart Development Service (DDS) instance.
Usage:
${argParser.usage}
''');
return;
}
// This URI is provided by the VM service directly so don't bother doing a
// lookup.
final remoteVmServiceUri = Uri.parse(args.first);
final remoteVmServiceUri = Uri.parse(
argResults[DartDevelopmentServiceOptions.vmServiceUriOption],
);
// Resolve the address which is potentially provided by the user.
late InternetAddress address;
final bindAddress =
argResults[DartDevelopmentServiceOptions.bindAddressOption];
try {
final addresses = await InternetAddress.lookup(args[1]);
final addresses = await InternetAddress.lookup(bindAddress);
// Prefer IPv4 addresses.
for (int i = 0; i < addresses.length; i++) {
address = addresses[i];
if (address.type == InternetAddressType.IPv4) break;
}
} on SocketException catch (e, st) {
writeErrorResponse('Invalid bind address: ${args[1]}', st);
writeErrorResponse('Invalid bind address: $bindAddress', st);
return;
}
final portString = argResults[DartDevelopmentServiceOptions.bindPortOption];
int port;
try {
port = int.parse(args[2]);
port = int.parse(portString);
} on FormatException catch (e, st) {
writeErrorResponse('Invalid port: ${args[2]}', st);
writeErrorResponse('Invalid port: $portString', st);
return;
}
final serviceUri = Uri(
@ -51,31 +118,30 @@ Future<void> main(List<String> args) async {
host: address.address,
port: port,
);
final disableServiceAuthCodes = args[3] == 'true';
final disableServiceAuthCodes =
argResults[DartDevelopmentServiceOptions.disableServiceAuthCodesFlag];
final startDevTools = args[4] == 'true';
final serveDevTools =
argResults[DartDevelopmentServiceOptions.serveDevToolsFlag];
Uri? devToolsBuildDirectory;
if (args[5].isNotEmpty) {
devToolsBuildDirectory = Uri.file(args[5]);
if (serveDevTools) {
devToolsBuildDirectory = _getDevToolsAssetPath();
}
final logRequests = args[6] == 'true';
final enableServicePortFallback = args[7] == 'true';
final enableServicePortFallback =
argResults[DartDevelopmentServiceOptions.enableServicePortFallbackFlag];
try {
// TODO(bkonyi): add retry logic similar to that in vmservice_server.dart
// See https://github.com/dart-lang/sdk/issues/43192.
final dds = await DartDevelopmentService.startDartDevelopmentService(
remoteVmServiceUri,
serviceUri: serviceUri,
enableAuthCodes: !disableServiceAuthCodes,
ipv6: address.type == InternetAddressType.IPv6,
devToolsConfiguration: startDevTools && devToolsBuildDirectory != null
devToolsConfiguration: serveDevTools && devToolsBuildDirectory != null
? DevToolsConfiguration(
enable: startDevTools,
enable: serveDevTools,
customBuildDirectoryPath: devToolsBuildDirectory,
)
: null,
logRequests: logRequests,
enableServicePortFallback: enableServicePortFallback,
);
stderr.write(json.encode({

View file

@ -125,25 +125,16 @@ class _DebuggingSession {
execName = dartPath.toString();
}
final devToolsBinaries = [
dartDir,
if (fullSdk) 'resources',
'devtools',
].join('/');
const enableLogging = false;
_process = await Process.start(
execName,
[
snapshotName,
server!.serverAddress!.toString(),
host,
port,
disableServiceAuthCodes.toString(),
enableDevTools.toString(),
devToolsBinaries,
enableLogging.toString(),
_enableServicePortFallback.toString(),
'--vm-service-uri=${server!.serverAddress!}',
'--bind-address=$host',
'--bind-port=$port',
if (disableServiceAuthCodes) '--disable-service-auth-codes',
if (enableDevTools) '--serve-devtools',
if (_enableServicePortFallback) '--enable-service-port-fallback',
],
mode: ProcessStartMode.detachedWithStdio,
);

View file

@ -29,7 +29,7 @@ copy("copy_dds_aot_snapshot") {
application_snapshot("generate_dds_snapshot") {
main_dart = "../../pkg/dds/bin/dds.dart"
training_args = []
training_args = [ "--help" ]
output = "$root_gen_dir/dds.dart.snapshot"
}