# Build modes (/docs/build-modes)

There are two modes, because fast rebuilds and deep optimization pull in opposite directions.

| Mode | Command | Use it for |
| --- | --- | --- |
| dev (default) | `marmot build` | Day to day work. Each package is compiled on its own and cached. |
| release | `marmot build -release` | Shipping. The whole program is optimized together. Builds take longer. |

<Diagram name="modes" alt="In dev mode each package becomes a cached object and the objects are linked; in release mode all packages are optimized as one whole program, then linked" />

## Dev builds [#dev-builds]

Each package is compiled separately and cached, so an edit recompiles little. Three things make
dev builds fast:

- **A fast code generator.** Dev builds write machine code directly, without LLVM. Its code is
  not optimized. `MARMOT_TIER0=0` uses LLVM instead: slower builds, faster code.
- **Background optimization.** After a dev build returns, the packages it compiled are
  compiled again with LLVM at `-O2` on idle cores, and later builds link those optimized
  objects. `MARMOT_TIER1=0` turns this off.
- **An incremental front end.** Rebuilds type check and compile only the changed packages and
  the packages that import them. `MARMOT_INCREMENTAL=0` turns it off.

## Release builds [#release-builds]

The optimizer sees the whole program, which allows inlining across packages and removal of
code that nothing uses. Release builds use `-O3` and every specialization. `MARMOT_RELEASE=1`
makes `-release` the default.

| Flag | Effect |
| --- | --- |
| `-O z` | Optimize for size: the smallest binary. |
| `-O s` | Optimize for size, less aggressively. |
| `-s` | Leave out file and line tables. Smaller, but panics show no source lines. |
| `-pgo-gen`, `-pgo file` | Profile guided optimization. |

The smallest possible binary:

```sh
marmot build -release -O z -s -o app ./cmd/app
```

## Numbers [#numbers]

| | dev | release | go |
| --- | --- | --- | --- |
| hello world with `println` | | 148 KB | 1.68 MB |
| hello world with `fmt.Println` | | 665 KB | 2.4 MB |
| run time, 43 programs | 1.4x faster with `MARMOT_TIER0=0` | 1.6x faster | 1.0x |

See [Benchmarks](/docs/benchmarks) for the method.

## Environment variables [#environment-variables]

| Variable | Meaning |
| --- | --- |
| `MARMOT_RELEASE=1` | Make `-release` the default. |
| `MARMOT_TIER0=0` | Dev builds use LLVM instead of the fast code generator. |
| `MARMOT_TIER1=0` | Turn off background optimization of dev builds. |
| `MARMOT_INCREMENTAL=0` | Turn off the incremental front end. |
| `MARMOT_CACHE_MAX_MB` | Size cap of the build cache in megabytes (default 4096). |
| `GOMAXPROCS`, `GOGC` | As in Go. |