# marmot build (/docs/commands/build)

<!-- Generated by scripts/gen.mjs from `marmot build --help` and scripts/commands.mjs. Do not edit by hand. -->

Compile the named main package (default: the current directory) into an executable.

```text title="Usage"
marmot build [packages] [flags]
```

## Examples [#examples]

```sh
marmot build -o app ./cmd/app
marmot build -release ./cmd/app
marmot build -target linux/amd64 -o app-linux .
```

## Build modes [#build-modes]

`marmot build` has two modes. Dev builds (the default) compile each package on its own and
cache it, so a rebuild after an edit compiles little. `-release` optimizes the whole program
together at `-O3`: slower to build, smaller and faster to run. See [Build modes](/docs/build-modes).

## Common recipes [#common-recipes]

Smallest possible binary:

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

Build for Linux from a Mac:

```sh
marmot build -target linux/amd64 -o app-linux ./cmd/app
```

Profile guided optimization: build an instrumented binary, run it, then build again with the
merged profile:

```sh
marmot build -pgo-gen -o app ./cmd/app
./app                                   # writes marmot-<id>.profraw next to itself
llvm-profdata merge -o app.profdata marmot-*.profraw
marmot build -release -pgo app.profdata -o app ./cmd/app
```

Stop early and look at the compiler's output with `-emit mlir`, `-emit llvm` or `-emit obj`.

## Allocation report [#allocation-report]

`marmot build -allocs` prints, for each allocation in the main module that goes to the heap,
where it is, what it allocates and why it could not stay in the stack frame. `-allocs-all`
does the same for every package, the standard library included. Packages are compiled again
for the report, so the build cache does not hide them.

The reason is the first use that makes the value escape: returned, stored in a global or in
memory that outlives the function, passed to a call that may keep it, captured by a closure,
sent on a channel, converted to an interface, or too large for the frame. A heap allocation
inside a loop gets a note, since it happens once per iteration. Each site is a diagnostic with
code [M0111](/docs/diagnostics/codes/m0111).

`MARMOT_ALLOC_REPORT=FILE` writes the raw decisions of any build, stack sites included, one
JSON object per line:

```json
{"fn":"example.com/ad.newPoint","pos":"/src/ad/main.go:9:47","kind":"composite","type":"point","bytes":16,"where":"heap","reason":"returned from the function (line 9)","final":true}
```

`where` is `stack`, `heap`, `region` (in the caller's region, freed when the caller is done)
or `static`. `final` is false when the back end may still change the decision.

## The build cache [#the-build-cache]

Compiled packages are cached, so a rebuild with no changes does almost no work. The cache is
capped at 4 GB by default and old entries are removed automatically. Set `MARMOT_CACHE_MAX_MB`
to change the cap; `marmot cache` shows its size, `marmot cache trim` and `marmot cache clean`
shrink or remove it.

## Flags [#flags]

Flags take one dash or two: `-release` and `--release` are the same.

| Flag | Meaning |
| --- | --- |
| `-O string` | optimization level: 0, 1, 2, 3, s, z (default 2, 3 with -release) |
| `-allocs` | report the allocation sites of the main module: heap or stack, and why (rebuilds without the object cache) |
| `-allocs-all` | like -allocs, for every package |
| `-color string` | color in human output: auto, always or never (NO_COLOR turns auto off) (default "auto") |
| `-dialect string` | MLIR dialect level: llvm or go (default: go with -release, llvm otherwise; $MARMOT_DIALECT overrides) |
| `-emit string` | output kind: mlir, llvm, obj, exe (default "exe") |
| `-gc string` | garbage collector: precise or none (default "precise") |
| `-json` | machine readable output: JSON Lines on stderr (also $MARMOT_OUTPUT=json, and the default under coding agents) |
| `-nocache` | do not use the object cache |
| `-o string` | output file |
| `-pgo string` | profile guided optimization with this indexed profile (llvm-profdata merge -o FILE *.profraw) |
| `-pgo-gen` | build an instrumented binary that writes marmot-<id>.profraw next to itself |
| `-release` | release build: whole program optimization, -O3, all specializations (default from $MARMOT_RELEASE=1) |
| `-s` | omit the pc table (tracebacks without file:line) |
| `-tags string` | comma separated build tags |
| `-target string` | target triple (default: host) |
| `-trace string` | traceback detail of -release builds: full keeps the inlined frames of each call site apart (as dev builds do) |
| `-v` | print progress and timing |
| `-work` | print and keep the temporary work directory |
| `-x` | print the commands run |

## Full help [#full-help]

```text title="marmot build --help"
Compile the named main package (default: the current directory) into an executable.

Usage:
  marmot build [packages] [flags]

Examples:
marmot build -o app ./cmd/app
marmot build -release ./cmd/app
marmot build -target linux/amd64 -o app-linux .

Flags:
      --O string         optimization level: 0, 1, 2, 3, s, z (default 2, 3 with -release)
      --allocs           report the allocation sites of the main module: heap or stack, and why (rebuilds without the object cache)
      --allocs-all       like -allocs, for every package
      --color string     color in human output: auto, always or never (NO_COLOR turns auto off) (default "auto")
      --dialect string   MLIR dialect level: llvm or go (default: go with -release, llvm otherwise; $MARMOT_DIALECT overrides)
      --emit string      output kind: mlir, llvm, obj, exe (default "exe")
      --gc string        garbage collector: precise or none (default "precise")
  -h, --help             help for build
      --json             machine readable output: JSON Lines on stderr (also $MARMOT_OUTPUT=json, and the default under coding agents)
      --nocache          do not use the object cache
      --o string         output file
      --pgo string       profile guided optimization with this indexed profile (llvm-profdata merge -o FILE *.profraw)
      --pgo-gen          build an instrumented binary that writes marmot-<id>.profraw next to itself
      --release          release build: whole program optimization, -O3, all specializations (default from $MARMOT_RELEASE=1)
      --s                omit the pc table (tracebacks without file:line)
      --tags string      comma separated build tags
      --target string    target triple (default: host)
      --trace string     traceback detail of -release builds: full keeps the inlined frames of each call site apart (as dev builds do)
      --v                print progress and timing
      --work             print and keep the temporary work directory
      --x                print the commands run
```