elixir_library
Elixir code compiled into cacheable bytecode and Erlang application metadata.
Description#
elixir_library compiles all target sources together and materializes the
bytecode plus Erlang Open Telecom Platform
application metadata as build outputs. Downstream Elixir targets receive the
compiled application on the code path, so tests and dependent libraries do not
compile the same project again.
Compiling the complete target together lets Elixir resolve relationships among macros, structs, protocols, and their implementations.
Once records Elixir compile metadata alongside bytecode. That metadata tracks
external resources, compile environment reads, modules that export
__mix_recompile__?/0, protocols, implementations, and compiler warnings. On
later builds, Once checks that metadata before reusing the result. Changes to a
dynamic input invalidate the cached compilation even when the source files did
not change.
Compile-time dependencies that must be loaded while compiling, such as macros
or structs used by another target, should be modeled as separate
elixir_library dependencies. Config and data globs are available to the
action and are included in cache keys. Config files are loaded before
compilation using Elixir's config reader so Application.compile_env sees the
same values the target records in compile metadata. Once does not run Mix's
compile task or require a Mix project during library compilation.
Library compilation does not require a Mix project file by default. Set
mix_config only when a project file should participate in cache keys.
Dependencies should come from deps, not from precompiled build directories
passed through compile_args; otherwise Once cannot cache or rebuild them at
target granularity.
Use mix_dependencies for third-party
packages selected by mix.exs and pinned by mix.lock. Its aggregate provider
implements the same elixir_app contract, so an elixir_library receives the
complete transitive bytecode path without knowing about Hex registry metadata.
Development Model#
Use once build <target> for compile feedback and once test <target> for
tests. When one source file changes, Once recompiles the target. When sources
and recorded dynamic inputs are unchanged, the compiled application can be
reused from the cache.
Targets that use dynamic compile inputs learn those inputs during compilation.
The first build after adding a new dynamic marker may compile locally instead of
using a remote cache entry so the next cache key includes the discovered inputs.
After metadata exists, @external_resource, Application.compile_env, and
__mix_recompile__?/0 participate in cache invalidation.
Phoenix projects should be represented as a graph instead of one broad target.
Macros or modules used across target boundaries should be separate
elixir_library targets. Third-party packages should also become Once-owned
dependency targets; pointing at precompiled build directories is only useful for
experiments because it puts compilation outside Once.
Attributes#
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
app_name | string | no | target name | Elixir application name; - and . are rewritten as _ when omitted |
mix_env | string | no | prod | Mix environment exported while compiling and testing, such as prod, test, or dev |
mix_config | string | no | empty | Optional package-relative Mix project file included in the library action key when the project still needs one |
version | string | no | 0.1.0 | Application version written to generated metadata |
description | string | no | "" | Application description written to generated metadata |
app_description | string | no | "" | Bazel-compatible alias used when description is omitted |
applications | list<string> | no | ["kernel", "stdlib", "elixir"] | Runtime applications written to generated metadata |
extra_apps | list<string> | no | [] | Bazel-compatible runtime applications appended to applications |
included_applications | list<string> | no | [] | Included applications written to generated metadata |
registered | list<string> | no | [] | Registered process names written to generated metadata |
consolidate_protocols | bool | no | true | Consolidate protocols after compilation and stage consolidated protocol bytecode into the application |
config | list<string> | no | ["config/**/*.exs"] | Config file globs included in the compile action key |
config_files | list<string> | no | [] | Buck-compatible alias for additional config file globs |
data | list<string> | no | [] | Data file globs available during compile |
priv | list<string> | no | [] | Priv file globs copied into the application priv output |
resources | list<string> | no | [] | Buck-compatible resource globs copied into the application priv output |
include | list<string> | no | ["include/**/*.hrl"] | Erlang header globs included in the compile action key |
docs | list<string> | no | [] | Buck-compatible documentation file globs included in the compile action key |
os_env | map<string, string> | no | {} | Buck-compatible environment variables exported before Elixir compile and test commands |
env_inherit | list<string> | no | [] | Host environment variable names inherited before explicit env values |
env | map<string, string> | no | {} | Environment variables exported before running Elixir compile and test commands |
compile_args | list<string> | no | [] | Additional arguments appended to elixirc |
elixirc_opts | list<string> | no | [] | Bazel-compatible alias for additional elixirc arguments |
Accepted but unsupported attributes: app_src, app_src_vsn, appup_src,
erl_opts, ez_deps,
extra_includes, extra_properties, include_src, mod, shell_configs,
and shell_libs. Non-empty values fail validation.
Dependency Edges#
| Edge | Accepts | Description |
|---|---|---|
deps | elixir_app | Elixir applications available on the compile path |
Providers#
The target emits elixir_app.
Provider Record#
| Field | Type | Meaning |
|---|---|---|
app_name | string | Elixir application name |
mix_env | string | Mix environment exported during compilation and tests |
ebin_dir | string | Directory containing compiled application bytecode and the generated application file |
priv_dir | string | Directory containing copied priv files |
include_dir | string | Directory containing copied Erlang header files |
compile_metadata | string | File containing dynamic compile metadata used for cache invalidation |
compile_warnings | string | File containing persisted compiler warning diagnostics |
transitive_elixir_apps | list<record> | This application plus dependency applications available to downstream Elixir targets |
transitive_sources | list<string> | Source files from this target and Elixir dependencies |
Capabilities#
| Capability | Output groups |
|---|---|
build | bytecode |
Example#
[[target]]
name = "greeting"
kind = "elixir_library"
srcs = ["lib/**/*.ex"]
[target.attrs]
app_name = "greeting"
Use elixir_test with a separate
mix_env = "test" library target when tests should reuse compiled bytecode.