-
Notifications
You must be signed in to change notification settings - Fork 67
[native_assets_cli] Add workspace path to input #2187
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
Comments
Where is the source on your system? In another package? So far we've been avoiding exposing the root package, because it would mean assets cannot be cached in a pub workspace across multiple packages. Coming to think of it, maybe we should only allow user-defines in the pub workspace pubspec instead of the root package pubspec? We could conceivably expose a path to the workspace in the input. cc @mosuem thoughts? |
I have a similar issue, and was just solving it by requiring absolute paths. But exposing the path to the pubspec/root folder sounds good to me. |
I think absolute paths are fine if the library is somewhere on your system. (Note you should not commit such path most likely. So we'll likely want some non-commitable place for user-defines as well.) However, if the file is somewhere in your workspace, then it's really annoying that you wouldn't be able to commit a relative path in the pubspec so that it would work for everyone checking out your git repo. @mosuem @simolus3 do any of your use cases have the file in the workspace? |
I'm wondering how user-defines at the pub workspace level would work if I want to depend on the same package (that defines hooks) in multiple packages of workspace but with different user-defines. For example, there are two flutter apps in the workspace, and they want to pass different values to As an aside: To me, |
We have a trade-off to make here. Assuming you do have multiple apps that use the same sqlite subset, you'd want your native assets to be shared. (Similarly to how all the Dart dependencies are shared.) If you want to "override" a Dart dependency for one app, you cannot have it in the same workspace. So my suggestion would be to not have those apps in the same workspace in that case.
I'm thinking that we will also allow command-line arguments at some point from Dart and Flutter, which would mirror https://dartcode.org/docs/using-dart-define-in-flutter/ . (And this will break the caching.) But I do agree it's kind of "code-centric" either C preprocessor or Dart. Config is already an overloaded term. I do like the "user", because it's signalling that these values are coming from the "end-user" e.g. the author of the root package (and workspace). If you have good suggestions, let me know, otherwise I think user-defines is a decent name for this concept. |
Do I want them to be shared because that reduces build times?
I think dependency versioning and configuration can be seen as different planes. In a pub workspace, every package uses the same version of a package but can configure and use it differently. Configuration is much more use case dependent than versioning. Potentially even dynamic (Dart defines can be provided at build time). Is the design for user defines to always be static? Something that feels related that I have been thinking about: Could Dart APIs be annotated with
I definitely think people will run into this! 😅 They will use pub workspaces for monorepos that contain reusable components and multiple apps that use them. You can have multiple pub workspaces in the same monorepo, but that somewhat defeats the purpose of using pub workspaces.
I think that's true from the perspective of a hook author. But for someone writing or reading user-defines in
To me, it would actually feel natural to have While it's usually nice to have symmetry in naming, I don't think the naming of the concept needs to be mirrored 1-to-1 in the hooks:
config:
sqlite3_native_assets:
source:
local: my_sqlite.c # file in the package applying mine I don't think this is a huge DX issue, though, just my 2 cents. 😊 |
build-times and disk space
It is not. If you pass command-line arguments for user-defines it's expected that your cache is invalidated. Maybe we add support for root package pubspec later (causing the cache to no longer be shared in workspaces). I think for command-line argument user-defines it always invalidates caches.
Can the subset of features be seen in the Dart API? If yes, I think it would be better to try to model this with What you are suggesting is that root-package authors need to configure the feature set. But this does not allow packages depending on you but depended on by the root package to declare that they require a feature. If it's not currently visible in the API, we should consider having a wdyt? |
So for context, while my package is downloading sources from sqlite3.org to compile them, there are ABI-compatible forks of sqlite3 that I know some users would like to use instead. I eventually want to move the native build hooks into So for this reason, I want to give users maximum flexibility to provide custom SQLite sources. And one of the options I had in mind was that users would vendor SQLite sources into their repository and then use user-defines towards However, I see that this sounds like a fairly unique use case, and I understand that this could make hermetic builds much harder. FWIW, I also allow users to completely skip my build hooks through user defines (with the intention that they would write their own |
That's an interesting use case. Reusing Dart code / bindings while dropping in another binary. That feels very much like what you'd do in the linking step in native code. You'd point to a different We could use link hooks in the following way:
This would enable someone to author a package that overrides the dylib and other packages to reuse such override. (Though maybe it's mostly the root package / app author that wants to override. So then the app / root package would have this in their build hook, and not publish a package.) If someone tries to use two packages that override at the same time, it wouldn't work. The build hook of such package would probably call a helper function from This would enable such override-dylib-packages to use all the infrastructure of using the hooks as normal. That seems like a clearer separation of concerns. If the package overrides the C sources, it should also build the dylib in its hook. That doesn't provide a solution for linking-not-enabled though. (Just brainstorming here. Maybe there's better ways to solve this.) |
If pub workspaces are used, then native assets are shared across the whole pub workspace. Using a different user-define, invalidates the cache. Therefore, we want to avoid having different user-defines in different pubspecs belonging to the same workspace. So, only use the workspace pubspec for user-defines. Analogous Dart SDK CL: https://dart-review.googlesource.com/c/sdk/+/422101 ### Testing Covered by the integration tests added in #166940 for user-defines. ### Design discussion We could allow adding user-defines in root package pubspecs later, but this will likely deteriorate caching behavior (either invalidating the cache often, or requiring a cache directory per root package, which increases latency for new root packages). Also, we'd likely add command-line user-defines later, these are expected to deteriorate caching behavior. For design discussion, refer to: * dart-lang/native#39 * dart-lang/native#2187
Native assets are cached for the whole pub workspace. So to avoid invalidating caches for running hooks from different root packages, only read user-defines from the workspace `pubspec.yaml`. Bug: dart-lang/native#39 Bug: dart-lang/native#2187 Change-Id: I3aeb91455a418004d3e28c231dc1f5d002c15739 Cq-Include-Trybots: luci.dart.try:pkg-linux-debug-try,pkg-linux-release-arm64-try,pkg-linux-release-try,pkg-mac-release-arm64-try,pkg-win-release-arm64-try,pkg-mac-release-try,pkg-win-release-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/422101 Auto-Submit: Daco Harkes <[email protected]> Reviewed-by: Hossein Yousefi <[email protected]> Commit-Queue: Daco Harkes <[email protected]>
RE: adding workspace directory
Edit: To support relative paths working properly, we want to distinguish where user-defines are coming from, cli arguments or workspace pubspec: "user_defines": {
"command_line_arguments": {
"user_defines": {
"my_data": "data/my_data.txt"
},
"working_directory": "~/src/foo/bar/pkgs/my_app/"
},
"workspace_pubspec": {
"user_defines": {
"foo_data": "pkgs/some_package/data/my_data.txt"
},
"workspace": "~/src/foo/bar/"
}
}, And then we can have a Dart interface that abstracts over the sources. class UserDefines {
Object? operator [] (String key) => // try command-line-args, if not populated try pubspec
Uri? path(List<String> keys, {bool absolute: true}) => // resolve path against the base path, try commandline-args first, then pubspec.
} (This intentionally hides from hook authors what the source of a user-define is.) This also scopes the use of the workspace directory to be only used for user-defines, and makes it not available in the API. |
For my use-cases that approach looks good to me 👍 |
SGTM - but why a list of keys as argument for the |
If you put a path not at the top level: "user_defines": {
"command_line_arguments": {
"user_defines": {
"my_data": {
"some_nested_path": "data/my_data.txt"
}
},
"working_directory": "~/src/foo/bar/pkgs/my_app/"
},
"workspace_pubspec": {
"user_defines": {
"my_data": {
"some_nested_path": "pkgs/some_package/data/my_data.txt"
}
},
"workspace": "~/src/foo/bar/"
}
}, |
The |
Bug: #39 Closes: #2187 Closes: #2201 ### Relative paths in user-defines accessible as absolute paths in hooks This PR enables resolving relative paths in user-defines as absolute paths. The `input.json` now is structured as follows: ```json { "user_defines": { "workspace_pubspec": { "base_path": "/private/var/folders/2y/mngq9h194yzglt4kzttzfq6800klzg/T/QqYcWN/user_defines/pubspec.yaml", "defines": { "user_define_key": "user_define_value", "user_define_key2": { "foo": "bar" }, "some_file": "assets/data.json" } }, }, } ``` We don't want to expose the workspace/pubspec path (except for resolving user-defines), so this can be done in the Dart API as follows: ```dart extension type HookInputUserDefines._(HookInput _input) { /// The value for the user-define for [key] for this package. /// /// This can be arbitrary JSON/YAML if provided from the SDK from such source. /// If it's provided from command-line arguments, it's likely a string. Object? operator [](String key) => // already present before this PR /// The absolute path for user-defines for [key] for this package.key /// /// The relative path passed as user-define is resolved against the base path. /// For user-defines originating from a JSON/YAML, the base path is this /// JSON/YAML. For user-defines originating from command-line aruments, the /// base path is the working directory of the command-line invocation. /// /// If the user-define is `null` or not a [String], returns `null`. Uri? path(String key) => // added in this PR. } ``` This PR does _not_ yet add support for command-line user-defines. But the JSON has been set up so that it's extensible. ### Move reading user-defines from flutter_tools/dartdev to `NativeAssetsBuildRunner` This PR changes the responsibility to read the user-defines from the pubspec to the `NativeAssetsBuildRunner`. 1. This ensures all SDKs have the same logic for reading user-defines 2. This ensures all SDKs have the same caching behavior for files containing user-defines changing on disk. This PR adds the pubspec.yaml in the `HookOutput.dependencies` to ensure the build runner is reinvoked if the pubspec changes. The API for the `NativeAssetsBuildRunner` changes to take the `pubspec.yaml` uri rather than user-defines. Consequently, this PR will need a manual roll into dartdev and flutter_tools.
Note: This needs to roll into Dart and Flutter first before it can be used. |
Roll for dart-lang/native#2187. The `NativeAssetsBuildRunner` now checks the pubspec for valid user-defines, errors if they are not valid, and loads them. So, delete all code in dartdev which did this. Change-Id: I34f5bba3f4a7c4847c9cd33901c2f0a2f915ea22 Cq-Include-Trybots: luci.dart.try:pkg-linux-debug-try,pkg-linux-release-arm64-try,pkg-linux-release-try,pkg-mac-release-arm64-try,pkg-win-release-arm64-try,pkg-mac-release-try,pkg-win-release-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/422720 Reviewed-by: Hossein Yousefi <[email protected]> Commit-Queue: Daco Harkes <[email protected]>
Roll for dart-lang/native#2187.
Uh oh!
There was an error while loading. Please reload this page.
I'm adopting user-defines for my
native_assets
package (thanks for shipping that btw! 🚀 ). One of the options I'd like to provide is for users to specify a custom C source file that would be used instead of (or in addition to) the default sources used by my package.I'm imagining that users would configure this like that:
My build hooks are then reading that option and can use that as an input. However, since all paths resolve against my own package (#1915), I need a way to figure out the root input package in some cases. At the moment, I'm reconstructing it from the output path but I'd like something more reliable than this:
I couldn't find anything in
HookInputs
that provides that root input path.The text was updated successfully, but these errors were encountered: