Skip to content
Prev Previous commit
Next Next commit
Iterate on the v1 spec
  • Loading branch information
dcharkes committed Jan 25, 2024
commit d75f6ab7e754647bbba060307412c9717b1a7ddc
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
Build Hook Specification
========================

**DISCLAIMER:** This is really just a native attempt, at writing a specification.


## Version 1: Currently implemented behind `--enable-experiment=native-assets`

Version 1: As of 2024-01-24 implemented behind `--enable-experiment=native-assets`

### Concepts


#### Asset
A file that is identified by an `assetId`. There may be multiple files with the
same `assetId` with different characteristics such as `target` or `link_mode`.

Note that in v1 there are _only_ native code assets, no data assets.

#### AssetId
An asset must have an `assetId`. Dart code that uses an asset, references the
asset using the `assetId`.
Expand All @@ -33,8 +30,6 @@ Dart and Flutter SDKs to be specified below:
* `linux_x64`
* TODO: enumerate full list of supported platform/architecture tuples.

**Remark:** It may appear confusing that `link_mode` is not part of the target
(if so, that's probably because it is confusing).


### `build.dart`
Expand All @@ -55,7 +50,7 @@ The `build.dart` file MUST:
* If `dry_run: true` in `build_config.yaml`, then this may be skipped.
* Filename are unrelated to `assetId`.
* Arbitrary file names are fine, `build_output.yaml` will map `assetId` to files.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this mean?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file names of the assets don't really matter. It could be file1.foo, file2.foo, file3.foo. Because the only way assets are accessed from Dart code is through their assetId.

However, we do want to have to files written to disk rather than having a buffer of bytes for files, because quite often the files are produces by an external Process call or for data assets already in your package.

* MUST avoid file name `build_output.yaml` (yes, this is poor design)
* MUST avoid file name `build_output.yaml`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a name for an asset?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you write your asset to out_dir/build_output.yaml it's going to fail to write build_output.yaml

Maybe in v2 we should consider writing the assets somewhere else than the build output.

* Write `build_output.yaml` into `out_dir` (from `build_config.yaml`).
* This maps `assetId` to assets previous written in `out_dir`.
* There may be multiple assets for a given `assetId` depending on
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to add something about the uniqueness of an assetId - this was unclear in an earlier review comment as well.

Expand All @@ -74,45 +69,65 @@ Configuration file passed to `build.dart` as the `--config` option.
# Running in dry-run mode `<out_dir>/build_output.yaml` must be written, but
# the files it references need not exist.
dry_run: true | false

# Build Mode.
#
# A hint `build.dart` can use to determined which optimizations to enable and
# whether or not to include debug symbols in the format relevant for the asset.
#
# Not provided on dry runs.
build_mode: release | debug
# Unspecified
dependency_metadata: {}

# Metadata as output from build.dart from direct dependencies.
#
# Not provided on dry runs.
dependency_metadata:
# package name of direct dependency.
some_package_name:
# key value pairs.
some_key: some_value

# Preferred link mode
link_mode_preference: dynamic | static | prefer-dynamic | prefer-static

# Path to output directory where assets should be placed.
#
# This is also where `build_output.yaml` should be written.
#
# Remark: Avoid using the name "build_output.yaml" for an asset file, this is
# forbidden.
out_dir: <path/to/out_dir/>
out_dir: /absolute/path/to/out_dir/

# Name of the package that contains the `build.dart`
#
# Remark: This is entirely redundant since this is a config file specified to
# `build.dart`, and the author of `build.dart` probably knows the name of the
# package they are writing.
package_name: my_package_with_native_assets

# Path to root folder for the package that contains `build.dart`.
#
# This is useful if `build.dart` wishes to find source code files embedded in
# its own package and compile them to an asset.
package_root: $PUB_CACHE/hosted/.../my_package_with_native_assets/
#
# Note that this will be most likely a path in the pub cache when the package
# with a `build.dart` is a dependency of another package.
package_root: /absolute/path/to/my_package_with_native_assets

# Target architecture
#
# Combined with `target_os` this specifies the "target" for which assets
# should be built
target_architecture: x64
# should be built.
#
# Not provided on dry runs.
target_architecture: x64 | ia32 | arm | arm64 | riscv32 | riscv64

# Target operating system
#
# Combined with `target_architecture` this specifies the "target" for which
# assets should be built.
#
# Remark: If this appears confusing, that's because it is.
target_os: linux
target_os: android | ios | linux | macos | windows

# Version of this file.
version: 1.0.0
```
Expand All @@ -121,19 +136,47 @@ version: 1.0.0
Mapping from `assetId`s to files created by `build.dart`.

```yaml
timestamp: <date-time>
# The list of assets.
#
# In dry runs, must contain assets for each architecture for the requested os.
assets:
- id: <assetId>
- id: 'package:my_package_with_native_assets/src/foo.dart'
link_mode: dynamic | static | prefer-dynamic | prefer-static
path:
path_type: absolute | relative
uri: <out_dir/arbitrary_filename.whatever>
target: <target>
path_type: absolute | system | process | executable
# Only provided for path_type absolute and system.
#
# If path_type absolute: The absolute path to the file name.
#
# If path_type system: The path of the dynamic library as available on
# the target machine's PATH.
uri: /absolute/path/to/outdir/arbitrary_filename.whatever
target: linux_x64
...

# The files used by this build.
#
# If any of the files in [dependencies2] are modified after [timestamp], the
# build will be re-run.
#
# Not output on dry runs.
dependencies:
- <path/to/source-file.c>
- /absolute/path/to/my_package_with_native_assets/build.dart
...
metadata: {}

# The time the build this output is for started.
#
# Must be before any of the files in dependencies are read.
timestamp: 2024-01-02 17:05:35.000

# Metadata usable for build.dart of packages directly depending on this package.
#
# Not output in dry runs.
metadata:
# Key value pairs.
some_key: some_value

# Version of this file.
version: 1.0.0
```

Expand All @@ -146,26 +189,28 @@ For each `target` it maps from `assetId` to `url`
(with `urlKind` indicating if it's a relative or absolute path).

```yaml
# Version of this file.
format-version: [1, 0, 0]

# A mapping from target and assetId to an asset.
native-assets:
<target>:
<assetId>: [<urlKind>, <url>]
# A <target>.
linux_x64:
# An <assetId>.
: 'package:my_package_with_native_assets/src/foo.dart'
# A list of path_type and optionally a path.
- absolute | relative | system | process | executable
- <url> # Only provided for absolute, relative, and system path types.
...
```

This file is used by the embedded SDK to resolve `assetId`s when running in
development mode or build a deployable application (or standalone executable).

## Wishes to improve for v2



## Version 2: Proposal for a next iteration.

### Concepts

#### Asset
#### AssetId
#### ...



* Multiple asset types. Rename `Asset` to `NativeCodeAsset` and introduce `DataAsset`s.
* The path_types really only make sense for `link_mode: dynamic`.
* Fix the mismatch between `target` for output but `os` and `architecture` for config.
* Should the architecture field of native code assets be optional and be ommitted in dry runs?
* Introduce a `link.dart` protocol with a link input and link output.