nishikaze 0.3.1

Zephyr build system companion.
Documentation
nishikaze-0.3.1 has been yanked.

Nishikaze - The West Wind

crates.io docs.rs pre-commit pipeline Coverage Status

A CLI companion that orchestrates the whole lifecycle of Zephyr-based projects using a declarative config.

Index

Why?

Zephyr OS is a dream to work with. Zephyr's west, however, is a different story (at least for multi image sysbuild projects). Even though at first glance this meta tool looks exactly like west, you have the option to configure your project declaratively. I admit, when building a simple Zephyr app, you can just use pure CMake + ninja/make and configure everything in CMake. However, when building a multi-image app using sysbuild (e.g. updatehub OTA + mcuboot + app image) then you're stuck with passing a mile of args into west as you cannot configure it declaratively and cannot externally modify mcuboot's CMake config.

Features

  1. Manage the whole lifecycle of a Zephyr app - config, build, flash, sim runs
  2. Supports both simple Zephyr apps and multi-image apps with sysbuild
  3. Automatic Zephyr workspace detection
  4. Declarative config through kaze.toml @ project root
  5. Automatic project dir navigation (can be run from both project root or build dir)
  6. Automatically detects sysbuild projects and adjusts the build accordingly
  7. Supports multiple build profiles (can build multiple binaries for a specific app, useful for simulations or multiple board targets)
  8. SPDX BoM generation
  9. Zephyr workspace management

Installation

Install using cargo:

cargo install nishikaze

Requirements

As it's intended to manage Zephyr OS apps, you'll need a workspace setup with Zephyr OS and Zephyr SDK installed.

Usage

Usage: kaze [OPTIONS] <COMMAND>

Commands:
  init        Initializes project with kaze.toml
  boards      Lists available boards
  runners     Lists available runners
  profiles    Lists profiles configured in kaze.toml
  clean       Cleans build dir
  conf        Configure project
  build       Build binary
  run         Run simulation
  flash       Flash binary
  menuconfig  Run menuconfig
  bom         Generate SPDX `BoM`
  workspace   Workspace management
  help        Print this message or the help of the given subcommand(s)

Options:
  -c, --clean              Pre-clean the active build dir
  -a, --all                Run command for all configured profiles (overrides --profile/default)
  -p, --profile <PROFILE>  Select project profile defined in kaze.toml
  -b, --board <BOARD>      Zephyr OS board/target (overrides config)
  -r, --runner <RUNNER>    Zephyr OS flash runner (overrides config)
      --project <PROJECT>  Explicit project root
  -v, --verbose...         Verbosity (repeatable)
  -d, --dry-run            Dry run
  -h, --help               Print help
  -V, --version            Print version

Kaze config

kaze.toml is a declarative config located at the project root.

File discovery

kaze locates the project by:

  1. if --project <path> is given, use it
  2. else traverse upward from cwd until kaze.toml is found
  3. if run from a build directory, traverse upward to find the owning project root

Configuration layers and precedence

Resolved configuration is produced by merging layers in this order:

  1. Project config: <project>/kaze.toml
  2. CLI flags (--profile, --board, --runner, etc.)

Within the project config:

  • global values apply first
  • active profile values override global values
  • CLI overrides override both

Top-level schema overview

kaze.toml supports these configuration tables:

Table Description
[project] Global project configuration
[build] Build layout configuration
[zephyr] Zephyr workspace overrides
[bom] SPDX BoM generation config
[profile.<name>] Build profile

Recommended top-level tables:

  • [project] — defaults and profile selection
  • [build] — build directory rules

[project]

Key Type Default Summary
board string (none) Default Zephyr board
runner string (none) Default Zephyr runner
args table Per-phase args for the profile
default_profile string (none) Default profile name
name string (optional) Display name for the project (optional)

[profile.<name>]

Each profile is a partial override of the global project config.

Key Type Summary
board string Profile board
runner string Profile runner
args table Per-phase args for the profile

Example:

[profile.sim]
board = "native_sim"

[profile.prod]
board = "nucleo_f767zi"
runner = "openocd"

Profile selection rules

When profiles are defined:

  1. if --all arg provided -> all profiles selected (kaze runs selected command for all profiles)
  2. else if default_profile defined -> selects that profile
  3. else if --profile provided -> selects that profile
  4. else -> selects 1st profile defined in config file

When profiles are not defined:

  • profile selection is ignored and build is profile-less.

[build]

Key Type Default Summary
root string "build" Root build output directory
link_compile_commands bool true When profiles enabled, create root build/compile_commands.json symlink

Build output layout

  • Profile-less layout with no profiles configured: ./<build.root>/
  • Profiles layout with profiles configured: ./<build.root>/<profile>/

If building with profiles layout and link_compile_commands=true:

  • ./<build.root>/compile_commands.json is a symlink to the selected default/first profile’s compile_commands.json If building a sysbuild project and link_compile_commands=true:
  • ./<build.root>/compile_commands.json is a symlink to the project app image's compile_commands.json while perserving profile logic. Linking is skipped when building in profile-less layout or when link_compile_commands=false.

[zephyr]

Key Type Default Summary
workspace string auto-detect Zephyr workspace root
base string ${workspace}/zephyr Zephyr base directory
url string (none) Zephyr workspace manifest repository url
manifest string (none) Zephyr workspace local manifest file path

Auto-detection order (when not set):

  1. ZEPHYR_BASE environment variable
  2. find .west/ by traversing upward; if found, treat its parent as workspace

[project.args] and per-profile args

Args are configurable for phases:

  • conf (CMake configure)
  • build (Ninja)
  • flash (west flash / runner invocation)
  • run (simulator binary or fallback command)

Value forms:

  • string → treated as a single argument string (split behavior is implementation-defined; recommended to use arrays)
  • array of strings → preferred, exact args list

Example:

[project.args]
conf  = ["-DHG_TEST=ON"]
build = ["-j", "0"]
flash = ["--hex-file", "path/to/other.hex"]
run   = ["-flash_mount=seed/sd"]

[profile.sim.args]
run = ["-flash=seed/flash.bin", "-wait_uart"]

Arg merge order

For a given phase:

  1. global [project.args.<phase>]
  2. profile [profile.<name>.args.<phase>]
  3. CLI passthrough args after --

[bom]

Key Type Default Summary
build bool false Enables SPDX BoM generation
version string "2.2" SPDX version ("2.2" / "2.3")

If BoM generation is enabled, calling kaze bom will configure the project for BoM generation and generates SPDX BoM.

For sysbuild projects, you have to manually enable CONFIG_BUILD_OUTPUT_META=y for all sysbuild images in their respective Kconfigs.

Minimal config examples

1) Simple project (profile-less)

[project]
board = "nucleo_f767zi"
runner = "openocd"

2) Project with profiles

[project]
default_profile = "sim"

[profile.sim]
board = "native_sim"
runner = "native"

[profile.prod]
board = "nucleo_f767zi"
runner = "openocd"

3) Project with both profiles and extra args

[project]
# global extra args (applies to all profiles)
args = {
    build = ["-j", "0"],
    run = ["wait_uart"]
}

[profile.dev]
board = "native_sim"
runner = "native"
# dev profile specific extra args
args = {
    build = ["-DKAZE_TEST=ON"],
    run = ["-flash=seed/flash.bin"],
}

[profile.prod]
board = "nucleo_f767zi"
runner = "openocd"

Verbosity

Kaze emits user-facing logs prefixed with kaze: and uses colored logs if colour output is supported by the terminal.

Verbosity levels:

  • -v (1): quiet — no kaze logs, no command output
  • default / -vv (2): normal — kaze logs only; command output only on error
  • -vvv+ (3+): verbose — kaze logs + command output always

Environment variables:

  • KAZE_TESTING=1 suppresses logs (useful for tests).
  • KAZE_LOGS=1 re-enables logs during tests.

Typical workflow

Let's say you have a Zephyr app like this:

app
├── boards
   └── ...
├── include
   └── ...
├── src
   └── ...
├── CMakeLists.txt
├── LICENSE
├── prj.conf
└── README.md
  1. Initialize the project with a kaze.toml, either manually or use:
kaze init

This will create a kaze.toml file with some default settings:

app
├── boards
   └── ...
.
.
.
├── README.md
└── kaze.toml # <- kaze project config
# kaze.toml
#edit this configuration at your discretion
# Project config
[project]
board = "nucleo_f767zi"
runner = "openocd"
# args = { conf = [""], build = [""], run = [""], flash = [""] }
# default_profile = "sim"

# Build dir config
[build]
root = "build"

# Zephyr workspace override
# [zephyr]
# workspace = ""
# base = ""

# SPDX BoM generation
# [bom]
# build = true
# version = "2.2"

# Build profiles
# [profile.sim]
# board = "native_sim"
# runner = "native"
# args = { conf = [""], build = [""], run = [""], flash = [""] }

# [profile.prod]
# args = { conf = [""], build = [""], run = [""], flash = [""] }

  1. Configure and build the app:
kaze conf # <- optional step, as kaze build will configure project as well if not configured
kaze build
  1. Flash app
kaze flash

or if using one of Zephyr's simulator boards (native_sim or qemu boards) run simulation:

kaze run

Sysbuild projects

When building a sysbuild project the workflow looks pretty much the same:

  1. Init project with kaze config
  2. Config + build project
  3. Flash project images / run simulations

Sysbuild image selection

Sysbuild projects often consist of multiple standalone apps all built by sysbuild. Let's consider a sysbuild project consisting of the mcuboot bootloader and a simple app compatible with mcuboot (let's call it just app), so the project would look something like this:

app
├── boards
   └── ...
├── keys                # keys to sign our app and mcuboot
   └── ...
├── src
   └── ...
├── sysbuild            # additional sysbuild image configs
   └── mcuboot.conf    # in our case that is mcuboot
├── CMakeLists.txt      # app cmake config
├── LICENSE
├── prj.conf            # app kconfig
├── README.md
├── sysbuild.conf       # sysbuild config
└── kaze.toml           # already initialized with kaze config

This app, when built, would produce 2 separate images:

Image Description
app Our app compatible with mcuboot
mcuboot Mcuboot bootloader image

You can list available images with the --list option passed to run, flash, menuconfig and bom commands:

kaze flash --list

Output:

...
Available sysbuild images:

1: app
2: mcuboot

To select an image to flash/run use the --image option and pass in either the image name (e.g. app) or the image number (e.g. 1):

kaze flash --image app

or

kaze flash --image 1

If no image selected, kaze will default to the first non-bootloader image available.

SPDX BoM generation

To be able to generate SPDX BoMs, enable the [bom.build] option in kaze config. BoMs can only be genrated from built binaries pre-configured for BoM generation. If a binary is built without BoM support and you enable it, kaze automatically configures and rebuilds it when running kaze bom.

Workspace management

kaze is able to manage Zephyr workspaces through west.yml manifest files or repositories using west. To manage a zephyr workspace use the kaze workspace command:

Usage: kaze workspace <COMMAND>

Commands:
  init    Initialize workspace from a url or a manifest file
  update  Update workspace
  export  Exports workspace cmake package
  apply   Apply workspace by running init, update and export
  help    Print this message or the help of the given subcommand(s)

Options:
  -h, --help     Print help
  -V, --version  Print version

kaze supports all workspace topologies, given the [zephyr] table of kaze config is set up correctly.

🔔 Note: [zephyr.url] and [zephyr.manifest] settings are mutually exclusive.

Example app

For a simple example Zephyr app managed by kaze see kaze-demo

Similar projects

License

This project is licensed under either of:

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual licensed under the Apache-2.0 and MIT license, without any additional terms or conditions.

Development

See contribution guidelines.

TLDR:

Requires just to bootstrap all tools and configuration

cargo install just
just init # setup repo, install hooks and all required tools

To run:

just run

To test:

just test

Before committing work:

just pre-commit

To see all available commands:

just list

Upcomming features

  • Menuconfig
  • SPDX BoMs
  • Zephyr workspace management
  • Key generation for mcuboot bootloader and images
  • Manual image signing
  • Debugging apps
  • Project template generation (app, module, sysbuild project, ...)
  • Reference config values in string config options