From 3a22fedb719762165e6e87129c96a7983f0f8a99 Mon Sep 17 00:00:00 2001
From: urob <978080+urob@users.noreply.github.com>
Date: Thu, 8 Aug 2024 13:30:56 -0400
Subject: [PATCH] Document local build environment
---
Justfile | 8 ++--
readme.md | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 133 insertions(+), 9 deletions(-)
diff --git a/Justfile b/Justfile
index d096d3e..353b960 100644
--- a/Justfile
+++ b/Justfile
@@ -40,14 +40,14 @@ _parse_targets $expr:
echo "$(yq -r "$filter" build.yaml | grep -i "${expr/#all/.}")"
# build firmware for single board + shield combination
-_build $board $shield *args:
+_build $board $shield *west_args:
#!/usr/bin/env bash
set -euo pipefail
artifact="${shield:+$shield-}${board}"
build_dir="{{ build / '$artifact' }}"
echo "Building firmware for $artifact..."
- west build -s zmk/app -d "$build_dir" -b $board {{ args }} -- \
+ west build -s zmk/app -d "$build_dir" -b $board {{ west_args }} -- \
-DZMK_CONFIG="{{ config }}" ${shield:+-DSHIELD="$shield"}
if [[ -f "$build_dir/zephyr/zmk.uf2" ]]; then
@@ -57,7 +57,7 @@ _build $board $shield *args:
fi
# build firmware for matching targets
-build expr *args: _auto-conf
+build expr *west_args: _auto-conf
#!/usr/bin/env bash
set -euo pipefail
targets=$(just _parse_targets {{ expr }})
@@ -66,7 +66,7 @@ build expr *args: _auto-conf
echo "$targets" | while IFS=, read -r board shield; do
echo "board: $board"
echo "shield: $shield"
- just _build "$board" "$shield" {{ args }}
+ just _build "$board" "$shield" {{ west_args }}
done
# clear build cache and artifacts
diff --git a/readme.md b/readme.md
index 618e3fc..85d044a 100644
--- a/readme.md
+++ b/readme.md
@@ -10,7 +10,7 @@ compatible with Zephyr 3.0 is available
## Highlights
-- clean keymap + unicode setup using helper macros from
+- simple keymap configuration using helper macros from
[zmk-helpers](https://github.com/urob/zmk-helpers)
- the base keymap and combo setup are independent of the physical location of
keys and are re-used for multiple keyboards. The configuration is fit onto
@@ -28,10 +28,8 @@ compatible with Zephyr 3.0 is available
space → sticky-shift
- "Greek" layer for mathematical typesetting (activated as sticky-layer via a
combo)
-- modified Github Actions workflow that recognizes git-submodules
-- automated
- [build-scripts](https://github.com/urob/zmk-config/tree/main/scripts#readme)
- for local and Docker-based building (independently of VS Code)
+- nix-based [local build environment](#local-development-workspace) -- simply
+ `cd` into your workspace and start building without any setup

@@ -260,6 +258,126 @@ haven't yet tried placing alphas on combos, I am currently experimenting with a
`repeat` combo on my home row that I use to reduce SFUs when typing
double-letter words.
+## Local development workspace
+
+I streamline my local build process using `nix`, `direnv` and `just`. This
+automatically sets up a virtual development environment with `west`, the
+`zephyr-sdk` and all its dependencies when `cd`-ing into the ZMK-workspace. The
+environment is _completely isolated_ and won't pollute your system.
+
+### Setup
+
+#### Pre-requisites
+
+1. Install the `nix` package manager:
+
+ ```bash
+ # Install Nix with flake support enabled
+ curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix |
+ sh -s -- install --no-confirm
+
+ # Start nix daemon without reloading shell
+ . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
+ ```
+
+2. Install [`just`](https://github.com/casey/just) and
+ [`direnv`](https://direnv.net/) (and optionally
+ [`nix-direnv`](https://github.com/nix-community/nix-direnv)) using your
+ package manager of choice. E.g., using the `nix` package manager that we just
+ installed[^5]:
+
+ ```
+ nix profile install nixpkgs#just nixpkgs#direnv nixpkgs#nix-direnv
+ ```
+
+3. Set up the `direnv` [shell-hook](https://direnv.net/docs/hook.html) for your
+ shell. E.g., for `bash`:
+
+ ```bash
+ # Install the shell-hook
+ echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
+
+ # Optionally: Activate nix-direnv (if installed in the previous step)
+ echo 'source $HOME/.nix-profile/share/nix-direnv/direnvrc' >> ~/.config/direnv/direnvrc
+
+ # Source the bashrc to activate the hook (or start a new shell)
+ source ~/.bashrc
+ ```
+
+#### Set up the workspace
+
+1. Clone _your fork_ of this repository. I like to name it `zmk-workspace` as it
+ will be the toplevel of the development environment.
+ ```bash
+ # Replace `urob` with your username
+ git clone https://github.com/urob/zmk-config zmk-workspace
+ ```
+2. Enter the workspace and set up the environment.
+
+ ```bash
+ # This automatically sets up and activates a virtual shell with the Zephyr toolchain.
+ # This takes a while when entering the workspace for the first time.
+ cd zmk-workspace
+
+ # Initialize the Zephyr workspace and pull in the ZMK dependencies
+ # (same as `west init -l config && west update && west zephyr-export`)
+ just init
+ ```
+
+### Usage
+
+After following the steps above your workspace should look like this:
+
+```bash
+zmk-workspace
+├── config
+├── firmware (created after building)
+├── modules
+│ ├── auto-layer
+│ ├── helpers
+│ └── tri-state
+└── zmk
+ └── ...
+```
+
+#### Building the firmware
+
+To build the firmware, simply type `just build all` from anywhere within the
+workspace. This will parse `build.yaml` and build the firmware for all board and
+shield combinations listed there.
+
+To only build the firmware for a specific target, use `just build `.
+This will build the firmware for all matching board and shield combinations. For
+instance, to build the firmware for my Corneish Zen, I can type
+`just build zen`, which builds both `corneish_zen_v2_left` and
+`corneish_zen_v2_right`. (`just list` shows all valid build targets.)
+
+Additional arguments to `just build` are passed on to `west`. For instance, a
+pristine build can be triggered with `just build all -p`.
+
+(For this particular example, there is also a `just clean` recipe, which clears
+the build cache. To list all available recipes, type `just`.)
+
+#### Hacking the firmware
+
+To make changes to the ZMK source or any of the modules, simply edit the files
+or use `git` to pull in changes.
+
+To switch to any remote branches or tags, use `git fetch` inside a module
+directory to make the remote refs locally available. Then switch to the desired
+branch with `git checkout ` as usual. You may also want to register
+additional remotes to work with or consider making them the default in
+`config/west.yml`.
+
+#### Updating the build environment
+
+To update the ZMK dependencies, use `just update`. This will pull in the latest
+version of ZMK and all modules specified in `config/west.yml`. Make sure to
+commit and push all local changes you have made to ZMK and the modules before
+running this command, as this will overwrite them.
+
+To upgrade the Zephyr SDK and Python build dependencies, use `just upgrade-sdk`.
+
## Issues and workarounds
Since I switched from QMK to ZMK I have been very impressed with how easy it is
@@ -318,3 +436,9 @@ remaining issues:
yields a minimum `require-prior-idle-ms` of (60 _ 1000) / (5.7 _ x) ≈ 10500
/ x milliseconds. The approximation errs on the safe side, as in practice
home row taps tend to be faster than average.
+
+[^5]:
+ This will permanently install the packages into your local profile, forgoing
+ many of the benefits that make Nix uniquely powerful. A better approach,
+ though beyond the scope of this document, is to use `home-manager` to
+ maintain your user environment.