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 spacesticky-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 ![](img/keymap.png) @@ -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.