CLI Reference

This page captures the currently implemented CLI surface (src/main.rs).

Global

  • --config <path>: Path to config file (default config.chariot).
  • --cache <path>: Path to cache directory (default .chariot-cache).
  • --rootfs-version <tag>: Override rootfs version tag (default baked into release).
  • --no-lockfile: Skip acquiring the cache lockfile (use with care).
  • -v, --verbose: Stream logs while building.
  • -o, --option key=value: Provide option values; can also be set via environment OPTION_<NAME>=value.

Subcommands

build

chariot build [OPTIONS] <recipe>...

  • --prefix <path>: Install prefix for package/custom recipes (/usr by default).
  • -j, --parallelism <n>: Parallelism for build scripts (defaults to host CPUs).
  • -w, --clean: Force a clean build directory for the targeted recipes.
  • --ignore-changes: Do not rebuild dependencies even if they changed.

exec

chariot exec [OPTIONS] [--] <command...>

  • --recipe-context <ns/name>: Run inside a recipe context with its dependencies mounted.
  • -p, --package <pkg>: Extra packages to install into the container.
  • -d, --dependency <ns/name>: Extra recipe dependencies to mount/install.
  • -e, --env KEY=VAL: Extra environment variables.
  • -m, --mount from=to[:ro]: Bind mount host paths (:ro for read-only).
  • --uid <id>, --gid <id>: Override user/group (default 1000/1000).
  • --rw: Make the container writable (read-only by default).
  • --cwd <path>: Set working directory inside the container.

purge

Remove recipes from cache that are no longer in the config.

list

List cached recipes with status, size, and last build timestamp.

wipe

chariot wipe <cache|rootfs|proc-cache|recipe [--all] [<recipe>...]>
Delete parts of the cache/rootfs. recipe accepts specific recipes or --all.

path

chariot path <ns/name> [--raw]
Print the install/output path for a recipe (raw path only with --raw).

hash

chariot hash <ns/name> [--raw]
Print the recipe hash (machine-readable with --raw).

logs

chariot logs <ns/name> [kind]
Print stage logs for a recipe (defaults to build.log).

completions

chariot completions <shell>
Generate shell completion scripts.

Configuration

Chariot uses a Domain-Specific Language (DSL) to describe its configuration. Configuration is typically stored in files with the .chariot extension (for example, config.chariot).

The elysium distro repo contains a set of recipes that can be used as a reference https://github.com/elysium-os/elysium.

Syntax

Whitespace

Whitespace separates other tokens but has no meaning beyond that.

Comment

There are two types of comments in chariot:

  • Single-line comments (starting with //).
```
// This is a single-line comment
```
  • Multi-line comments (starting with /* and ending with */).
```
/*
    This is a multi-line comment
*/
```

Identifier

  • Starts with a letter.
  • Continues with letter, number, _, ., -, +

String

  • Wrapped in double quotes.
  • Any characters are allowed except newline.

Code Block

  • Wrapped with language tags <lang></lang>.
    • Currently valid languages are:
      • sh, shell, bash
      • py, python
  • Note that if a closing tag (</lang>) is present but the language does not match, the tag will be interpreted as code.
```
<sh>
    echo "Hello world!"
</sh>
```

Directive

  • Starts with @.
  • Continues with letters, numbers, _, -.
```
@env
@option
@n0ne_3xistent-directive
```

Structure

There are two top level constructs:

Directives

The syntax for directives differs widely depending on the directive. The list of directives is available on this page along with examples for them.

Recipe Definition

Recipes definitions are structured as follows:

<recipe type>/<name> {
    <option key>: <option value>
}

Recipes options are explained in more detail here.

Directive

Directives are global configuration statements prefixed with @. They are processed before recipe definitions.

DirectiveDescriptionValueExample
importImport another chariot file.Path to a chariot file, relative to the current file. Supports globs.@import "recipes/*.chariot"
envDeclare a global environment variable.Key-value pair of environment variable name and value.@env "CLICOLOR_FORCE" = "1"
collectionCreate a collection of dependencies.Key-value pair of collection name and its dependencies.@collection autotools = [ tool/autoconf tool/automake ]
optionDeclare an option.Key-value pair of option name and valid values. Note that the first value is considered the default value.@option "buildtype" = [ "debug", "release" ]
global_pkgAdd global image packagesEither a package or a list of packages.@global_pkg build-essentials

Recipe

The function of a recipe is to describe how to deterministically fetch or build software. One recipe normally represents one application or library. There are four types of recipes in Chariot:

  • Source — describes how to fetch and prepare, normally software source code, files.
  • Tool — describes how to build software for use by other recipes.
  • Package — describes how to build software for the target operating system being bootstrapped.
  • Custom — describes how to build software for an unspecified/custom purpose.

Every recipe consists of its type, name, and a set of options. All recipes allow the following options:

NameDescription
optionsThe user defined options used by this recipe.
dependenciesList of dependencies.
See type specific options.

User Defined Options

User defined options are not to be confused with recipe options.

Users can define options using the option directive. The options can be set on the command line as described in the CLI section. Recipes can then "subscribe" to relevant options and can use the values passed to influence the recipe.

A recipe that has "subscribed" to an option will create distinct builds per option set. Note that recipes that depend on these recipes will also create distinct builds for those options.

For example, take this configuration:
```
@option "buildtype" = [ "debug", "release" ]

package/xyz {
    options: [ "buildtype" ]
    ...
}
```
The xyz package will have a distinct build for both debug and release build types.

Recipes can also choose the allowed values for chosen options. This functionality is useful when combined with the optional modifier on a dependency.

```
package/xyz {
    options: [ "buildtype" = [ "release" ] ]
    ...
}
```
In this case the xyz package will fail to build for any other values of buildtype than debug.

Dependency

A dependency is made up of modifiers, a namespace, and a name. It takes the form of:

<modifier(s)><namespace>/<name>

The valid namespaces are:

  • source refers to a source recipe.
  • tool refers to a tool recipe.
  • package refers to a package recipe.
  • custom refers to a custom recipe.
  • image refers to an image package.
  • collection refers to a collection. Collections are defined by the collection directive.

The valid modifiers are:

ModifierSymbolApplies ToDescription
Runtime*AllDependency is needed at runtime, not just build time.
Optional?AllAllow the recipe to build even if the dependency cannot be fulfilled. This can happen if the dependency does not support an option value.
Mutable%Source onlySource directory can be modified during build. Note that the modifications will not persist after the build.
Loose!AllDependency will not invalidate its parent.
Usage of the loose discouraged. It is hacky and only meant for use in severe circumstances.
```
%source/libtool
tool/autoconf
image/build-essential
```

Source Recipe

A source recipe describes how to fetch and prepare files (often source code) to be used by other recipes. In addition to the common options, source recipes allow the following options:

FieldDescriptionValue
typeThe source type."tar.gz" | "tar.xz" | "git" | "local"
See source type specific options.
patchA path to a patchfile, the path is relative to the root chariot file.String
regenerateA script to run on the source, explained further here.Code Block

Source Type

There are currently three methods supported:

  • "tar.gz" | "tar.xz"

    This method fetches an archive from an URL, checks a checksum against it, extracts it.

    Options:

    FieldDescriptionValue
    urlURL to a tar archive.String
    b2sumBlake2 checksum of the archive.String
    ```
    source/autoconf {
        type: "tar.gz"
        url: "https://ftp.gnu.org/gnu/autoconf/autoconf-2.72.tar.gz"
        b2sum: "48fff54704176cbf2642230229c628b75c43ef3f810c39eea40cae91dd02e1203d04a544407de96f9172419a94b952865909d969d9e9b6c10879a9d9aeea5ad0"
    }
    ```
    
  • "git"

    This method clones a repo and checks out a specific revision.

    Options:

    FieldDescriptionValue
    urlURL to a tar archive.String
    revisionGit revision to check out. Can be a commit hash, tag, branch.String
    ```
    source/chariot {
        type: "git"
        url: "https://github.com/elysium-os/chariot"
        revision: "ece5664ddc1c7b0111ae870af0fc2aaa3fdb4c98"
    }
    ```
    
    If the revision is set to a branch or tag, chariot will not check for updates.
    In order to update the source the recipe needs to be explicitly built again.
    
  • "local"

    This method copies a local directory.

    Options:

    FieldDescriptionValue
    urlPath to local directory, the path is relative to the root chariot file.String
    ```
    source/support {
        type: "local"
        url: "support"
    }
    ```
    
    Chariot will check every file/directory(s) timestamp (ctime) to determine whether it has changed.
    Although this is convenient it can result in significant performance issues for large sources because of the nature of recursing through every directory and checking timestamps.
    

Regenerate

The regenerate field allows for a script to modify the source before it is used by other recipes. The regenerate step runs after the patch is applied if one is specified. Regenerate follows the standard execution environment with the exception that the current working directory is set to the source root.

Tool / Package / Custom Recipe

The tool, package, and custom recipes all describe how to build software. Most of the functionality (and thus options) are shared between these recipe types, here are the options they share:

FieldDescriptionValue
configureA script to configure the recipe.CodeBlock
buildA script to build the recipe.CodeBlock
installA script to install the recipeCodeBlock
always_cleanWhether to always wipe the build cacheBoolean

Execution Environment

The execution environment for configure/build/install follows the the standard execution environment. In addition to the standard environment these codeblocks define the following environment variables:

  • PARALLELISM is set to the number of worker threads expected.
  • PREFIX is the installation prefix to use. For packages and custom recipes this is the configured prefix. For tools it is an internal one.
  • BUILD_DIR is set to the path of the build directory.
  • INSTALL_DIR is set to the path of the installation directory.

Tool Recipe

The tool recipe is for building tools (such as cross compiler etc) for the host (the chariot container). These tools can then be used as dependencies for other packages.

Package Recipe

The package recipe is for building packages for the target platform.

Custom Recipe

This recipe does not have a specific purpose it is there to fill needs that both package and tool recipes fail to.

Execution Environment

Chariot executes all scripts in its container. This means the execution environment is well defined. The root filesystem is a debian one. This rootfs is built using CI in the charon-rootfs repository.

Current Working Directory

The current working directory is set to the build directory.

Environment Variables

Chariot exposes several environment variables to all execution environments:

  • SOURCES_DIR is set to the path of a directory where source recipes are mounted. For example the shellscript $SOURCE_DIR/xyz would refer to a dependency source/xyz.
  • CUSTOM_DIR is set to the path of a directory where custom recipes are mounted. For example the shellscript $CUSTOM_DIR/xyz would refer to a dependency custom/xyz.
  • SYSROOT_DIR is set to the path of the sysroot. The sysroot is where all package recipes are installed. Unlike sources and customs these are not installed separately but installed together.
  • User defined options create environment variables in the format of OPTION_<option>. For example if there was a user defined option called buildtype an environment variable called OPTION_buildtype would be created. The value of these variables are naturally set to the value of the options.
  • All environment variables defined using the env directive.

Image Package

Image package refers to normal debian packages as chariot uses a debian rootfs. The image packages present are chosen by the recipe dependencies as well as the global package set.

Note that the global package set includes both some hardcoded packages described here and packages defined using the global_pkg directive.

Debian package search can be useful to find packages: https://packages.debian.org/index.

Overrides

Chariot provides a method to override source recipes with a local source. This is done by creating a .chariot-overrides file in the same directory as the root chariot config. Each line in this file represents one override in the format of <source recipe name>: <path to local source>.

```
gcc: ../gcc-source
binutils: ../binutils-source
```

The goal of overrides is to provide a convenient way to develop/modify sources without having to modify the recipe. It is recommended to gitignore or otherwise make sure the .chariot-overrides file is not published to version control.