Architecture Specifiers
=======================

## architecture specifiers for binaries
External binaries need to be compatible with a given Pd binary.
In order to identify externals that are compatible, *architecture specifiers* are used.

Each architecture specifier consists of a triplet `Operating System`, `CPU` and `floatsize`,
joined by dash (`-`), for example `Linux-amd64-32`
(Operating System is *Linux*, the CPU is *amd64* and the floatsize is *32*)

The `Operating System` and `CPU` specifiers define, whether a binary is loadable in principle
(by the means provided by a given OS installation).
The `floatsize` specifier is used to distinguish between precision flavours of Pd
(whether a binary is for single precision or double precision).


### OS specifiers

#### common OS specifiers

| OS        | description |
|-----------|-------------|
| `Darwin`  | the OS produced by Apple (macOS, OSX,...);<br/>*Darwin* is the name of the kernel of these systems |
| `Linux`   | the popular Open Source OS |
| `Windows` | the OS produced by Microsoft |


#### other OS specifiers

| OS        | description |
|-----------|-------------|
| `NetBSD`  | BSD-variant
| `FreeBSD` | BSD-variant
| `OpenBSD` | BSD-variant
| `Hurd`    | the GNU Operating System |
| `Solaris` | a Unix system |
| `Irix`    | a Unix system for SGI workstations |

### CPU specifiers

The CPU specifiers follow the [Debian architecture naming scheme](https://wiki.debian.org/ArchitectureSpecificsMemo).
They are generally all-lowercase and consist only of alphanumeric characters.

| CPU     | word size | endianness | description                                                       |
|---------|-----------|------------|-------------------------------------------------------------------|
| `amd64` | 64        | little     | 64bit AMD/Intel processors (aka `x86_64`)                         |
| `arm64` | 64        | little     | 64bit ARM processors (e.g. *Apple Silicon*, *Raspberry Pi 4*,...) |
| `i386`  | 32        | little     | 32bit AMD/Intel processors (aka `x86`)                            |
| `armv8` | 32        | little     | 32bit ARM processors (e.g. *Raspberry Pi 4*)                      |
| `armv7` | 32        | little     | 32bit ARM processors (e.g. *Raspberry Pi 2*)                      |
| `armv6` | 32        | little     | 32bit ARM processors (e.g. *Raspberry Pi zero*)                   |

#### compatible CPU specifiers

| CPU     | compatible with these CPUs |
|---------|----------------------------|
| `i686`  | `i586`
| `i586`  | `i386`
| `armv7` | `armv6`
| `armv6` | `armv5`
| `armv5` | `arm`

(e.g. a package for `Windows-i586-32` can only run on a Windows PC with a Pentium processor,
whereas a package for  `Windows-i386-32` can run on a Windows PC with either an i386 CPU or a Pentium processor)


#### deprecated CPU specifiers

Sometimes people use alternative names for CPUs.
While these should be handled gracefully by `deken`, it is best to avoid them and use the canonical names instead:

|deprecated CPU name | canonical CPU name |
|-------------|------------------|
| `PowerPC`   | `ppc`            |
| `x86_64`    | `amd64`          |
| `aarch64`   | `arm64`          |



#### other CPU specifiers

These are somewhat modern but CPUs (but probably see very few uses of Pd):

| CPU        | word size | endianness | description |
|------------|-----------|------------|-------------|
| `loong64`  | 64        | little     | Loongson processors
| `ppc`      | 32        | BIG        | PowerPC (rather old Apple computers)
| `ppc64`    | 64        | BIG        | PowerPC (slightly newer Apple computers)
| `ppc64el`  | 64        | little     | IBM Power8 & Power9
| `mipsn32`  | 32        | BIG        | MIPS with n32 ABI (e.g. newer SGIs)
| `riscv`    | 32        | little     | RISC-V (`RV32*`)
| `riscv64`  | 32        | little     | RISC-V (`RV64*`)
| `s390x`    | 64        | BIG        | IBM zSystems S/390x (mainframes)



The following are probably only used on historic machines long out of use
(and there are no known Pd installations on these systems)

| CPU        | word size | endianness | description |
|------------|-----------|------------|-------------|
| `sparc`    | 32        | BIG        |
| `s390`     | 32        | BIG        | IBM S/390 (old mainframes)
| `hppa`     | 64        | BIG        |
| `sh4`      | 32        | ??         | SuperH (SH4)
| `blackfin` | 32        |            |
| `avr`      | ??        |            |
| `x32`      | 32        | little     |
| `ia64`     | 64        | BIG        |
| `ia64el`   | 64        | little     |
| `m68k`     | 32        | BIG        | very old Apple computers
| `sparc64`  | 64        | BIG        |
| `alpha`    | 64        | BIG        | DEC Alpha
| `mips`     | 32        | BIG        | MIPS (e.g. old SGIs)
| `mipsel`   | 32        | little     | MIPS (Little Endian)
| `mips64`   | 64        | BIG        | MIPS (e.g. new SGIs)
| `mipso64`  | 64        | BIG        | MIPS with o32 ABI (probably unused)
| `mips64el` | 64        | little     | MIPS (Little Endian)


### floatsize specifiers


| floatsize | description |
|-----------|-------------|
| `32`      | single precision Pd
| `64`      | double precision Pd
| `0`       | precision agnostic (binaries can be loaded by a Pd running any precision, including - but not limited to - single and double precision)



## special architecture `Sources`

Packages that contain source-code to compile a specific library
use the pseudo architecture specifier `Sources`.

A package that only contains this pseudo architecture (e.g. `my_library[v0.1](Sources).dek`)
is not usable directly by Pd.

However, it is useful to allow people to re-compile the library (e.g. for a new architecture).

Depending on the license of the library, it might also be *required* to provide the source code.


## architecture specifier for non-binaries

Packages that can be used on any architecture where Pd runs on
(typically because they do not include any compiled objects)
are said to be *architecture independent*.

In this case the list architecture specifiers is left empty.


## merging architecture specifiers
Architectures are cumulative: If a library contains multiple architectures,
the architecture specifiers are appended to the list.

E.g. if a package contains both a `foo.dll` binary (Windows, i386, single precision)
and a file `foo.d_fat` (macOS, amd64 and arm64, single precision),
the architecture identifiers for the package are `Windows-i386-32`+`Darwin-amd64-32`+`Darwin-arm64-32`

If a package contains binaries (for a given OS/CPU combination) that are both
floatsize-specific (e.g. for double precision, e.g. `Linux-amd64-64`)
*and* floatsize-agnostic (e.g. `Linux-amd64-0`),
then the former shadows the latter, so the package will have
the architecture identifier(s) `Linux-amd64-64`.

If a package contains both architecture independent objects (e.g. abstractions)
*and* binary objects (e.g. a `Windows-i386-32` external)
the latter shadow the former, so the package will have
the architecture identifier(s) `Windows-i386-32`.

The only exception to this is, when *all* binary objects also have an architecture
independent counterpart (e.g. the library provides objects like
`[cartesian2polar]` both as optimized binaries for a few selected architectures and
(slower) fallback abstractions for the rest).
In this case the architecture specifiers should be omitted from the filename.
