Skip to content

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.

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

AttributeTypeRequiredDefaultDescription
app_namestringnotarget nameElixir application name; - and . are rewritten as _ when omitted
mix_envstringnoprodMix environment exported while compiling and testing, such as prod, test, or dev
mix_configstringnoemptyOptional package-relative Mix project file included in the library action key when the project still needs one
versionstringno0.1.0Application version written to generated metadata
descriptionstringno""Application description written to generated metadata
app_descriptionstringno""Bazel-compatible alias used when description is omitted
applicationslist<string>no["kernel", "stdlib", "elixir"]Runtime applications written to generated metadata
extra_appslist<string>no[]Bazel-compatible runtime applications appended to applications
included_applicationslist<string>no[]Included applications written to generated metadata
registeredlist<string>no[]Registered process names written to generated metadata
consolidate_protocolsboolnotrueConsolidate protocols after compilation and stage consolidated protocol bytecode into the application
configlist<string>no["config/**/*.exs"]Config file globs included in the compile action key
config_fileslist<string>no[]Buck-compatible alias for additional config file globs
datalist<string>no[]Data file globs available during compile
privlist<string>no[]Priv file globs copied into the application priv output
resourceslist<string>no[]Buck-compatible resource globs copied into the application priv output
includelist<string>no["include/**/*.hrl"]Erlang header globs included in the compile action key
docslist<string>no[]Buck-compatible documentation file globs included in the compile action key
os_envmap<string, string>no{}Buck-compatible environment variables exported before Elixir compile and test commands
env_inheritlist<string>no[]Host environment variable names inherited before explicit env values
envmap<string, string>no{}Environment variables exported before running Elixir compile and test commands
compile_argslist<string>no[]Additional arguments appended to elixirc
elixirc_optslist<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

EdgeAcceptsDescription
depselixir_appElixir applications available on the compile path

Providers

The target emits elixir_app.

Provider Record

FieldTypeMeaning
app_namestringElixir application name
mix_envstringMix environment exported during compilation and tests
ebin_dirstringDirectory containing compiled application bytecode and the generated application file
priv_dirstringDirectory containing copied priv files
compile_metadatastringFile containing dynamic compile metadata used for cache invalidation
compile_warningsstringFile containing persisted compiler warning diagnostics
transitive_elixir_appslist<record>This application plus dependency applications available to downstream Elixir targets
transitive_sourceslist<string>Source files from this target and Elixir dependencies

Capabilities

CapabilityOutput groups
buildbytecode

Example

toml
[[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.

Released under an open-source license.