Version 1: As of 2024-01-24 implemented behind --enable-experiment=native-assets
An asset is data which is accessible from a Dart or Flutter application. To retrieve an asset at runtime, we associate with it a string as a unique identifier, the assetId
. There are several example types of assets:
An application is compiled to run on a certain target OS and architecture. If different targets require different assets, the package developer must specify which asset to bundle for which target.
An asset has different ways of being accessible in the final application. It is either brought in “manually” by having the package developer specify a path of the asset on the current system, it can be part of the Dart or Flutter SDK, or it can be already present in the target system. If the asset is bundled “manually”, the Dart or Flutter SDK will take care of copying the asset from its specified location on the current system into the application bundle.
Assets are also called “native assets” to differentiate them from the Dart code also bundled with an application.
An asset must have a string identifier called assetId
. Dart code that uses an asset, references the asset using this assetId
.
A package must prefix all assetId
s it defines with: package:<package>/
, <package>
being the current package‘s name. This ensures assets don’t conflict between packages.
Additionally, the convention is that an asset referenced from lib/src/foo.dart
in package:foo
has the assetId
'package:foo/src/foo.dart'
.
A target specifies the operating system and architecture of the targeted platform of the application.
build.dart
Any package which needs to access assets at runtime must define a build.dart
script to specify these assets. If there are assets in a package which are not shipped as part of Dart or Flutter and also not present on the target system by default, those assets will be bundled into the final application by the Dart or Flutter SDK automatically. The build.dart
script takes as input information such as the target OS and architecture in a build_config.yaml
file, and returns as output a list of assets which can be accessed at runtime in a build_output.yaml
file.
build_config.yaml
This is the structure of the input to a build.dart
script.
# Build in dry-run mode. # # 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 # 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: /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. # # 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. # # 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. target_os: android | ios | linux | macos | windows # Schema version of this file. version: 1.0.0
build_output.yaml
This file is the output from running a build.dart
script, and contains the list of assets to be bundled into the application.
# The list of assets. # # In dry runs, must contain assets for each architecture for the requested os. assets: - id: 'package:my_package_with_native_assets/src/foo.dart' link_mode: dynamic | static | prefer-dynamic | prefer-static path: 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 on the # current machine. # # 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 [dependencies] are modified after [timestamp], the # build will be re-run. # # Not output on dry runs. dependencies: - /absolute/path/to/my_package_with_native_assets/build.dart ... # 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 # Schema version of this file. version: 1.0.0
build.dart
The input is passed as a absolute path to a YAML file build_config.yaml
encoding the input information as follows:
$ dart build.dart --config <build_config.yaml>
The Dart and Flutter SDK invoke build.dart
of all packages in the transitive dependencies and pass a build_config.yaml
as the --config
option.
If not in dry_run
mode, the build.dart
file MUST:
build_config.yaml
file,build_config.yaml
, if not already existing.out_dir
that was provided by build_config.yaml
.build_output.yaml
.build_output.yaml
into the directory at out_dir
.assetId
s to assets previously written into out_dir
.assetId
depending on characteristics like target
, link_mode
, etc.dry_run
is set to true in the build configuration, the list of assets must be output, but the asset files must not be written. The asset file urls are expected to refer to non-existing files.Notes:
out_dir
is irrelevant, because in Dart code the asset will only be referenced by its assetId
.dry_run
is set to true in the build configuration, then the actual creation and writing of assets can be skipped, as long as the assets are still listed in the build_output.yaml
..dart_tool/native_assets.yaml
This is not part of the build.dart protocol.
This file is internal to the Dart SDK and Flutter SDK. It produced by native_asset_builder
(as embedded in the SDKs). For each target
it maps from assetId
to a path type with an optional path.
These paths are used to resolve @Native() external
functions in Dart code.
The path types in this file are as follows:
absolute
paths are absolute paths on the system where the Dart executable is running. This path type is used when running in JIT mode on a developers' host machine, or in an Android app where the root path is the Android bundle.relative
paths are relative to the kernel or aot snapshot. This path type is used for shipping native assets in a directory together with a kernelsnapshot, aotsnapshot, or standalone executable (dartaotruntime+aotsnapshot).system
paths are expected to resolve on the target machine PATH.process
“paths” have no path, symbols are resolved in the current process.executable
“paths” have no path, symbols are resolved in the current executable.# Schema version of this file. format-version: [1, 0, 0] # A mapping from target and assetId to an asset. native-assets: # 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).
Asset
to NativeCodeAsset
and introduce DataAsset
s.link_mode: dynamic
.target
for output but os
and architecture
for config.link.dart
protocol with a link input and link output.