# Target Triples

### Target Triples

One of Zig's main design goals is cross compilation.

A Zig compiler running on one machine can produce programs for many other operating systems and processors without installing a separate toolchain.

You can build a Linux executable on macOS. You can build for ARM on x86-64. You can build freestanding binaries for systems with no operating system at all.

The target is selected with a target triple.

A target triple describes three things:

```text
<architecture>-<operating system>-<abi>
```

For example:

```text
x86_64-linux-gnu
aarch64-macos-none
wasm32-freestanding-none
riscv64-linux-musl
```

The first field is the CPU architecture.

Common architectures include:

| Architecture | Meaning |
|---|---|
| `x86_64` | 64-bit x86 |
| `aarch64` | 64-bit ARM |
| `riscv64` | 64-bit RISC-V |
| `wasm32` | WebAssembly 32-bit |

The second field is the operating system.

| Operating system | Meaning |
|---|---|
| `linux` | Linux |
| `macos` | Apple macOS |
| `windows` | Microsoft Windows |
| `freestanding` | No operating system |

The third field is the ABI.

ABI means Application Binary Interface. It defines low-level conventions such as calling functions, object layout, and system libraries.

Common ABIs include:

| ABI | Meaning |
|---|---|
| `gnu` | glibc-based systems |
| `musl` | musl libc |
| `msvc` | Microsoft Visual C++ ABI |
| `none` | No libc or ABI runtime |

A native build uses the current machine automatically:

```sh
zig build-exe hello.zig
```

This produces an executable for the current operating system and processor.

To build for another target, use `-target`:

```sh
zig build-exe hello.zig -target x86_64-linux-gnu
```

On a macOS machine this produces a Linux executable.

To build for ARM Linux:

```sh
zig build-exe hello.zig -target aarch64-linux-musl
```

To build for WebAssembly:

```sh
zig build-exe hello.zig -target wasm32-freestanding-none
```

You can inspect supported targets with:

```sh
zig targets
```

The output is large. It includes architectures, operating systems, CPUs, features, and ABI combinations known to the compiler.

A small program can inspect its target at compile time.

```zig
const std = @import("std");
const builtin = @import("builtin");

pub fn main() void {
    std.debug.print("arch = {s}\n", .{@tagName(builtin.cpu.arch)});
    std.debug.print("os   = {s}\n", .{@tagName(builtin.os.tag)});
}
```

On Linux x86-64 the output might be:

```text
arch = x86_64
os   = linux
```

`builtin` contains information generated by the compiler for the current target.

`builtin.cpu.arch` is an enum value describing the CPU architecture.

`builtin.os.tag` is an enum value describing the operating system.

`@tagName` converts an enum tag into a string.

Since target information is available at compile time, programs can select code conditionally:

```zig
const builtin = @import("builtin");

pub fn main() void {
    if (builtin.os.tag == .windows) {
        windowsMain();
    } else {
        posixMain();
    }
}

fn windowsMain() void {}

fn posixMain() void {}
```

Only the selected branch is compiled for the target.

This is important in systems programming. Different systems often require different APIs, different calling conventions, or different executable formats.

Zig treats cross compilation as a normal operation, not a special case.

Exercise 17-1. Run `zig targets` and inspect the architectures supported by your compiler.

Exercise 17-2. Build the same program for two different operating systems.

Exercise 17-3. Print the target ABI with `builtin.abi`.

Exercise 17-4. Add target-specific code for Windows and Linux.

