Zephyr RTOS 〜 チーム開発を見据えた管理方法 〜


# 1. はじめに

この記事では、会社など組織的な活動で Zephyr を採用する際に、チーム内で環境を統一したり、デプロイやテストを効率よくするための仕組み作りに対してのヒントの提供を目的としています。

下地として [Zephyr RTOS 〜 Lチカのその先へ 〜](https://qiita.com/Corgeek/items/ca4c515ccf556551562f) [^1] で紹介しているリポジトリを利用していますので、よろしければそちらもご参照ください。

また、実装解説を交えた記事として[Zephyr RTOS 〜 GPIO を叩く！ 〜](https://qiita.com/Corgeek/items/122a00e430ad0d9c297a) [^2] や [Zephyr RTOS 〜 I2C 通信の方法と VL53L4CD の移植 〜](https://qiita.com/Corgeek/items/ac211cd48a54971d9b17) [^3] も投稿しています。こちらは本日の記事を読む上で必須ではありませんが、ご覧になっていただけると幸いです。

それぞれの記事で利用しているリポジトリはこちら

https://github.com/Corgeek/ZephyrOpsPlaybook

# 2. 課題の整理

* 公式の [Getting Started](https://docs.zephyrproject.org/latest/develop/getting_started/index.html) [^4] そのままで環境を構築すると常に最新の環境が構築される
    * 全員同じ日時に環境構築して一切環境を変えないのであれば統一できますが、現実的ではありません
* 2024/12現在、手順通りで環境構築すると Zephyr 本体の 6.7GB 強、加えて SDK が 9.2GB 弱になります
    * 本リポジトリの運用で管理対象は 1MB 未満、その他は随時ダウンロードになるため管理不要で、環境構築後は 3.2GB 強、SDK で 1.5GB 強程度
    * アウトソーシングや業務委託、 git が使えない組織風土(!?)などに於いても有用です
* 副次的効果として、新規開発部分と Zephyr 本体を分離しつつ、互いにアクセスしやすいディレクトリ構成を維持しているため、管理しやすさと開発のしやすさを両立しています

# 3. 環境構築のキモ west.yml

公式の [Getting Started](https://docs.zephyrproject.org/latest/develop/getting_started/index.html) では、`west init ~/zephyrproject` で環境構築するディレクトリを指定しています。
ここで、環境の設定ファイル(manifestと呼びます)である west.yml があるディレクトリを -l で指定すると、その設定に沿った環境が構築されます。
つまり、この west.yml を管理することが、今回のお題となる環境の軽量化や統一化に繋がります。

# 4. west.yml のメンテナンスの流れ

2024/12 現在、ZephyrOpsPlaybook では、Zephyr 本体を v4.0.0 で固定しています。
また、関連の HAL 等もその v4.0.0 がリリースされた当時のもので固定されており、
ターゲットは Nordic 系、STM32 系、RaspberryPi Pico系 に絞っています。
つまり、もっと絞りたい場合はこの3種からさらに削れば良いですし、NXP 等のターゲットを増やしたい場合はここに追加すれば良い、となります。

以下は、west.yml をメンテナンスする際のおおまかな流れとなります。

**1. 固定したい Zephyr のバージョンを決める**
**2. 固定したいバージョンの west.yml を取得する**
**3. 欲しい機能を抜き取って local の west.yml に反映させる**
**4. zephyr 公式のリポジトリも west.yml による管理対象として追加する(重要)**

それでは、以降では具体的な手順を追っていきます。

# 5.1. 固定したい Zephyr のバージョンを決める

これは、何がしたいかによるため、今回は ZephyrOpsPlaybook で採用している v4.0.0 を例に話を進めていきます。
下記コマンドでリポジトリを clone して、v4.0.0 の tag を指定して checkout します。

```bash:
git clone https://github.com/zephyrproject-rtos/zephyr.git
cd zephyr
git checkout -b v4.0.0 refs/tags/v4.0.0
```

# 5.2. 固定したいバージョンの west.yml を取得する

先述した zephyr から west.yml を取得します。

tag v4.0.0 時点の実際のファイルはこちら

https://github.com/zephyrproject-rtos/zephyr/blob/40cd35e56d43716bdbdeafafa6c356407121ca2e/west.yml

# 5.3. 欲しい機能を抜き取って local の west.yml に反映させる

先程取得した west.yml から、例えば NXP のみにターゲットを絞り込んだ環境を作りたい場合、
最低限 cmsis と hal_nxp が必要でしたので、これらを抽出します。

```yml:cmsis と hal_nxp だけを取得する west.yml
manifest:
  defaults:
    remote: upstream

  remotes:
    - name: upstream
      url-base: https://github.com/zephyrproject-rtos

  projects:
    - name: cmsis
      revision: 4b96cbb174678dcd3ca86e11e1f24bc5f8726da0
      path: modules/hal/cmsis
      groups:
        - hal
    - name: hal_nxp
      revision: 0ac830233092247c26f5dd01a07b0a484532ea4c
      path: modules/hal/nxp
      groups:
        - hal
```

# 5.4. zephyr 公式のリポジトリも west.yml による管理対象として追加する(重要)

先述の manifest だけでは、公式 zephyr 本体は取得できないため、この west.yml に zephyr 本体も取得するように追記します。
また、その際 revision: で tag や hash を、clone-depth: 1 指定で過去の履歴を取得しないように指定しています。

```yml:NPX 向け最小構成 west.yml
manifest:
  defaults:
    remote: upstream

  remotes:
    - name: upstream
      url-base: https://github.com/zephyrproject-rtos

  projects:
    - name: zephyr_public
      repo-path: zephyr.git
      path: zephyr
      remote: upstream
      revision: v4.0.0
      clone-depth: 1
      west-commands: scripts/west-commands.yml

    - name: cmsis
      revision: 4b96cbb174678dcd3ca86e11e1f24bc5f8726da0
      path: modules/hal/cmsis
      groups:
        - hal
    - name: hal_nxp
      revision: 0ac830233092247c26f5dd01a07b0a484532ea4c
      path: modules/hal/nxp
      groups:
        - hal
```

# 6. 実際に NXP 向け最小構成の環境を構築してみる

1\. model24 というリポジトリを用意したとして、projects ディレクトリ配下にその環境を構築する例を以下に示します。
まず、model24 以下に west.yml を配置します(venv 環境は activate 済み)。

```bash:
(.venv) user@host:~/projects$ ls model24/
west.yml
```

2\. `west init -l model24` で west の位置関係を登録させます。

```bash:
(.venv) user@host:~/projects$ west init -l model24/
=== Initializing from existing manifest repository model24
--- Creating ~/projects/.west and local configuration file
=== Initialized. Now run "west update" inside ~/projects.
```

3\. `west update` で、設定ファイルをベースに各種モジュールを取得します

```bash:
(.venv) user@host:~/projects$ west update
```

4\. 結果の確認

```bash:
(.venv) user@host:~/projects$ ls -a
.  ..  .venv  .west  model24  modules  zephyr
```

5\. ビルドに必要な初期設定を実施

まずは初回の環境構築として pip の追加インストールと環境変数の登録

```bash:
(.venv) user@host:~/projects$ pip install -r zephyr/scripts/requirements.txt
(.venv) user@host:~/projects$ source zephyr/zephyr-env.sh
```

ローカル環境に sdk がまだインストールされていないのであれば下記も実施

```bash:
(.venv) user@host:~/projects$ west sdk install -t arm-zephyr-eabi
```

6\. 公式のサンプルをビルド

```bash:
(.venv) user@host:~/projects$ west build -b frdm_k22f zephyr/samples/basic/minimal
```

※ `west build -b frdm_k22f zephyr/samples/basic/minimal` が通ることは確認していますが、実機を持ち合わせていないため動作確認はできていません。ご理解ください。

参考として、この NXP 最小構成だと 2024/12 現在で 2.4GB弱になりました。

```bash:
(.venv) user@host:~$ du -s -m projects/
2388    projects/
```

# 6.a いただいたコメントの反映

より楽なメンテナンス方法を紹介いただけたので、実際にそれを試してみました。

import を利用する[^5]ことで、指定のリポジトリが持つ west.yml 内のリポジトリを指定することができ、これを利用することで 逐一指定していた revision 指定が不要になり、zephyr.git の revision に紐付いた各モジュールを引っ張ってこれるようになりました。
以下は、5.4 で示した `NPX 向け最小構成 west.yml` と同等の設定になります。
(明示的に個別設定したい場合を除き、こちらの方がメンテナンス性が高く import 利用推奨です)

```yaml:NPX 向け最小構成 west.yml (改)
manifest:
  defaults:
    remote: upstream

  remotes:
    - name: upstream
      url-base: https://github.com/zephyrproject-rtos

  projects:
    - name: zephyr_public
      repo-path: zephyr.git
      path: zephyr
      remote: upstream
      revision: v4.0.0
      clone-depth: 1
      west-commands: scripts/west-commands.yml
      import:
        name-allowlist:
          - cmsis
          - hal_nxp
```

# 7. 公式の manifest 紹介

今回 west.yml を用いた組織的な運用方法を例示しました。
また、詳細は[公式のドキュメント](https://docs.zephyrproject.org/4.0.0/develop/west/manifest.html) [^6] に記載されていますので、こちらもご確認の上、より良い運用方法を模索していただければと思います。

# 8. おわりに

ここまでの4日分の記事で、Zephyr を採用したチーム開発のスタートラインに立てるのでは？と考えています。
ただ、まだまだ業務に必要な知識や(バッド)ノウハウなどもたくさんあり、今後もアドベントカレンダー以外でも投稿していけたらと考えています。

みなさん、良い2025年を！

[^1]: Zephyr RTOS 〜 Lチカのその先へ 〜 (Qiita記事)
https://qiita.com/Corgeek/items/ca4c515ccf556551562f
[^2]: Zephyr RTOS 〜 GPIO を叩く！ 〜 (Qiita記事)
https://qiita.com/Corgeek/items/122a00e430ad0d9c297a
[^3]: Zephyr RTOS 〜 I2C 通信の方法と VL53L4CD の移植 〜 (Qiita記事)
https://qiita.com/Corgeek/items/ac211cd48a54971d9b17
[^4]: Getting Started (Zephyr公式)
https://docs.zephyrproject.org/latest/develop/getting_started/index.html
[^5]: West Manifests (Zephyr公式)
https://docs.zephyrproject.org/latest/develop/west/manifest.html#option-3-mapping
[^6]: manifest の解説 (Zephyr公式)
https://docs.zephyrproject.org/4.0.0/develop/west/manifest.html