From d58f6a1ce3c856057462933c9cd6c5fc2abaa188 Mon Sep 17 00:00:00 2001 From: Ben Konyi Date: Mon, 11 Mar 2024 19:54:47 +0000 Subject: [PATCH] [ 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 Commit-Queue: Ben Konyi --- pkg/dartdev/lib/src/dds_runner.dart | 44 ++------ pkg/dds/bin/dds.dart | 124 ++++++++++++++++----- sdk/lib/_internal/vm/bin/vmservice_io.dart | 21 +--- utils/dds/BUILD.gn | 2 +- 4 files changed, 109 insertions(+), 82 deletions(-) diff --git a/pkg/dartdev/lib/src/dds_runner.dart b/pkg/dartdev/lib/src/dds_runner.dart index 6982bcc6ca0..79ce257b014 100644 --- a/pkg/dartdev/lib/src/dds_runner.dart +++ b/pkg/dartdev/lib/src/dds_runner.dart @@ -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 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 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, ); diff --git a/pkg/dds/bin/dds.dart b/pkg/dds/bin/dds.dart index 9d4773214ff..acb009f9066 100644 --- a/pkg/dds/bin/dds.dart +++ b/pkg/dds/bin/dds.dart @@ -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 main(List 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 main(List 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({ diff --git a/sdk/lib/_internal/vm/bin/vmservice_io.dart b/sdk/lib/_internal/vm/bin/vmservice_io.dart index b41fe5b00ee..5f02fedc641 100644 --- a/sdk/lib/_internal/vm/bin/vmservice_io.dart +++ b/sdk/lib/_internal/vm/bin/vmservice_io.dart @@ -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, ); diff --git a/utils/dds/BUILD.gn b/utils/dds/BUILD.gn index 68d48a73b7d..d3580f67805 100644 --- a/utils/dds/BUILD.gn +++ b/utils/dds/BUILD.gn @@ -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" }