Skip to content

Tools

Environment variables

Brine needs no environment variables: everything has a default. The ones below change how programs run (threads, the GPU, multi-process runs), how the compiler builds (backend, C compiler, WebAssembly, timing), and how the installers install. This is the complete list for Brine 0.4.0, plus the two WebAssembly variables, which come with WebAssembly support after 0.4.0.

Variable Read by Values Effect
BRINE_THREADS programs a number worker threads for par (default: all hardware threads)
BRINE_GPU programs auto, on, off when par constructs may run on a GPU
BRINE_GPU_LOG programs 1 print where each par construct ran, and why
BRINE_LEAKCHECK programs any print the number of live strings and arrays at exit
BRINE_RANK programs 0 to size − 1 this process’s rank in a world run
BRINE_WORLD_SIZE programs a number how many ranks there are
BRINE_PEERS programs host:port,... where every rank listens
BRINE tests a path set by brine test: the brine running the tests
BRINE_BACKEND compiler c, native force the C or the native backend
BRINE_CC compiler a command the C compiler (checked first)
CC compiler a command the C compiler, if BRINE_CC isn’t set
BRINE_TIMES compiler 1, 2 print how long each compiler phase takes
BRINE_DUMP_PTX compiler a file path write the program’s GPU module to this file
WASI_SDK_PATH compiler a path the wasi-sdk folder, for WebAssembly builds
BRINE_WASM_RUNNER compiler a command the WASI runtime brine run and brine test use for --target wasm (default: Node.js)
NO_COLOR compiler any no colors in --color auto mode
TMPDIR compiler, programs a path the temp directory on Linux and macOS
BRINE_VERSION installers 0.4.0 the version to install
BRINE_INSTALL installers a path where to install
BRINE_NO_MODIFY_PATH installers 1 don’t add Brine to PATH
BRINE_DOWNLOAD_URL installers a URL where to download releases from

“Programs” means every executable Brine builds: the variables are read by the runtime when the program runs, not when it’s compiled. The brine compiler is itself a Brine program, so the program variables also apply to it (see the note below).

The number of worker threads for par constructs. Unset, 0, a negative number or something that isn’t a number means one thread per hardware thread; the most is 1024.

Terminal window
BRINE_THREADS=4 target/release/sim
brine run --release --threads 4 # the same: brine sets BRINE_THREADS for the program

Results don’t depend on it: reductions combine in an order fixed by the number of elements, so BRINE_THREADS=1 and BRINE_THREADS=32 print the same bits. brine test runs each test with BRINE_THREADS=2. WebAssembly builds always use one thread and ignore it.

Whether par for, par [...] and par reductions may run on a GPU. See GPUs.

Value Effect
auto (default; also any value not below) the runtime measures each construct and uses the GPU when it expects that to be at least 25% faster, copies included
on, 1 use the GPU for every construct that can run there
off, 0 never use a GPU

The results are the same bits whichever side runs a construct.

Any value other than empty or 0 prints a line to stderr each time a par for, par [...] or par reduction runs: its location, kind, size, where it ran, how long it took, and why.

Terminal window
brine build --release gpu.br
BRINE_GPU_LOG=1 ./gpu
brine gpu: gpu.br:3:14 par map n=10000000 -> cpu 5.035 ms (faster on the CPU)
brine gpu: gpu.br:4:17 par reduction n=10000000 -> cpu 1.218 ms (faster on the CPU)
8.333332083333376e+19

With BRINE_GPU=off the reason reads (BRINE_GPU=off); a body that can’t run on a GPU says why (not GPU-eligible: ...).

When set (to any value, even 0), the program prints the number of strings and arrays still allocated when it exits. It should always be 0. See Debugging.

brine: 0 live objects at exit

These make a program one rank of a multi-process world run. brine run --ranks N sets all three for each process it starts, with every rank on 127.0.0.1. To run across machines, start the same executable on each machine and set them yourself:

Variable Value
BRINE_RANK this process’s rank, from 0 to BRINE_WORLD_SIZE - 1
BRINE_WORLD_SIZE the number of ranks
BRINE_PEERS host:port for every rank, in rank order, separated by commas; each rank listens on its own entry
Terminal window
# on host a
BRINE_RANK=0 BRINE_WORLD_SIZE=2 BRINE_PEERS=10.0.0.1:7000,10.0.0.2:7000 ./sim
# on host b
BRINE_RANK=1 BRINE_WORLD_SIZE=2 BRINE_PEERS=10.0.0.1:7000,10.0.0.2:7000 ./sim

All three must be set; otherwise, or when BRINE_WORLD_SIZE is 1 or less, the program runs as a single rank (world.size() == 1). An entry without a : stops the program with brine: invalid BRINE_PEERS entry '...'. A WebAssembly build runs as one rank: with BRINE_WORLD_SIZE above 1 it stops with brine: `world` programs can't run with more than one rank on WebAssembly. When every peer is 127.x.x.x or localhost, ranks listen on loopback only; otherwise they listen on every interface. A brine launch --hosts command that does this for you is on the roadmap.

brine test sets BRINE to the path of the brine executable running the tests, so a test can run the compiler (for example with run([getenv("BRINE").unwrap(), "check", "x.br"])).

Picks the code generator, overriding the default for the profile and platform.

Value Effect
c generate C and compile it with the system C compiler, for every profile
native use the native backend (x86-64 or AArch64) for every profile, --release included, where there is one; elsewhere C
unset native for dev and debug builds on x86-64 Windows/Linux and AArch64 Linux; C for --release and every other platform

A build with BRINE_BACKEND set goes to its own folder (target/dev-c/, target/release-native/, …), so it never replaces a default build’s executable:

Terminal window
BRINE_BACKEND=c brine build
Built hello v0.1.0 [dev] in 0.27s
Output target/dev-c/hello.exe

It’s meant for comparing backends and for debugging the compiler. BRINE_BACKEND=native with --release gives unoptimized native code, not a faster build.

The C compiler Brine uses to compile the runtime, to link, and for every C build. Brine checks BRINE_CC, then CC, then tries clang, gcc and cc on your PATH, in that order, and takes the first that runs. Empty values are skipped.

Terminal window
BRINE_CC=clang brine build --release

The value is one program (a name on PATH or a full path), not a command line: extra flags in it aren’t split off. brine doctor shows which compiler was found. Without one, builds fail with E0702 (brine check doesn’t need one).

Prints how long each phase of the compiler takes, to stderr.

Terminal window
BRINE_TIMES=1 brine build sum.br
parse 0.000s
check 0.000s
uniform 0.000s
verify 0.001s
lower 0.000s
x86-64 0.000s
link 0.084s
Built sum [dev] in 0.10s
Output sum.exe

C builds show emit C and cc (compiled/total units) instead of x86-64. With BRINE_TIMES=2, Brine also names every function the prover spends more than 20 ms on, which tells you where a requires or invariant would speed up checking. The end of that output when checking the compiler’s own source:

verify alloc_regs: 0.050s
verify forward: 0.027s
verify write_elf: 0.027s
verify 0.158s
Checked main in 0.38s — 1003 runtime checks proven unnecessary, 1633 remain (see --report)

BRINE_DUMP_PTX=file writes the program’s GPU module to file while building: PTX for NVIDIA GPUs, or Metal Shading Language source on macOS.

Terminal window
BRINE_DUMP_PTX=kernels.ptx brine build --release
kernels.ptx
// generated by brine
.version 6.0
.target sm_50
.address_size 64

These two are read when you build or run with --target wasm or --target web.

The folder of wasi-sdk, whose clang and C library Brine uses for WebAssembly builds. Brine looks for $WASI_SDK_PATH/bin/clang, then /opt/wasi-sdk/bin/clang. An empty value is skipped.

Terminal window
WASI_SDK_PATH=~/tools/wasi-sdk-34.0-x86_64-linux brine build --target web

Without it, WebAssembly builds fail with E0702 (no WebAssembly C toolchain found). Native builds don’t use it. brine doctor shows the clang it found.

The command brine run --target wasm and brine test --target wasm run a module with. Brine splits the value at spaces, then adds the module’s path and the program’s arguments. Unset or empty, Brine uses Node.js with a small node:wasi script.

Terminal window
BRINE_WASM_RUNNER="wasmtime run --dir=." brine run --target wasm

Give the runtime access to the current folder (--dir=. for wasmtime) if the program uses files. A command that can’t start fails with error: could not start <command>: program not found.

When NO_COLOR is set, --color auto (the default) prints no colors. --color always still does.

On Linux and macOS, the temp directory for single-file builds ($TMPDIR/brine-cache, else /tmp/brine-cache) and for os.temp_dir() in programs. On Windows, Brine uses the system temp folder (GetTempPath2W, usually %TEMP%).

The one-line installers (install.sh and install.ps1) read:

Variable Default Effect
BRINE_VERSION the latest release the version to install, like 0.4.0
BRINE_INSTALL ~/.brine where to install; the binary goes in $BRINE_INSTALL/bin
BRINE_NO_MODIFY_PATH unset when set, don’t add Brine to PATH (in your shell’s startup file, or the Windows user PATH)
BRINE_DOWNLOAD_URL GitHub releases where the release archives and SHA256SUMS are, for mirrors
Terminal window
curl -fsSL https://raw.githubusercontent.com/brinelang/brine/main/install.sh | BRINE_VERSION=0.4.0 sh
Terminal window
$env:BRINE_VERSION = '0.4.0'; irm https://raw.githubusercontent.com/brinelang/brine/main/install.ps1 | iex

The brine compiler is written in Brine, so it’s a Brine program like any other, and the program variables apply to it too. BRINE_THREADS limits the threads the compiler uses for parsing and proving. BRINE_LEAKCHECK and BRINE_GPU_LOG make brine run print the compiler’s own lines as well as your program’s:

Terminal window
BRINE_LEAKCHECK=1 brine run en.br
Built en [dev] in 0.10s
Running C:/Users/you/AppData/Local/Temp/brine-cache/7477652331a79471/dev/en.exe
Shape.Rect(w=2, h=3) Some(1) {"ann": 31, "bob": 27} (1, "two")
brine: 0 live objects at exit
brine: 0 live objects at exit

The first count is your program’s, the second the compiler’s. To see only your program’s, build it, then run the executable with the variable set.