Using Want

This section will get you up and running with Want.

Most of the time you should run want build. This command is suitable to use as a pre-merge check. It will build all the targets in the current module. It does not and cannot perform publishing or other side effects.

Creating a Want Module

Want operates on Modules. A Module is just a filesystem tree with a file named WANT at its root. The WANT file holds module level configuration, and its presence is what tells Want that a directory is meant to be built.

To start a new module, run want init in your project's root. It writes a WANT file with the default module config — the want standard library as a dependency — and a default .wantignore:

.deps = [
	{"want", \(_: Ctx) FS LATEST},
]

See Module Files for what the WANT file can contain, and how the sibling .wantignore file controls which paths are imported.

Creating a Build Target

Want calls the things that you, the user, want, but don't yet have, and need to build, Targets.

A target is declared by a file ending in .want. Create a file named hello.txt.want at the root of your module, and fill it with the following:

build = (#import "want:build")
paths = (#import "want:build/paths")

.input = [
    (paths.unit "./input.txt")
]
.do = \(ctx: build.Ctx) build.FS {
    (build.pick ctx.jobs ctx.input "input.txt")
}

The file declares two things: the module paths the build reads (.input), and the computation that produces the output (.do). Here do simply picks the input file input.txt out of the target's input tree and returns it.

Create input.txt next to it containing Hello World!, then run

$ want cat hello.txt
Hello World!

The unit file hello.txt.want produces the output path hello.txt (its file name minus the .want extension), and want cat reads that file out of the build output.

Inspecting the Build Output

Normally cat hello.txt would print the source file, but want cat reads from the build output, while the regular cat reads from the regular filesystem, which is the build input.

Want organizes build targets into an output filesystem. This filesystem only exists virtually, within Want, but it can be inspected using UNIX-like tools (ls and cat).

want ls <path> will list the contents of a tree in the build output. Compare this to the output of regular ls.

want serve-http <addr> builds the output and serves it as a read-only HTTP file tree (for example want serve-http 127.0.0.1:8080): directories render as an index of links, and files are written with a content type guessed from their extension. Stop it with Ctrl-C.

This simple translation of inputs to outputs is what makes Want so easy to use and reason about. You will never find yourself in a situation where you don't know when/how/where a Target is being computed.

Armed with just want ls, want cat, and want build, you can get pretty far. To learn more about what you can build with Want, read the Build Configuration section.

Publishing and Secrets

A unit file may export an optional .sink proc: the side effect to run after the build is green. Sinks do not run in a normal build; want build --publish runs them. A sink belongs to its target, consumes the target's output as ctx.input, and reaches the outside world through the job port and the capabilities in build.SinkCtx.

Secrets reach a sink through ctx.secrets, a list of ports in the order the WANT's .secrets grants name them. Supply them on the command line:

# one raw secret
want build --publish --secret mySecret:/path/to/my_secret.txt
# or one spore map carrying several named values
want build --publish --secrets cloudflare:~/.config/want/cloudflare.sp
want build --publish --secrets github:~/.config/want/github.sp

Only the targets the build query names directly are published; a target pulled in to satisfy a dependency is built but its sink does not run. A publish build fails if a directly queried target (or the sink that will run for it) is granted a secret that was not supplied. See Module Files for the .secrets grant syntax.