-
Notifications
You must be signed in to change notification settings - Fork 215
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support native assets #1975
Support native assets #1975
Conversation
Should this apply to both AOT and JIT modes? We also support compiling with |
Ah, I'm not aware of that code path, met me try! |
|
||
// If we have native assets for the host os in JIT mode, they are here. | ||
Uri? nativeAssetsYaml = | ||
packageConfigUriAwaited.resolve('native_assets.yaml'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be a configurable path? Or just wait to allow that until/if it is needed later?
The package config isn't always necessarily what you think it is... tools could copy it to a new location and modify it before invoking us etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use case I'm thinking about is dart test
which is equal to dart run test:test
. In this case dart run
/dart test
will run themselves in JIT mode use the .dart_tools/package_config.json
and .dart_tools/native_assets.yaml
.
(dart test/foo_test.dart
already works after .dart_tools/package_config.json
and .dart_tools/native_assets.yaml
are present. Basically running a test that way skips the whole runner infrastructure.)
tools could [...]
I hope these tools would then still run dart pub get
+ dart test
/dart run test
which would then result in the same layout. Are you aware of tools that do different things?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this package actually reads the Isolate.packageConfig
to get the location. Users can customize what package config they pass, it's just that by default it will be .dart_tool/package_config.json
. But we are not opinionated today and I would like to keep it that way if possible.
There is also one very concrete place this will happen which is internally, the package config files are always manually passed. I don't believe that internal hits this code path today though (it uses pre-compiled mode or runs directly from source), and I don't know what our plans are there long term.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope these tools would then still run dart pub get + dart test/dart run test which would then result in the same layout. Are you aware of tools that do different things?
I am not sure if it is still the case but for a long time flutter used to mess with the package config after pub get, to inject some references to generated packages. It did cause problems for build_runner etc or other tools that expect the .dart_tool/package_config.json
file to be the source of truth, or the pubspec.yaml
or pubspec.lock
files to agree with the package_config.json
file (which was the case with build_runner).
Also as soon as you step outside of the pub ecosystem all these assumptions no longer apply.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, for Flutter I have implementations for this in flutter_tools
. (It does cross-compiling, Dart doesn't. It bundles libraries differently per target OS as well, so it also transforms the paths where libraries are found for the target bundles.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a random thought here, but would it make sense to add a new (optional) field to the package_config.json
which lists the location of the native_assets.yaml
file? That way we need no changes to this package at all, and internally it should also be more straightforward.
Any command that supports reading that file would just get it from the package config, which is always already supplied.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good thought. @jonasfj and discussed embedding the native assets mapping inside the package config earlier.
Unfortunately package_config.json
is produced by pub on pub get
, this file is produced on dart run
, dart compile
, flutter run
, dart test
, flutter pub test
which is later in the pipeline. Only those later stages of the pipeline know where a file is shipped. (For example an Android bundle in the case of Flutter, in which case the paths of dylibs are inside that Android bundle.) So pub cant produce this file, only the embedders can. And pub doesn't know if and when embedders are going to produce this file.
(Side note, I believe the pub authors don't like us modifying package_config.json
after pub created that file.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the pub authors don't like us modifying package_config.json after pub created that file.
Yeah, ideally it's best not to do this. It messes up timestamps. We can add support for it -- but I would suggest just writing it next to package_config.json
in .dart_tool/native_assets.yaml
.
This is not going to work just yet.
To support dynamic libraries, we need to introduce a new command I have added a check to I can follow up with |
Why do you need to invoke My guess is that you haven't ran a Ultimately though I would add this test to the |
Before landing native assets mapping in the Dart SDK for I need to land this PR first and roll it into the SDK and add a test there. And later a test here once an SDK has been released with
Here is what the test would look like once https://github.com/dart-lang/test/compare/native-assets-test |
package:test itself does not require any native assets, so this shouldn't matter right?
Ok so maybe this explains things for me, is the issue that the |
I am just going to check out your branch and see if I can get things working locally :) |
I tried building the latest sdk and running I wanted to try just checking in this file into the integration test, at least until the SDK can actually build it as a part of |
Correct, none of the released SDKs will produce
Correct. You need some version of https://dart-review.googlesource.com/c/sdk/+/26734.
Incorrect, that exists. See the tests that manually provide a native_assets.yaml in https://github.com/dart-lang/sdk/tree/main/tests/ffi/native_assets.
Checking in won't work fully, we need to provide an absolute path, a target ( format-version:
- 1
- 0
- 0
native-assets:
linux_x64:
package:native_add/src/native_add_bindings_generated.dart:
- absolute
- /usr/local/google/home/dacoharkes/src/dart-lang/test/pkgs/test/test/runner/native_assets/test_projects/native_add/out/libnative_add.so Moreover, before landing some version of https://dart-review.googlesource.com/c/sdk/+/26734 that file is to going to be ignored when doing |
Ok, so given all that it sounds like we can't land any test of the functionality in this repo until the SDK changes are landed. I am hesitant to land anything that is enabled by default but not tested though (on CI). I wouldn't want a new SDK to drop that creates this file but then the way we use it is somehow broken and people get broken. Could we guard this code behind an environment variable so that you can enable it explicitly in the SDK tests? I am not sure if our CI setup there supports setting an environment variable for a test. |
In the CL that would start creating this file, would also land a unit test that exercises
That could work, as I'm invoking I think a better solution might be to gate all native assets logic in the SDK behind an experimental flag, that way the |
Hm, (Side note: We want a experimental flag this feature, since it's an experiment we can't really experiment with if it only runs on my machine locally. So we want to land some stuff behind a flag. So it's not just for this PR.) |
Experiments are supported at least to some extent, IIRC you need to pass them before the |
Would the file potentially still exist but with stale contents though if somebody ran with the experiment once and then without it? We could parse the VM arguments to see if this experiment is enabled though and guard the logic behind that. |
Good catch.
Perfect! That was indeed an issue. https://dart-review.googlesource.com/c/sdk/+/267340/42 with https://github.com/dart-lang/test/tree/native-assets-test
|
Yeah the way experiments can/should be specified in general is pretty weird and seemingly inconsistent to the end user, although it can usually be explained with reason, it isn't obvious :). Fwiw for package:test we rely on the argument being set for the actual test runner script because we spawn Isolates to run tests, and we can't enable an experiment just for an Isolate. |
I think this PR is pretty much ready to go but I think we want to land #1974 first, cc @natebosch . Then we will want to update the pubspec/changelog here. |
The versioning here is slightly complicated so I will push up a pubspec/changelog change |
Ready to merge from my side if you're happy with it. |
@natebosch good on your end? |
The Dart VM expects a
native_assets.yaml
next topackages_config.json
to contain the mapping for@FfiNative
and@Native
FFI functions when running a script or spawning an isolate.When a program compiles to kernel eagerly (before invoking the Dart VM), it should add that
native_assets.yaml
to the kernel compilation invocation.package:test
does manual compilation to kernel, so it needs to provide this mapping.After https://dart-review.googlesource.com/c/sdk/+/267340, the
native_assets.yaml
will be created bydartdev
when doingdart test
ordart run test
.I'm not entirely sure how to test this PR.
I can't land the dartdev logic in https://dart-review.googlesource.com/c/sdk/+/267340 without doing dependency overrides for package:test and package:test_core, but I don't want to land dependency overrides pointing to non-merged code in the SDK.
I can't easily add a unit test that compiles a dynamic library and adds a
native_assets.yaml
manually on this repo. I would need to be able to invokebin/test.dart
instead ofdart run test:test
from an example project that provides a dylib. But package:test doesn't seem to support that:I know it works locally with a patched package:test and patched dartdev.
Any suggestions for how to test this?
(For reference: the unit tests in the VM that get a manually provided
native_assets.yaml
: https://dart-review.googlesource.com/c/sdk/+/264842)