This document defines the canonical platform representation and the mapping rules used by the platforms module.
A platform has six fields. Only Arch and OS are required.
| Field | Example | Description |
|---|---|---|
| Arch | x86_64 |
CPU architecture, using kernel/vendor conventions |
| OS | linux |
Operating system |
| Vendor | apple |
Hardware vendor (optional) |
| ABI | gnu |
ABI or C library variant (optional) |
| OSVersion | 11.0 |
Minimum OS version (optional, used by Python macOS) |
| LibCVersion | 2.17 |
Minimum libc version (optional, used by Python manylinux) |
Architecture names follow uname -m output where possible:
x86_64(notamd64, notx64)aarch64(notarm64)i686(notx86, noti386, not386)arm,riscv64,s390x,ppc64,ppc64le,loong64mips,mips64,mipsle,mips64le
OS names use lowercase kernel names:
linux,darwin,windows,freebsd,netbsd,openbsdandroid,ios,aix,solaris,dragonfly,illumos,plan9
Fourteen ecosystems are supported: go, node, rust, rubygems, python, debian, llvm, nuget, vcpkg, conan, homebrew, swift, kotlin, maven.
The mapping data lives in three JSON files under data/.
Maps each canonical arch to its name in each ecosystem. Values can be a string, an array of strings (first is preferred for formatting, all are recognized for parsing), or null (unsupported).
Same structure for OS names.
Pre-computed full platform strings for common arch/os/vendor/abi combinations. Each entry maps a canonical platform to the complete string each ecosystem uses. This handles cases where the string can't be composed mechanically from arch and OS alone, like Python's manylinux_2_17_x86_64 or RubyGems' use of arm64 for darwin but aarch64 for linux.
Only ecosystems that have a distinct string for the exact combination should appear in an entry. When an ecosystem can't distinguish between two entries (for example, Go produces linux/amd64 for both gnu and musl), the string should appear only in the default (gnu) entry.
- Look up the input string in the
platforms.jsonindex for the given ecosystem - If not found, decompose using ecosystem-specific splitting:
- Go: split on
/asos/arch - Node: split on
-asos-arch - Rust: split on
-asarch-vendor-os[-abi] - RubyGems: split on
-asarch-os[-abi] - Python: match against
manylinux_M_m_arch,musllinux_M_m_arch,macosx_M_m_arch,win_arch,win32, orlinux_arch - Debian: split on
-asarch-os-abi - LLVM: split on
-asarch-vendor-os[-abi] - NuGet: split on
-asos-archoros-musl-arch - vcpkg: split on
-asarch-os - Conan: split on
/or-asos/archoros-arch - Homebrew: split on
_asarch_codename(always macOS) - Swift: same as LLVM (
arch-vendor-os[-abi]) - Kotlin: split camelCase as
osArch(e.g.,linuxX64) - Maven: split on
-asos-arch
- Go: split on
- Resolve each component through the arch/OS reverse lookup indices
- Return
ErrUnknownPlatformif neither approach works
- Look up the Platform in
platforms.jsonbyarch/os/vendor/abikey, trying default vendor and ABI if not specified - If found, return the preferred string for the target ecosystem (applying version overrides for Python)
- If not found, compose from component mappings using ecosystem-specific rules:
- Missing vendor defaults to
applefor darwin/ios,pcfor windows,unknownotherwise - Missing ABI defaults to
gnufor linux,msvcfor windows
- Missing vendor defaults to
- Return
ErrNoMappingif the ecosystem doesn't support the arch or OS
Translate(from, to, s) parses from the source ecosystem, fills in default vendor and ABI, then formats for the target ecosystem. Normalize(eco, s) is Translate(eco, eco, s).
Some translations are lossy. Go and Node cannot express ABI, so translating x86_64-unknown-linux-musl from Rust to Go gives linux/amd64 with no way to recover the musl distinction. Python encodes OS and libc versions that other ecosystems ignore. Debian has no macOS or Windows support.