# Standard Library & Targets — Capabilities, Modules, and Cross-Build Boundaries

> The two-tier stdlib model: target-neutral modules (std.mem, std.codec, std.parse, std.json, std.io) available everywhere versus hosted-capability modules (std.fs, std.net, std.http, std.args, World.out) that are target-gated and rejected at compile time on non-host targets. How to inspect target facts before cross-building and choose the right build profile.

- Repository: vercel-labs/zerolang
- GitHub: https://github.com/vercel-labs/zerolang
- Human wiki: https://grok-wiki.com/public/wiki/vercel-labs-zerolang-9ab46b2a38e0
- Complete Markdown: https://grok-wiki.com/public/wiki/vercel-labs-zerolang-9ab46b2a38e0/llms-full.txt

## Source Files

- `skill-data/zero-stdlib.md`
- `skill-data/zero-builds.md`
- `native/zero-c/src/target.c`
- `native/zero-c/targets`
- `examples/std-http-request.0`
- `examples/std-path-io.0`

---

<details>
<summary>Relevant source files</summary>
The following files were used as context for generating this wiki page:

- [skill-data/zero-stdlib.md](skill-data/zero-stdlib.md)
- [skill-data/zero-builds.md](skill-data/zero-builds.md)
- [native/zero-c/src/target.c](native/zero-c/src/target.c)
- [native/zero-c/targets/targets.manifest](native/zero-c/targets/targets.manifest)
- [examples/std-http-request.0](examples/std-http-request.0)
- [examples/std-http-json.0](examples/std-http-json.0)
- [examples/std-path-io.0](examples/std-path-io.0)
- [examples/std-platform.0](examples/std-platform.0)
</details>

# Standard Library & Targets — Capabilities, Modules, and Cross-Build Boundaries

Zero's standard library is divided into two tiers: **target-neutral modules** that compile on every supported platform, and **hosted-capability modules** whose availability is gated by the target's declared capability set. This distinction is enforced at compile time — using a hosted module on a target that lacks the required capability is a hard build error, not a runtime failure. Understanding this boundary is essential for writing portable Zero programs and for making correct cross-build decisions.

This page covers all stdlib modules, the capability system that gates them, how target facts are stored and queried in the toolchain, how build profiles interact with targets, and the workflow for safely inspecting a target before committing to a cross-build.

---

## The Two-Tier Standard Library Model

### Tier 1 — Target-Neutral Modules

These modules have no dependency on host OS services. They operate purely over caller-owned memory and are available on every build target:

| Module | Responsibilities |
|---|---|
| `std.mem` | Spans, copy, fill, length, safe indexed `get`, fixed-buffer allocation, byte buffers, caller-owned vectors |
| `std.codec` | Byte reads, varint sizing, CRC helpers, byte checksums |
| `std.parse` | ASCII predicates, decimal integer parsers returning `Maybe<T>` |
| `std.json` | Explicit-buffer JSON parsing and string writing helpers |
| `std.io` | Buffered reader/writer surfaces over caller-owned storage |
| `std.time` | Duration construction and conversion helpers |
| `std.rand` | Explicit deterministic random sources |
| `std.crypto` | Small hash and byte-oriented crypto helpers |
| `std.path` | Path normalization, relative path resolution, basename/dirname/extension |

All of these follow the same invariant: no ambient heap, no global logger, no hidden system calls. When a function can fail or return nothing, it returns `Maybe<T>` rather than panicking.

Sources: [skill-data/zero-stdlib.md:19-28]()

### Tier 2 — Hosted-Capability Modules

These modules require an OS capability that not every build target provides. Using them on a target that lacks the relevant capability is rejected at compile time with a target diagnostic:

| Module | Required Capability | What It Provides |
|---|---|---|
| `std.args` | `args` | Process argument access |
| `std.env` | `env` | Process environment variables |
| `std.fs` | `fs` | Hosted filesystem handles (`Fs`, `owned<File>`) |
| `std.net` | `net` | Bootstrap network handles |
| `std.http` | `net` | HTTP request/response helpers built on `std.net` |
| `std.proc` | `proc` | Process spawning and exit-code inspection |
| `World.out`, `World.err` | `stdio` | Program output and error streams |

Sources: [skill-data/zero-stdlib.md:33-43]()

---

## The Capability System

### How Capabilities Are Declared

Every build target declares an explicit list of capabilities in `native/zero-c/targets/targets.manifest`. The manifest is TOML-like, with one `[[target]]` stanza per supported target:

```toml
[[target]]
name = "darwin-arm64"
capabilities = ["memory", "stdio", "args", "env", "fs", "time", "rand", "net", "proc"]

[[target]]
name = "linux-musl-arm64"
capabilities = ["memory", "stdio", "time", "rand"]
```

The full known capability vocabulary — as enumerated in the toolchain — is: `memory`, `stdio`, `args`, `env`, `fs`, `net`, `proc`, `time`, `rand`, `web`.

Sources: [native/zero-c/targets/targets.manifest:1-55](), [native/zero-c/src/target.c:299-310]()

### Per-Target Capability Matrix

| Target | memory | stdio | args | env | fs | net | proc | time | rand |
|---|---|---|---|---|---|---|---|---|---|
| `darwin-arm64` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| `darwin-x64` | ✓ | ✓ | — | — | ✓ | — | — | ✓ | ✓ |
| `linux-musl-x64` | ✓ | ✓ | ✓ | ✓ | ✓ | — | — | ✓ | ✓ |
| `linux-musl-arm64` | ✓ | ✓ | — | — | — | — | — | ✓ | ✓ |
| `linux-x64` | ✓ | ✓ | — | — | — | — | — | ✓ | ✓ |
| `linux-arm64` | ✓ | ✓ | — | — | — | — | — | ✓ | ✓ |
| `win32-x64.exe` | ✓ | ✓ | — | — | — | — | — | ✓ | ✓ |
| `win32-arm64.exe` | ✓ | ✓ | — | — | — | — | — | ✓ | ✓ |

Sources: [native/zero-c/targets/targets.manifest:1-112]()

### How the Toolchain Enforces Capabilities

The runtime function `z_target_has_capability` is the gatekeeper. It checks the target's `capabilities` string from the manifest. There is one special case: for the host target specifically, the five capability strings `args`, `env`, `fs`, `net`, and `proc` are additionally considered always available if the host reports itself as the active target — even before the manifest string is consulted. For all other targets, the manifest is authoritative.

```c
static bool host_capability_available(const char *capability) {
  return capability &&
         (strcmp(capability, "args") == 0 ||
          strcmp(capability, "env") == 0 ||
          strcmp(capability, "fs") == 0 ||
          strcmp(capability, "net") == 0 ||
          strcmp(capability, "proc") == 0);
}

bool z_target_has_capability(const ZTargetInfo *target, const char *capability) {
  if (z_target_is_host(target) && host_capability_available(capability)) return true;
  return target->capabilities && strstr(target->capabilities, capability) != NULL;
}
```

Sources: [native/zero-c/src/target.c:247-261]()

---

## Inspecting Target Facts Before Cross-Building

Before using a hosted module in code that will be cross-compiled, inspect the target's capability set explicitly. The toolchain provides three commands for this:

```sh
# List all known targets and their capabilities
zero targets

# Check whether a specific input compiles cleanly for the target
zero check --target linux-musl-x64 examples/memory-package

# Emit a full JSON fact report (capabilities, toolchain, libc, backend status)
zero graph --json --target linux-musl-x64 examples/memory-package
```

The JSON output includes `capabilityFacts` — an array of objects with `name`, `available` (boolean), and `source` fields — alongside toolchain, libc, sysroot, and direct-backend fields. Use this to verify all required capabilities before cross-building.

Sources: [skill-data/zero-stdlib.md:44-50](), [skill-data/zero-builds.md:48-54]()

### Sysroot Requirements

Some targets use `libcMode = "sysroot"`, meaning the toolchain needs a platform SDK rooted at the path given by a target-specific environment variable. The variable name is derived from the target's Zig target string, uppercased and with non-alphanumeric characters replaced by `_`, prefixed with `ZERO_SYSROOT_`. For example, `x86_64-linux-gnu` → `ZERO_SYSROOT_X86_64_LINUX_GNU`. If the sysroot is missing, the build fails explicitly with a diagnostic naming the missing variable.

Sources: [native/zero-c/src/target.c:285-296]()

---

## Build Profiles and Their Interaction With Targets

Profiles control optimization level, debug metadata, and artifact size, and are orthogonal to the target selection:

| Profile | Typical Use |
|---|---|
| `debug` | Maximum diagnostics, no optimization |
| `dev` | Fast builds for local iteration |
| `release-fast` | Speed-optimized release |
| `release-small` | Size-optimized release |
| `tiny` | Minimum-footprint artifacts |
| `audit` | Security-oriented build pass |

Profile selection does **not** expand the capability set. A `release-fast` build for `linux-musl-arm64` still has no `args`, `env`, `fs`, `net`, or `proc` capability.

```sh
zero build --profile release-small examples/hello.0
zero size --json --profile tiny examples/hello.0
```

The `zero size --json` command explains retained functions, sections, literals, runtime shims, and optimization hints — useful for understanding what hosted shims were linked and what can be trimmed.

Sources: [skill-data/zero-builds.md:58-67]()

---

## Code Patterns for Each Tier

### Target-Neutral: Memory and IO

Path normalization, buffered IO, and span copies are all caller-stack operations with no syscalls:

```zero
// examples/std-path-io.0
let mut path_buf: [32]u8 = [0, ...]
let normalized = std.path.normalize(path_buf, "src//./main.0/")
let mut reader_buf: [8]u8 = [0, ...]
let reader = std.io.bufferedReader(reader_buf)
```

Sources: [examples/std-path-io.0:3-9]()

### Hosted: Filesystem Access

File handles are explicit and owned. There is no ambient filesystem:

```zero
let fs = std.fs.host()
let mut file: owned<File> = check std.fs.createOrRaise(fs, ".zero/out/log.txt")
check std.fs.writeAllOrRaise(&mut file, std.mem.span("hello\n"))
```

Sources: [skill-data/zero-stdlib.md:88-93]()

### Hosted: HTTP with `net` Capability

`std.net` and `std.http` both require the `net` capability. The HTTP runtime is further restricted to host targets with an audited provider (currently libcurl on macOS and Linux ELF64):

```zero
// examples/std-http-request.0
let net = std.net.host()
let client = std.http.client(net)
let mut response: [512]u8 = [0_u8; 512]
let result = std.http.fetch(client, std.mem.span(maybe_request.value), response, std.time.ms(5000))
if std.http.resultOk(result) {
    check world.out.write("http request ok\n")
}
```

Sources: [examples/std-http-request.0:8-14]()

### Hosted: Platform Utilities

`std.proc`, `std.rand`, `std.crypto`, and `std.time` cover process spawning, randomness, hashing, and timing. Note that `std.time` and `std.rand` are available on all targets (they appear in every target's capability list), while `std.proc` requires the `proc` capability and is only available on `darwin-arm64` as of the current manifest:

```zero
// examples/std-platform.0
let status = std.proc.spawn("zero-noop")
let hash = std.crypto.hash32(std.mem.span("message"))
let mut rng = std.rand.seed(7_u32)
```

Sources: [examples/std-platform.0:9-11]()

---

## Capability Boundary Diagram

```text
┌────────────────────────────────────────────────────────────────┐
│                    Zero Standard Library                        │
│                                                                 │
│  ┌──────────────────────────────┐   ┌───────────────────────┐  │
│  │   TARGET-NEUTRAL (always OK) │   │ HOSTED (capability-   │  │
│  │                              │   │ gated, compile error  │  │
│  │  std.mem    std.codec        │   │ if target lacks cap)  │  │
│  │  std.parse  std.json         │   │                       │  │
│  │  std.io     std.path         │   │  std.args  → "args"   │  │
│  │  std.time   std.rand         │   │  std.env   → "env"    │  │
│  │  std.crypto                  │   │  std.fs    → "fs"     │  │
│  └──────────────────────────────┘   │  std.net   → "net"    │  │
│                                     │  std.http  → "net"    │  │
│                                     │  std.proc  → "proc"   │  │
│                                     │  World.out → "stdio"  │  │
│                                     └───────────────────────┘  │
│                                                                 │
│  Capability set is declared per-target in targets.manifest      │
│  and enforced by z_target_has_capability() at compile time.     │
└────────────────────────────────────────────────────────────────┘
```

---

## Cross-Build Decision Workflow

```text
1. Identify required stdlib modules for your program
      │
      ▼
2. Determine which capabilities they require
   (see table above: "Hosted-Capability Modules")
      │
      ▼
3. Run: zero targets
   → Verify the cross-target lists those capabilities
      │
      ├─ Capability present → proceed
      │
      └─ Capability absent  → refactor to target-neutral modules,
                               or restrict to a capable target
      │
      ▼
4. Run: zero check --target <target> <input>
   → Compile-time confirmation (no surprises at link time)
      │
      ▼
5. Run: zero build --profile <profile> --target <target> <input>
   → Check for sysroot env-var errors (libcMode = "sysroot" targets)
      │
      ▼
6. Optionally: zero ship --json --target <target> <input>
   → Produces artifact with size, hash, and target contract facts
```

---

## Failure Modes

| Failure | Cause | Fix |
|---|---|---|
| Compile error naming a hosted module | Target lacks the required capability | Use `zero targets` to find a capable target, or remove the hosted import |
| `BLD003` error | Old backend flag (`--emit c` or similar removed flag) | Remove the flag; use `--emit exe` or `--emit obj` |
| Missing `ZERO_SYSROOT_*` | Cross-target with `libcMode = "sysroot"` but env var unset | Set the correct sysroot path for the target |
| `http runtime unsupported` on cross-target | `std.http` requires host + `net` + direct ELF/Mach-O emitter | Run HTTP on the host target only; `darwin-arm64` and `linux-musl-x64` qualify |
| `zero check` passes but `zero build` fails | Sysroot missing or toolchain not found | Run `zero doctor --json` to enumerate host readiness |

Sources: [skill-data/zero-builds.md:80-86](), [native/zero-c/src/target.c:409-432]()

---

## Summary

Zero's standard library enforces a hard boundary between modules that are always available and modules that are gated by target capabilities declared in `native/zero-c/targets/targets.manifest`. Target-neutral modules (`std.mem`, `std.codec`, `std.parse`, `std.json`, `std.io`, `std.path`, `std.time`, `std.rand`, `std.crypto`) are safe to use in any cross-build. Hosted modules (`std.args`, `std.env`, `std.fs`, `std.net`, `std.http`, `std.proc`, `World.out`) are rejected at compile time on any target whose manifest entry does not include the required capability string. The correct cross-build workflow is: inspect target facts with `zero targets` and `zero check --json`, choose a profile appropriate to the deployment goal, and treat a clean `zero check` as the authoritative signal before committing to a `zero build` or `zero ship`.

Sources: [native/zero-c/src/target.c:256-261]()
