zmk-workspaceで簡単にZMKファームウェアをローカルビルドする
ローカルビルドについて
ZMKファームウェア(正確には、zmk-config)をビルドするにはGitHub Actionsを使用するのが一般的ですが、ビルドが遅い(2分ほどかかる)上に、zipをダウンロードして展開するのも面倒ですよね。ダウンロードして展開するのはスクリプトで自動化できるにしても、キーマップやモジュール開発で試行錯誤する際に、いちいち2分も待っていられません。
それを解決するのがローカルビルド、つまり、自分のPC上でビルドすることです。マシンスペックにもよりますが、筆者の環境だと15秒程度でビルドできます。
ローカルビルドの手順はZMK公式のドキュメントに記載されていますが、それに従ってやるとかなり面倒くさいです。本記事で使用するzmk-workspaceは、それを簡単に、便利にできるようにしたものです。
公式手順の面倒くさいところ
公式のローカルビルド手順では、最終的に以下のようなコマンドでビルドすることになります。
west build -s app -d build/right -b seeeduino_xiao_ble -S studio-rpc-usb-uart \
-- -DZMK_CONFIG=/workspaces/zmk-config/config -DSHIELD=roBa_R \
-DZMK_EXTRA_MODULES=/workspaces/zmk-modules/zmk-pmw3610-driver
まずコマンドが長すぎてキレそうになります。(設定で永続化できたり、2回目以降のビルドでは省略できたりしますが、最初の手間は変わりません。) パスは相対パスではなく絶対パスでないといけないという罠があり、初めて試す人はそこでハマります。
そして、-DZMK_EXTRA_MODULESオプションで指定している外部モジュール、これはwest.ymlに記載しているものですが、手動でgit cloneした上でビルドコマンドに記載する必要があります。GitHub Actionsでのビルドなら自動でやってくれるのに、不便ですよね。1つや2つならまだいいですが、それ以上になってくると耐えられません。
どうしてそんな面倒くさい仕様になっているかというと、GitHub Actionsでのビルドと公式手順のローカルビルドの視点の違いが理由です。これに関しては、snize氏の説明が分かりやすいです。
- Devcontainer: ZMK 本体が「主」であり、そこにユーザー設定/モジュールを「追加」するイメージ。
- GitHub Actions: ユーザー設定/モジュールが「主」であり、その west.yml に従って ZMK 本体などを「取得」し、自身もビルド対象に含めるイメージ。
(ここでいうDevcontainerとは、公式手順でのローカルビルドのことを指しています。)
zmk-workspaceでは、このコマンドを自動で構築します。また、GitHub Actionsのアプローチと同じ方法を取ることで、west.ymlに記載された外部モジュールを手動でcloneすることなく、自動で解決します。
zmk-workspaceは、urob氏のzmk-configビルドセットアップに基づいています。この場でurob氏にお礼申し上げます。
前提知識・環境
- 基本的なGitの操作・ターミナル操作(
cdとかgit cloneとか) - Windowsの場合、WSLがインストールされていること(NixまたはDev Containerを使用するために必要です)
セットアップ
zmk-workspaceはセットアップの方法としてNixを使用する方法とDev Containerを使用する方法の2つをサポートしています。どちらかを選択して進めてください。
Winodws/macOSの場合、Nixならuf2ファイルの書き込みを自動化するスクリプトを用意している[1]ので、Nixの方がおすすめです。
Nixによるセットアップ
-
https://nixos.org/download/ に従い、Nixをインストールする
-
nix-commandを使えるように設定する
mkdir -p ~/.config/nix && echo 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf -
Nixのインストールを反映するため、ターミナルを再起動する
-
zmk-workspaceをcloneする
git clone https://github.com/kot149/zmk-workspace.gitcd zmk-workspace -
nix developを実行する。以下、この中で作業する
nix developオプション: direnvを使用して`nix develop`の実行を省略する
以下のコマンドを実行することで、
nix developを実行しなくてもディレクトリに移動するだけで自動で有効化されるようになります。以下はbashを使用している場合の手順です。zshなど他のシェルを使用している場合は、適宜読み替えてください。
# direnvとnix-direnvをインストールする nix profile add nixpkgs#direnv nixpkgs#nix-direnv # シェルフックを設定する echo 'eval "$(direnv hook bash)"' >> ~/.bashrc # nix-direnvを設定する mkdir -p ~/.config/direnv echo 'source $HOME/.nix-profile/share/nix-direnv/direnvrc' >> ~/.config/direnv/direnvrc # 設定を再読み込みする source ~/.bashrc # zmk-workspaceでdirenvの有効化を許可する direnv allow
Dev Containerによるセットアップ
- VSCodeをインストールする https://code.visualstudio.com/download
- Dockerをインストールする https://docs.docker.com/get-docker/
- ターミナルを開き、zmk-workspaceをcloneする
git clone https://github.com/kot149/zmk-workspace.git - cloneしたzmk-workspaceをVSCodeで開く
code zmk-workspace - VSCodeの拡張機能「Dev Containers」をインストールする
- VSCodeの拡張機能の画面で
@id:ms-vscode-remote.remote-containersで検索してインストール
- VSCodeの拡張機能の画面で
- VSCodeのフォルダをDev Containerで開き直す
-
F1キーかCtrl+Shift+Pを押してコマンドパレットを開く -
開発コンテナー: コンテナーで再度開く(Dev Containers: Reopen in Container)コマンドを検索して実行する
-
- VSCodeのウィンドウがリロードされ、Dev Containerが起動するので、完了までしばらく待つ
- 以下、VSCodeでDev Containerを開いた状態で、VSCodeのターミナルから操作する
ビルド
- zmk-configを
config/ディレクトリの中にcloneするcd config(cloneするリポジトリは自身のものに合わせて変更してください)git clone https://github.com/kot149/zmk-config-roBa.gitcd .. - 初期化する(前の手順でcloneしたzmk-configのリポジトリ名に合わせて変更してください)
just init config/zmk-config-roBa
この時点で、west.ymlに記載された外部モジュールが自動でcloneされます。 - ビルドする(
just build roBa_RroBa_Rはshieldの名前です。ビルドしたいshieldの名前に合わせて変更してください。)
問題なくビルドが終われば、zmk-workspaceのfirmware/ディレクトリにビルドされたファームウェアが保存されています。 - uf2ファイルを書き込む
just flash roBa_R-rを指定すると、flashする前に再ビルドします。just flash roBa_R -r
補足
- 再度ビルドを行った場合は、キャッシュが使用されます。キャッシュなしでビルドするには、
-pオプションを指定してjust build シールド名 -pを実行します。 - 別のzmk-configでビルドするには、
config/ディレクトリの中に、別のzmk-configをcloneし、just init config/zmk-config-xxxからやり直します。 - モジュールを追加するには、
config/zmk-config-xxx/config/west.ymlにモジュールを追加した後、just updateを実行し、just buildします。 - モジュールやZMK本体のソースコードをいじるには、zmk-workspace内にzmkやモジュールがcloneされているので、それをいじります。再度ビルドすれば、いじったコードが反映されます。
- cloneされるモジュールを
modules/フォルダの中にまとめるには、west.ymlのprojectsの各項目にpath: modules/module-nameを追加すると、modules/module-name/にcloneされるようになります。
-
Dev Containerでもコンテナの外から実行して書き込みを自動化するスクリプトを作ればできますが、Nixを使用した方が楽です。 ↩︎
Discussion