Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.

Add book (WIP) #46

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
book
6 changes: 6 additions & 0 deletions docs/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[book]
authors = ["cassaundra"]
language = "en"
multilingual = false
src = "src"
title = "quake"
25 changes: 25 additions & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Summary

- [Introduction](./introduction.md)
- [Installation](./installation.md)
- [Guide](./guide.md)
- [Initializing a project](./guide/initializing.md)
- [Tasks](./guide/tasks.md)
- [Subtasks]()
- [Concurrency](./guide/concurrency.md)
- [File watching and reloading](./guide/watching.md)
- [Introspecting with `$task`]()
- [External scripts]()
- [Cookbook](./cookbook.md)
- [Basic projects]()
- [Configuration]()
- [Client and server]()
- [Generating subtasks]()
- [Converting C Makefile to quake]()
- [Reference](./reference.md)
- [Command-line usage]()
- [Nushell commands]()
- [Engine behavior]()
- [JSON specifications]()
- [Project metadata]()
- [Event output]()
3 changes: 3 additions & 0 deletions docs/src/cookbook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Cookbook

This chapter contains a variety of examples you might find useful when setting up a project.
6 changes: 6 additions & 0 deletions docs/src/guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Guide

This chapter gives a fairly comprehensive tour of quake's features.
It assumes no prior knowledge of [nushell](https://nushell.sh), but does assume the reader has at least some familiarity with basic scripting and shell usage.

If you want to follow along with any examples, you should first [install quake](./installation.md).
1 change: 1 addition & 0 deletions docs/src/guide/concurrency.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Concurrency
16 changes: 16 additions & 0 deletions docs/src/guide/initializing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Initializing a project

quake projects are defined by a `build.quake` or `build.quake.nu` file in the project's root directory.
This file is just a nushell script that's evaluated with a few extra commands added by quake.

You can verify that your project is configured correctly with `quake --dry-run`, or `quake list` (lists all tasks), and then run any of the defined tasks with `quake <task>`.

## Quick start

The easiest way to get up and running is just to add a simple task to your build script:

```sh
def-task build [] {
# shell commands for running your task go here
}
```
1 change: 1 addition & 0 deletions docs/src/guide/subtasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Subtasks
113 changes: 113 additions & 0 deletions docs/src/guide/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Tasks

Tasks are the basic building block of quake scripts, and are defined with the `def-task` command.
Tasks consist of a name, a signature, and two independently optional bodies (a declaration body and/or a run body).

The declaration body is used to declare metadata about the task (e.g. what other tasks it depends upon), while the run body contains the actual commands that make up the task.
Both bodies share the same signature and have the same arguments passed into them.

## Basic examples

Simple task:

```sh
def-task build [] {
cargo build
}
```

Task with a dependency:

```sh
def-task build [] {
cargo build --release
}

def-task bundle [] {
depends build
} {
cp target/release/foobar out/
}
```

Task with an argument:

```sh
def-task build [package: string] {
cargo build --package $package
}

# "pure" task with no run block
def-task --pure build-my-packages [] {
depends build my-package
depends build my-other-package
}
```

## `def-task` usage

```
Usage:
> def-task <name> <params> <run_body>
> def-task <name> <params> <decl_body> <run_body>
> def-task --pure <name> <params> <decl_body>

Parameters:
name <string>: task name
params <signature>: task body parameters
decl_body <closure()>: task declaration body
run_body <closure()>: task run body
```

## Task evaluation

When running a task, quake's evaluation model looks like this:

1. Evaluate the build script to gather definitions
2. Evaluate the declaration body of the given task (if it exists)
3. Recursively evaluate the declaration bodies of any and all of the task's dependencies
4. Evaluate run bodies in depth-first order until all have completed

This splitting of tasks into two phases allows the engine to reason about programatically-declared task metadata without actually having to run the tasks.
This enables a number of useful features which we will cover throughout this guide.

### Evaluating declaration bodies

Declaration bodies are evaluated inside of a special scope which enables the following commands:

- `depends <task> [args...]`: depend on another task with optional arguments
- `sources <files>`: declare files that this task consumes
- `produces <files>`: declare files that this task produces

This scope is carried through function calls.

## Sources and artifacts

As previously mentioned, tasks may declare the files that they consume (called *sources*) and the files they produce (called *artifacts*) in their declaration bodies, using the `sources` and `produces` commands respectively.

When both sources and artifacts are defined, quake will use that information to determine the "dirtiness" state of a task by comparing the most recent modification time in each set of files, and skip any tasks which are not dirty.

<div class="warning">
Be careful when declaring directories as sources and artifacts, as on most file systems the last modification time of directories is not updated when contents of files in that directory are updated.

When in doubt, use a glob pattern for the files you actually want to watch, preferably in addition to any directories in which those files are located as well, so new files (which do update the last modification time of the directory) are discovered.
</div>

### Basic example

For example:

```
def-task render-docs [] {
sources in.md
produces out.html
} {
pandoc --quiet -s -o out.html in.md
}
```

After we run this the first time (with `quake render-docs`), subsequent runs will result in the task being skipped, usually until either the source file is updated or the artifact is removed.

### Globbing

**TODO**
1 change: 1 addition & 0 deletions docs/src/guide/watching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# File watching and reloading
53 changes: 53 additions & 0 deletions docs/src/installation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Installation

Requirements:
- rustup (to install a nightly[^1] Rust toolchain)
- git (*optional*, can alternatively download sources via HTTP)
- [pandoc](https://pandoc.org) (*optional*, used to generate manpages)

As quake is in early development, the current recommended installation path is to simply:

```sh
# install the latest rust nightly toolchain
rustup install nightly

# clone the repository (subsequent updates should use `git pull`)
git clone https://github.com/quake-build/quake && cd quake

# choose where to output quake's binary and manpages
#
# this example requires ~/.local/bin to be in your PATH
INSTALL_DIR="$HOME/.local"

# bootstrap quake to build and install itself in a single step
#
# uncomment `--no-man` to skip manpages
cargo run --release -- install $INSTALL_DIR # --no-man

# clean up build artifacts (optional)
cargo clean
```

This installs the following:
- The binary `quake`
- man pages (see `man 1 quake`, `man 5 build.quake`)

You can verify your installation by running `quake --version`.

[^1]: quake will eventually transition into using the stable toolchain, but as it is considered under very much "alpha" software, it's convenient to depend on nightly for the time being.

## System-wide installation

Similar to to the above, except that we build as the user and install as root.

```sh
# ...

INSTALL_DIR=/usr/local # or /usr, etc.

# build as the current user
cargo run --release -- bundle-dist # --no-man

# install as root
sudo ./target/release/quake install-dist --dir $INSTALL_DIR # --no-man
```
45 changes: 45 additions & 0 deletions docs/src/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# What is quake?

quake is a cross-platform build system designed to make architecting large multilingual projects simpler.
quake picks up where other build systems leave off, as an end-to-end build system with modern design considerations that benefit everyone.

## Features

- Declarative build scripts, written in [nushell](https://nushell.sh)[^1]
- Composable and highly extensible task model
- Hot reloading support via file watchers with partial rebuilds
- Concurrent tasks; can be used for running a client/server simultaneously, in addition to any performance improvements
- Exposed JSON metadata modes, to enable third-party tooling integration
- Lazy evaluation of tasks and their declarations

[^1]: nushell is a powerful, strongly-typed cross-platform shell written in Rust. Its syntax is intuitive enough that learning it is *not* a prerequisite for understanding the scripts used in this book, but it's certainly worth learning as you go.

## A quick example

```sh
# read our Cargo.toml to (very naively) guess the binary name
let binary_name = open Cargo.toml | get package.name

def-task build [] {
# declare what files this task consumes
sources (glob src/**/*.rs)
sources [Cargo.toml, Cargo.lock]

# declare what files this task produces
produces target/release/$binary_name
} {
cargo build --release
}

def-task bundle [] {
depends build

# the same as before, but at a directory-level
sources static/
produces out/
} {
rm -rf out/
cp -r static out/
cp $task.dependencies.build.artifacts out/
}
```
3 changes: 3 additions & 0 deletions docs/src/reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Reference

This chapter contains various reference materials that also serve as quake's specification.