- docs
- Reference
- Platforms
Platforms
A platform is one string that names an OS/architecture pair, optionally refined by CPU variant and required OS features, or any for platform-agnostic content. The same string is the --platform value, a key in ocx.lock’s per-platform digest map and a field in the build receipt ocx package create writes beside a bundle.
Grammar
Section titled “Grammar”A platform is the literal any, or an os/arch pair optionally refined by a CPU variant and a list of required OS features. os and arch are closed sets: adding a value to either requires an OCX release.
platform = "any" | specific ;specific = os "/" arch [ "/" variant ] [ "+" feature-list ] ;
os = "linux" | "darwin" | "windows" | "wasip1" | "wasip2" ;arch = "amd64" | "arm64" | "wasm" ;
variant = value ; (* e.g. "v7", "v8" *)feature-list = feature { "," feature } ;feature = value ; (* e.g. "libc.glibc" *)/introducesvariantand a single+introduces the comma-separated feature list, solinux/arm64/v8(a variant) is never confused with a+-list.anycarries no fields:any+libc.glibcandany/amd64are rejected as malformed.
| Example | Meaning |
|---|---|
linux/amd64 | Linux on x86-64, no refinements |
linux/arm/v7 | Linux on 32-bit ARM, variant v7 |
linux/amd64+libc.glibc | Linux on x86-64, requires the libc.glibc os.features tag |
linux/amd64+libc.glibc,libc.musl | Linux on x86-64, requires both glibc and musl (a dual-libc override) |
linux/arm64/v8+libc.glibc | Every field combined |
wasip1/wasm | A WebAssembly module targeting the WASI 0.1 ABI |
any | Platform-agnostic: no OS, architecture, or feature requirement |
Supported pairs
Section titled “Supported pairs”Only the pairs below parse, because a valid os and a valid arch do not always name an artifact (linux/wasm and wasip1/amd64 describe nothing). A pairing outside the list is refused while parsing, before resolution is attempted, and the refusal lists these pairs.
| Platform | Tier |
|---|---|
linux/amd64 | Native |
linux/arm64 | Native |
darwin/amd64 | Native |
darwin/arm64 | Native |
windows/amd64 | Native |
windows/arm64 | Native |
wasip1/wasm | Wasm |
wasip2/wasm | Wasm |
- Native: pairs OCX itself runs on and CI tests against. Host detection can produce any of them, and an omitted
--platformresolves to one. - Wasm: distribution labels only. No host reports
wasip1orwasip2, so they are reachable only through an explicit--platform. See publishing for wasm. - Surfaces: the one grammar for
--platform, the[tool.platforms]keys inocx.lockand theocx package createbuild receipt.
Escaping
Section titled “Escaping”variant and each feature value are registry-controlled strings, so the four structural characters are percent-escaped wherever they appear inside a value. Every other byte passes through verbatim, and ordinary values such as v7 and libc.glibc never need escaping.
| Character | Role | Escape |
|---|---|---|
% | escape introducer | %25 |
/ | os/arch/variant separator | %2F |
+ | feature-list introducer | %2B |
, | feature separator | %2C |
- A
%not followed by one of the four codes is a parse error. - The encoding round-trips: parsing a platform string and re-rendering it yields the identical string. It serves as both the CLI flag value and a
BTreeMapkey inocx.lock.
Compatibility
Section titled “Compatibility”OCX evaluates the directed relation is_compatible(required, offered) wherever a platform decision is made. Those places are resolving an install against an OCI Image Index, reading a locked digest out of ocx.lock and pinning a dependency during ocx package create.
The relation
Section titled “The relation”is_compatible(required, offered) reads “does offered satisfy required?”, where required is the detected host, an explicit --platform value or a lock lookup key and offered is an image-index child platform. The relation is not symmetric.
- An
anyoffer satisfies every requirement. - An
anyrequirement is satisfied only by ananyoffer. variantis strict equality, gated on the offer declaring a value. An offer that leavesvariantunset imposes no constraint.os.featuresinverts: every feature the offer declares must be present in the requirement’s host capabilities (offered.os_features ⊆ required.os_features), so an empty feature set on the offer matches every host.
| Required | Offered | Compatible? | Why |
|---|---|---|---|
linux/amd64 | linux/amd64 | Yes | Exact match, no refinements |
linux/amd64 | any | Yes | An any offer satisfies every requirement |
any | linux/amd64 | No | An any requirement is satisfied only by an any offer |
linux/arm64/v8 | linux/arm64 | Yes | Offer leaves variant unset, so it is unconstrained |
linux/arm64 | linux/arm64/v8 | No | Offer declares variant, required has none |
linux/amd64+libc.glibc | linux/amd64 | Yes | {} ⊆ {glibc}: a bare offer runs on a glibc host |
linux/amd64+libc.glibc | linux/amd64+libc.musl | No | {musl} ⊄ {glibc} |
linux/amd64+libc.glibc,libc.musl | linux/amd64+libc.glibc | Yes | {glibc} ⊆ {glibc,musl}: a dual-libc host runs a single-libc offer |
An empty os.features is a positive claim: the artifact demands nothing of the host, so every host matches. Omitting a feature is never neutral.
ocx package createenforces this for the libc namespace on Linux targets.- It reads the packaged binaries’ dynamic loader and refuses a platform whose
os.featuresdo not cover what they need.
See libc selection.
Scoring
Section titled “Scoring”When an image index offers several compatible manifests for one requirement, OCX picks the most specific, ranked lexicographically by these rules.
Specificoutranksany: alinux/amd64offer beats a co-presentanyoffer for alinux/amd64requirement.- Among
Specificoffers, more matched features win:linux/amd64+libc.glibcbeats a barelinux/amd64for a glibc host. - A tie is ambiguous and never guessed: OCX reports it with exit
65, and the caller disambiguates with an explicit--platform.