Repository navigation
Conversation
Declare pigeon under executables in pubspec.yaml, remove unused dart:mirrors imports, and resolve the Dart SDK and executable via package:cli_util.
There was a problem hiding this comment.
Code Review
This pull request updates the pigeon package to support running as a standalone AOT-compiled executable. It removes unused dart:mirrors imports, registers pigeon under executables in pubspec.yaml, adds a dependency on cli_util, and resolves the Dart SDK path using cli_util.sdkPath. A test is also added to verify SDK resolution. Feedback points out that cli_util does not expose a dartExecutable property, which will cause a compilation error, and suggests constructing the path manually using cli_util.sdkPath.
| final bool useJni = internalOptions.kotlinOptions?.useJni ?? false; | ||
|
|
||
| final String dartExecutable = Platform.resolvedExecutable; | ||
| final String dartExecutable = cli_util.dartExecutable ?? Platform.resolvedExecutable; |
There was a problem hiding this comment.
The cli_util package does not expose a dartExecutable property or getter. Accessing cli_util.dartExecutable will result in a compilation error. Instead, you should construct the path to the dart executable using cli_util.sdkPath and path.join.
final String dartExecutable = path.join(cli_util.sdkPath, 'bin', Platform.isWindows ? 'dart.exe' : 'dart');|
@tarrinneal any chance you could take a look at this one please? I'm looking at removing |
| dependencies: | ||
| analyzer: ">=13.0.0 <15.0.0" | ||
| args: ^2.5.0 | ||
| cli_util: ">=0.4.2 <0.7.0" |
There was a problem hiding this comment.
cli_util only added AOT SDK discovery (and nullable String? get sdkPath) in 0.6.0; in 0.4.2–0.5.2, cli_util.sdkPath unconditionally returns non-null path.dirname(path.dirname(Platform.resolvedExecutable)). Because dev_dependencies here has swiftgen: 0.2.0 -> ffigen: ^22.0.0 -> cli_util: ^0.4.2, packages/pigeon (and any project using swiftgen: ^0.2.0) resolves cli_util to 0.4.2:
- Under
<0.6.0, AOT SDK lookup doesn't happen, andsdkPath ?? cli_util.sdkPathinparseFileis nevernull—overridinganalyzer'sgetSdkPath()candidate search (such asthird_party/dart_lang/v2/sdkin google3 runfiles and<exeDir>/dart-sdk) with an unvalidated parent directory. - Also note the PR description still mentions
cli_util: ^0.6.0.
If >=0.4.2 <0.7.0 is needed until swiftgen supports ffigen >=23.0.0, could pigeon validate that cli_util.sdkPath actually contains SDK markers before passing it to AnalysisContextCollection (or use parseString(..., throwIfDiagnostics: false) from package:analyzer/dart/analysis/utilities.dart when sdkPath == null, since parseFile only needs syntactic parsing and wouldn't require a host Dart SDK at all)?
| static String _resolveDartExecutable(String? sdkPath) { | ||
| if (sdkPath != null) { | ||
| return path.join(sdkPath, 'bin', Platform.isWindows ? 'dart.exe' : 'dart'); | ||
| } | ||
| return Platform.resolvedExecutable; | ||
| } |
There was a problem hiding this comment.
Two issues with resolving dartExecutable for FFIgen/JNIgen:
- Line 903 passes
cli_util.sdkPathinstead ofsdkPath ?? cli_util.sdkPath, ignoring thesdkPathparameter passed intorunWithOptions. - When
pigeonis compiled to a standalone AOT binary,Platform.resolvedExecutableis thepigeonexecutable itself (notdart). IfsdkPathisnull(e.g.cli_util.sdkPathcan't find an SDK), falling back toPlatform.resolvedExecutableon line 807 causes_runFfigen/_runJnigento runpigeon run <configFile>instead ofdart run <configFile>—which prints usage and exits0(L851), silently skipping binding generation.
If sdkPath is null and Platform.resolvedExecutable isn't dart, should this fail with a clear error (or fall back to 'dart' on PATH) instead?
| test('parseFile locates Dart SDK via cli_util', () { | ||
| String requireSdkPath(String? sdkPath) => sdkPath!; | ||
| final String currentSdk = requireSdkPath(cli_util.sdkPath); | ||
| final ParseResults parseResult = runZoned( | ||
| () => parseSource('class Message { String? text; }'), | ||
| zoneValues: <Object, Object>{ | ||
| #environmentOverrides: <String, String>{ | ||
| '_DART_RESOLVED_EXECUTABLE': '/nonexistent/bin/pigeon', | ||
| 'DART_SDK': currentSdk, | ||
| }, | ||
| #_environmentOverrides: <String, String>{ | ||
| '_DART_RESOLVED_EXECUTABLE': '/nonexistent/bin/pigeon', | ||
| 'DART_SDK': currentSdk, | ||
| }, | ||
| }, | ||
| ); | ||
| expect(parseResult.errors, isEmpty); | ||
| expect(parseResult.root.classes.single.name, 'Message'); | ||
| }); |
There was a problem hiding this comment.
This test passes even if 'DART_SDK' is '/nonexistent' or sdkPath ?? cli_util.sdkPath is reverted:
- In Dart,
#_environmentOverridesis a library-privateSymbolscoped topigeon_lib_test.dart, so it doesn't matchcli_util's#_environmentOverrides(cli_util.environmentOverridesKeyin0.6.0)—under0.6.0,Zone.current[environmentOverridesKey]isnullandcli_util.sdkPathreturns_cachedSdkPathfrom line 3343. - In
packages/pigeon,cli_utilcurrently resolves to0.4.2(viaffigen: 22.0.0), wherecli_util.sdkPathignoresZone.currentaltogether and reads the JIT test runner'sPlatform.resolvedExecutable.
| ## 29.1.1 | ||
|
|
||
| * Adds `pigeon` to `executables` in `pubspec.yaml` and resolves the Dart SDK and | ||
| executable via `package:cli_util` so `pigeon` can run as a standalone | ||
| AOT-compiled executable (such as via `dart install` or `dart run pigeon@`). |
There was a problem hiding this comment.
Since lib/src/pigeon_lib.dart (_executeConfigurePigeon) and lib/src/generator_tools.dart still import dart:mirrors until #13524 lands, dart install pigeon / dart run pigeon@ will fail to AOT-compile if this merges and auto-publishes first. Can we land #13524 first and rebase this PR onto main (now at 30.0.2, which also already added cli_util to .repo_tool_config.yaml)?
| final collection = AnalysisContextCollection( | ||
| includedPaths: includedPaths, | ||
| sdkPath: sdkPath ?? cli_util.sdkPath, | ||
| ); |
There was a problem hiding this comment.
If parseFile keeps AnalysisContextCollection, note that AnalysisContextCollection throws ArgumentError when sdkPath isn't normalized (path.normalize(p) == p), and cli_util 0.6.0 calls path.absolute without path.normalize—so a trailing slash like DART_SDK=/path/to/dart-sdk/ will throw unless normalized with path.normalize(path.absolute(...)).
| flutter: | ||
| uses-material-design: true |
There was a problem hiding this comment.
Nit: Please revert the unrelated trailing-newline changes here and in platform_tests/test_plugin/example/pubspec.yaml.
| version: 29.1.1 # This must match the version in lib/src/generator_tools.dart | ||
|
|
||
| environment: | ||
| sdk: ^3.11.0 | ||
|
|
||
| executables: | ||
| pigeon: |
There was a problem hiding this comment.
Since adding pigeon under executables: exposes a new CLI entrypoint for dart install / dart pub global activate, should this be a minor bump (30.1.0 once rebased onto main) rather than a patch bump?
| /// [AnalysisContextCollection]. | ||
| ParseResults parseFile(String inputPath, {String? sdkPath}) { | ||
| final includedPaths = <String>[path.absolute(path.normalize(inputPath))]; |
There was a problem hiding this comment.
Nit: While touching parseFile, could we clean up its doc comment just above (L489-L492—[path] -> [inputPath] and drop the nonexistent [types] reference)?
Declares
pigeonunderexecutablesinpubspec.yamland resolves the Dart SDK anddartexecutable viapackage:cli_util(cli_util: ^0.6.0).Previously,
pigeoncould not be compiled to and run as a standalone AOT executable (such as viadart install pigeonordart run pigeon@) because:Pigeon.parseFilerelied onAnalysisContextCollection's defaultsdkPathdiscovery (FolderBasedDartSdk.defaultSdkDirectory, which assumesPlatform.resolvedExecutableis<sdk>/bin/dartrather than the compiledpigeonbinary), andrunWithOptionsusedPlatform.resolvedExecutabledirectly when invokingdart runfor FFIgen/JNIgen.dart:mirrorsimports ( also required for AOT compilation) has been split out into [pigeon] Remove remaining dart:mirrors usage #13524 (fixing [pigeon] Remove remainingdart:mirrorsusage flutter#190228).Part of dart-lang/sdk#63210
Pre-Review Checklist
[shared_preferences]///).Footnotes
Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2