From 060e4e208ceb66872708b151c13ec71e07c627ab Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Fri, 2 May 2025 11:49:21 -0700 Subject: [PATCH] dartdev: Support running the AOT analyis_server snapshot for analyze command The `dart analyze` command is quite separate from the `dart language-server` command. This CL adds support for `dart analyze`. Work towards https://github.com/dart-lang/sdk/issues/50498 Change-Id: I60a846ae5d3452c2bb050bd07502084ff44b82c0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/425188 Commit-Queue: Samuel Rawlins Reviewed-by: Siva Annamalai --- .../lib/src/utilities/sdk.dart | 9 +--- pkg/dartdev/lib/src/analysis_server.dart | 48 ++++++++++++------- pkg/dartdev/lib/src/commands/analyze.dart | 15 ++++-- .../lib/src/commands/language_server.dart | 8 ++-- pkg/dartdev/lib/src/core.dart | 14 ------ pkg/dartdev/lib/src/sdk.dart | 2 + sdk/BUILD.gn | 1 + utils/analysis_server/BUILD.gn | 4 +- utils/aot_snapshot.gni | 3 ++ 9 files changed, 54 insertions(+), 50 deletions(-) diff --git a/pkg/analysis_server/lib/src/utilities/sdk.dart b/pkg/analysis_server/lib/src/utilities/sdk.dart index b201df84fc0..af99cb5fedf 100644 --- a/pkg/analysis_server/lib/src/utilities/sdk.dart +++ b/pkg/analysis_server/lib/src/utilities/sdk.dart @@ -30,14 +30,7 @@ class Sdk { /// Path to the 'dart' executable in the Dart SDK. String get dart { - var basename = path.basename(Platform.executable); - // It's possible that `Platform.executable` won't include the '.exe' - // extension on Windows (e.g., launching `dart` from `cmd.exe` where `dart` - // is on the `PATH`). Append '.exe' in this case so the - // `checkArtifactExists` check won't fail. - if (Platform.isWindows && !basename.endsWith('.exe')) { - basename += '.exe'; - } + var basename = Platform.isWindows ? 'dart.exe' : 'dart'; return path.absolute( _runFromBuildRoot ? sdkPath : path.absolute(sdkPath, 'bin'), basename, diff --git a/pkg/dartdev/lib/src/analysis_server.dart b/pkg/dartdev/lib/src/analysis_server.dart index 9b3c4f66613..9494240797c 100644 --- a/pkg/dartdev/lib/src/analysis_server.dart +++ b/pkg/dartdev/lib/src/analysis_server.dart @@ -37,7 +37,8 @@ class AnalysisServer { this.enabledExperiments = const [], this.disableStatusNotificationDebouncing = false, this.suppressAnalytics = false, - }); + bool useAotSnapshot = false, + }) : _useAotSnapshot = useAotSnapshot; final String? cacheDirectoryPath; final File? packagesFile; @@ -48,6 +49,7 @@ class AnalysisServer { final List enabledExperiments; final bool disableStatusNotificationDebouncing; final bool suppressAnalytics; + final bool _useAotSnapshot; Process? _process; @@ -107,24 +109,8 @@ class AnalysisServer { /// Starts the process and returns the pid for it. Future start({bool setAnalysisRoots = true}) async { preAnalysisServerStart?.call(commandName, analysisRoots, argResults); - final command = [ - sdk.analysisServerSnapshot, - if (suppressAnalytics) '--${Driver.SUPPRESS_ANALYTICS_FLAG}', - '--${Driver.CLIENT_ID}=dart-$commandName', - '--disable-server-feature-completion', - '--disable-server-feature-search', - if (disableStatusNotificationDebouncing) - '--disable-status-notification-debouncing', - '--disable-silent-analysis-exceptions', - '--sdk', - sdkPath.path, - if (cacheDirectoryPath != null) '--cache=$cacheDirectoryPath', - if (packagesFile != null) '--packages=${packagesFile!.path}', - if (enabledExperiments.isNotEmpty) - '--$experimentFlagName=${enabledExperiments.join(',')}' - ]; - final process = await startDartProcess(sdk, command); + final process = await _startProcess(); _process = process; _shutdownResponseReceived = false; // This callback hookup can't throw. @@ -206,6 +192,32 @@ class AnalysisServer { return process.pid; } + Future _startProcess() { + final executable = _useAotSnapshot ? sdk.dartAotRuntime : sdk.dart; + final arguments = [ + if (_useAotSnapshot) + sdk.analysisServerAotSnapshot + else + sdk.analysisServerSnapshot, + if (suppressAnalytics) '--${Driver.SUPPRESS_ANALYTICS_FLAG}', + '--${Driver.CLIENT_ID}=dart-$commandName', + '--disable-server-feature-completion', + '--disable-server-feature-search', + if (disableStatusNotificationDebouncing) + '--disable-status-notification-debouncing', + '--disable-silent-analysis-exceptions', + '--sdk', + sdkPath.path, + if (cacheDirectoryPath != null) '--cache=$cacheDirectoryPath', + if (packagesFile != null) '--packages=${packagesFile!.path}', + if (enabledExperiments.isNotEmpty) + '--$experimentFlagName=${enabledExperiments.join(',')}', + ]; + + log.trace('$executable ${arguments.join(' ')}'); + return Process.start(executable, arguments); + } + Future getVersion() { return _sendCommand('server.getVersion') .then((response) => response['version']); diff --git a/pkg/dartdev/lib/src/commands/analyze.dart b/pkg/dartdev/lib/src/commands/analyze.dart index 8eeebe58f63..06859c5c814 100644 --- a/pkg/dartdev/lib/src/commands/analyze.dart +++ b/pkg/dartdev/lib/src/commands/analyze.dart @@ -90,6 +90,11 @@ class AnalyzeCommand extends DartdevCommand { help: 'The path to the Dart SDK.', hide: !verbose, ) + ..addFlag( + useAotSnapshotFlag, + help: 'Use the AOT analysis server snapshot', + hide: true, + ) ..addExperimentalFlags(); } @@ -129,20 +134,23 @@ class AnalyzeCommand extends DartdevCommand { final printMemory = args.flag('memory') && jsonFormat; io.Directory sdkPath; + final useAotSnapshot = args.flag(useAotSnapshotFlag); if (args.wasParsed('sdk-path')) { sdkPath = io.Directory(args.option('sdk-path')!); if (!sdkPath.existsSync()) { usageException('Invalid Dart SDK path: ${sdkPath.path}'); } + final snapshotName = useAotSnapshot + ? 'analysis_server_aot.dart.snapshot' + : 'analysis_server.dart.snapshot'; final snapshotPath = path.join( sdkPath.path, 'bin', 'snapshots', - 'analysis_server.dart.snapshot', + snapshotName, ); if (!io.File(snapshotPath).existsSync()) { - usageException( - 'Invalid Dart SDK path has no analysis_server.dart.snapshot file: ' + usageException("Invalid Dart SDK path has no '$snapshotName' file: " '${sdkPath.path}'); } } else { @@ -180,6 +188,7 @@ class AnalyzeCommand extends DartdevCommand { disableStatusNotificationDebouncing: true, enabledExperiments: args.enabledExperiments, suppressAnalytics: suppressAnalytics, + useAotSnapshot: useAotSnapshot, ); server.onErrors.listen((FileAnalysisErrors fileErrors) { diff --git a/pkg/dartdev/lib/src/commands/language_server.dart b/pkg/dartdev/lib/src/commands/language_server.dart index 42c2708adf0..79fbfed08c5 100644 --- a/pkg/dartdev/lib/src/commands/language_server.dart +++ b/pkg/dartdev/lib/src/commands/language_server.dart @@ -35,7 +35,7 @@ For more information about the server's capabilities and configuration, see: usageLineLength: dartdevUsageLineLength, includeHelpFlag: false, defaultToLsp: true, - )..addFlag(_useAotSnapshotFlag, + )..addFlag(useAotSnapshotFlag, help: 'Use the AOT analysis server snapshot', hide: true); } @@ -49,11 +49,11 @@ For more information about the server's capabilities and configuration, see: args = [...args, '--$protocol=$lsp']; } try { - if (argResults!.flag(_useAotSnapshotFlag)) { + if (argResults!.flag(useAotSnapshotFlag)) { if (!Sdk.checkArtifactExists(sdk.dartAotRuntime)) { return _genericErrorExitCode; } - args.remove('--$_useAotSnapshotFlag'); + args.remove('--$useAotSnapshotFlag'); VmInteropHandler.run( sdk.dartAotRuntime, [sdk.analysisServerAotSnapshot, ...args], @@ -77,7 +77,5 @@ For more information about the server's capabilities and configuration, see: } } - static const _useAotSnapshotFlag = 'use-aot-snapshot'; - static const _genericErrorExitCode = 255; } diff --git a/pkg/dartdev/lib/src/core.dart b/pkg/dartdev/lib/src/core.dart index 1eda0d3919c..6262f422bf7 100644 --- a/pkg/dartdev/lib/src/core.dart +++ b/pkg/dartdev/lib/src/core.dart @@ -12,7 +12,6 @@ import 'package:cli_util/cli_logging.dart'; import 'package:path/path.dart' as path; import 'experiments.dart'; -import 'sdk.dart'; import 'utils.dart'; // Initialize a default logger. We'll replace this with a verbose logger if @@ -86,19 +85,6 @@ extension DartDevCommand on Command { globalResults!.multiOption(experimentFlagName); } -/// A utility method to start a Dart VM instance with the given arguments and an -/// optional current working directory. -/// -/// [arguments] should contain the snapshot path. -Future startDartProcess( - Sdk sdk, - List arguments, { - String? cwd, -}) { - log.trace('${sdk.dart} ${arguments.join(' ')}'); - return Process.start(sdk.dart, arguments, workingDirectory: cwd); -} - Future runProcess( List command, { bool logToTrace = false, diff --git a/pkg/dartdev/lib/src/sdk.dart b/pkg/dartdev/lib/src/sdk.dart index ca2de5e7348..20835bfb55e 100644 --- a/pkg/dartdev/lib/src/sdk.dart +++ b/pkg/dartdev/lib/src/sdk.dart @@ -288,3 +288,5 @@ class Runtime { return Runtime._(version, channel); } } + +const useAotSnapshotFlag = 'use-aot-snapshot'; diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn index 10277d0ed5e..0343253075e 100644 --- a/sdk/BUILD.gn +++ b/sdk/BUILD.gn @@ -42,6 +42,7 @@ declare_args() { # ......utils/gen_snapshot or utils/gen_snapshot.exe (if not on ia32) # ......snapshots/ # ........analysis_server.dart.snapshot +# ........analysis_server_aot.dart.snapshot (AOT snapshot, if not on ia32) # ........dart2bytecode.snapshot (AOT snapshot, for selected targets) # ........dart2js_aot.dart.snapshot (AOT snapshot, if not on ia32) # ........dart2js.dart.snapshot (JIT snapshot only on ia32) diff --git a/utils/analysis_server/BUILD.gn b/utils/analysis_server/BUILD.gn index d50b86b7991..10ee5468b80 100644 --- a/utils/analysis_server/BUILD.gn +++ b/utils/analysis_server/BUILD.gn @@ -9,13 +9,14 @@ aot_snapshot("analysis_server_aot") { main_dart = "../../pkg/analysis_server/bin/server.dart" name = "analysis_server_aot" output = "$root_gen_dir/analysis_server_aot.dart.snapshot" - vm_args = [ "-Dbuilt_as_aot=true" ] + args = [ "-Dbuilt_as_aot=true" ] } aot_snapshot("analysis_server_aot_product") { main_dart = "../../pkg/analysis_server/bin/server.dart" name = "analysis_server_aot_product" output = "$root_gen_dir/analysis_server_aot_product.dart.snapshot" + args = [ "-Dbuilt_as_aot=true" ] # dartaotruntime in the dart sdk has dart_product_config applied to it, # so it is built in product mode in both release and @@ -32,5 +33,4 @@ application_snapshot("analysis_server") { "--sdk=" + rebase_path("../../sdk/"), "--train-using=" + rebase_path("../../pkg/compiler/lib"), ] - vm_args = [ "-Dbuilt_as_aot=false" ] } diff --git a/utils/aot_snapshot.gni b/utils/aot_snapshot.gni index 5288554ff36..138e6baf011 100644 --- a/utils/aot_snapshot.gni +++ b/utils/aot_snapshot.gni @@ -98,6 +98,9 @@ template("aot_snapshot") { if (product_mode) { args += [ "-Ddart.vm.product=true" ] } + if (defined(invoker.args)) { + args += invoker.args + } } # Whether to build an AOT snapshot, which can be opened by dlopen.