-
Notifications
You must be signed in to change notification settings - Fork 56
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
[native_assets_cli] Input.outputDirectorySystemShared
#1962
Comments
Good idea
Just to clarify, this is the workspace
If you upgrade
I believe that to be the default case, but not the general case. Examples for exceptions:
If we design the whole system with that user-machine specifics shouldn't matter for building artifacts of a package, then also package resolution and the resulting
Exactly. But there are considerable downsides to that approach as well. The code in your I think it might be good enough if hook authors decide whether their assets depend on the resolution in
👍
It should document it's shared across the system, but not across versions. What do we do with user-defines though? #39
(Off-topic: This probably also means we want the user-defines to have a target package and only make them available in those build and link hooks, so that we don't invalidate the cache for all other hooks.) And with
Note that link hooks would never be shared. They always depend on the entry point with tree shaking enabled. So they shouldn't even be shared in the workspace (#1956). |
Input.outputDirectorySystemShared
Notes from discussion with @mkustermann @mosuem @liamappelbe and @HosseinYousefi:
Dart APITo provide a nicer API for users, we could provide optional named arguments for the various types of sharing. These arguments can also be the place for documentation. A sketch: /// The directory in which output and intermediate artifacts can be placed.
///
/// If [workspaceIsolated], the directory will be scoped to the pub workspace.
/// If not [workspaceIsolated], the directory is system global. Only use the
/// system global output directory for assets that are _only_ dependent on the
/// hook itself. For example: Downloading prebuilt assets from the web.
///
/// If [configIsolated], the directory is unique per [config]. Use this to
/// avoid having config-dependent artifacts conflicting with each other.
///
/// If [versionIsolated], the directory is unique per version. For packages
/// with assets changing less frequent than the version, consider not using
/// version isolation and not using workspace isolation. This will prevent
/// building or redownloading assets multiple times.
///
/// The contents of this directory will not be modified by anything else than
/// the hook itself.
///
/// The invoker of the the hook will ensure concurrent invocations wait on
/// each other.
Uri getOutputDirectory({
bool workspaceIsolated = true,
bool versionIsolated = true,
bool configIsolated = true,
}) ProtocolWe can chose various levels of support in the protocol:
Related design questions
|
Maybe it would be best to make the protocol have two directories, e.g.:
and allow a hook to get a sub-directory of that that is config-specific via an API like @dcharkes suggested. This would
The downside is that it may store some binaries repeatedly, which is a bit like a pub-cache getting large with old unused versions. If we want to solve this problem, we probably want the same pruning solution that works for pub packages and their build artifacts. |
Agreed It would be very weird to have the global cache
I like this argument. Putting
Additionally the downside is that it will download binaries repeatedly. Let's investigate these downsides: We already download and store multiple versions of the Dart package already, so we'd be following that behavior. The question is whether the binary artifacts are significantly larger in size than the Dart sources.
(or 3 MB if third_party/ sources were excluded, which they would if a published version of the package would only support downloading prebuilt binaries. However, if there would be a
So for sample size N=1 the dylibs are the same size as the package (with cross compiling you'd get N * 1.5M leading to the same order of magnitude storage space). So @mkustermann's suggestion is: Uri getOutputDirectory({
bool workspaceIsolated = true,
bool configIsolated = true,
// bool versionIsolated = true, // always true
}) Protocol:
Some more gotcha's to think about when having version isolation:
I believe |
Notes from a discussion with @jonasfj workspace isolated / global cache
cc @mkustermann Thoughts? version isolated / version shared
config isolated
|
In this scenario, I think we should consider adding support for such binary artifacts through pub. I think @mkustermann suggested we do this a while back (something like python wheels), and I pushed back. And we shouldn't block native assets 1.0 on this.
I'm not entirely sure what we think But I'll say a few general things here:
|
Currently the build/link hooks are given two output directories:
outDir
: Unique to the configuration and packageoutDirShared
: Unique to the packageBoth of those are located in the
.dart_tool
folder that the developer is working on. We can leave it like this, but I just wanted to file this issue so we could discuss it a bit:Once our ecosystem uses hooks pervasively in many packages, we really care about it being fast: Running & Building apps should be fast.
It does raise a few questions:
What if someone upgrades Flutter SDK or Dart SDK: It will cause rerunning of all hooks, but the hooks are invoked with the same directories, making it an incremental build (afaik).
This is probably what we want, as the particular version of the Flutter/Dart SDK used to invoke the hook shouldn't affect the hook output much (if at all), so we really want incremental build here.
What if someone upgrades dependencies: It will cause rerunning of those dependencies, but the hooks are invoked with the same directories, making it an incremental build (afaik)
=> There's a question about expectations here: Will hook authors of packages write the hooks in a way that allows them to have "left over stuff" from different (most likely older) version of the package. So e.g. user has
package:crypto
dependency1.1.0
, runspub upgrade
and gets2.0.0
. Will the hook from2.0.0
be disturbed by finding old build results from1.1.0
?=> One could consider making the package directory also include the version number, but not sure if this makes sense.
=> The hook author could of course make a sub directory with the version number to avoid this.
What if someone builds app A and then app B: This will currently cause a re-build from scratch as the two apps will have different
.dart_tool
folders which don't share hook outputs. Not only will the user pay the price in terms of waiting time (for build hooks to run) but also in disc space.=> Let's assume developers will have reasonably many
.dart_tool
folders on their machine (at least I do).=> Let's further assume that very common packages will start using hooks (imagine a future
package:io
replacingdart:io
,package:http
, ...)=> Let's further assume those common packages's build output will be MBs in size.
(When actually building an app (e.g.
dart build
,flutter build
) one then copies those binaries again around, ending up with more duplicates)That will probably lead to a lot of wasted disc space (and possibly waiting time, network bandwith used, ...).
So I'm wondering if we should have a
config.outDirSystemShared
which is a system-wide per-package directory where the package's hook can store things. Those directories would be shared across all uses of the hook. So apackage:io
would store it's downloaded shared libraries into one place on the system and all hook invocations ofpackage:io
versions in various.dart_tool
app folders will all just emit assets from this shared directory (which may have version number ofpackage:io
in it).Another angle to view this is: The particular SDK (or other user-machine specifics) in question shouldn't matter for building artifacts of a package. One may want to build artifacts
All of these workflows would have one thing in common:
.dart_tool/package_config.json
of a particular app (which they shouldn't depend on anyway)=> We probably would do the build always this way if pub had
build_dependencies
.So given that, I'm wondering how much it makes sense to have the directories per-app and/or whether we should have an additional
config.outDirSystemShared
(e.g.~/.cache/dart/native_assets/<pkg-version>/
).Of course hook authors can do that themselves (just write to some place in the home directory), but:
The arguments whether to have it system-wide or not is somewhat similar to whether one may want to have a system-wide
~/.pub-cache
or one per app/cc @dcharkes @jonasfj
The text was updated successfully, but these errors were encountered: