この記事は何?(この項目のみ訳者独自記述)
この記事は、Nerves公式ドキュメントの「[Customizing Your Own Nerves System v1.7.9] (https://hexdocs.pm/nerves/customizing-systems.html)」の章の日本語訳です。対象はv.1.7.9で、2021/07/10前後に作業したものです。
勝手訳ですが、将来的に公式にマージできればいいなと思っています。
訳語はそれらしいものを選んでいますが、よく使われるものと異なっているものがある場合には、ご連絡等いただければ修正していきます。
Customizing Your Own Nerves System
このガイドに従う前に、The Anatomy of a Nerves System (Nervesシステムの内部構造) について読んでおくとよいでしょう。
アプリケーションによっては、事前に構築されたNervesシステムがニーズを満たさない場合があります。たとえば、追加のLinuxパッケージを入れたい場合や、Nervesがサポートするターゲットのリストにないハードウェアで実行したい場合などです。ホストプラットフォーム間でビルドプロセスを一貫させるため、またLinux以外のホストでビルドを実行するために、Nervesは舞台裏でDockerコンテナを使用しています。これにより、Docker for MacまたはDocker for Windowsがこれらのプラットフォームにインストールされていれば、以下のステップは、あなたが開発に使用しているどのホストプラットフォームにも適用することが可能になります。
Getting Setup to Build a System
ゼロからシステムを設計することもできますが、既存のシステムをコピーして変更し、公式リリースと区別するために名前を変更するのが最も簡単です。例えば、Raspberry Pi 3ボードを対象とする場合は、次のようにします。
-b
フラグを忘れないようにしてください。mainから直接Cloning/Forkすることは安定していないと考えられます。
git clone https://github.com/nerves-project/nerves_system_rpi3.git custom_rpi3 -b v1.12.0
システムディレクトリの名前は自由ですが、この例では custom_rpi3
とします。変更を加える前に、カスタムシステムをバージョンコントロールシステムに登録することをお勧めします。これにより、公式システムからのアップストリームの変更を後で簡単にマージすることができます。例えば、GitHubを使っていると仮定すると
# After creating an empty custom_rpi3 repository in your GitHub account
# GitHubアカウント上で空のcustom_rpi3レポジトリを作っておいてから
cd custom_rpi3
git remote rename origin upstream
git remote add origin git@github.com:YourGitHubUserName/custom_rpi3.git
git checkout -b main
git push origin main
次に、Mixプロジェクトのメタデータを調整するために、以下を更新します。
- ファイルの先頭にあるmixプロジェクトのモジュール名
-
@app
の値をcustom_rpi3
に変更する。 -
@github_organization
の値を、GitHubのユーザー名または組織に設定します。
このファイルの構造については、Mixプロジェクト の公式ドキュメントを参照してください。
# custom_rpi3/mix.exs
# =vvv= make sure to rename the module name
# defmodule NervesSystemRpi3.MixProject do
defmodule CustomRpi3.MixProject do
use Mix.Project
# =vvv= Rename `"nerves-project"` here to your user or ogranization name
# @github_orgranization "nerves-project"
@github_organization "YourGitHubUserOrOrganizationName"
# =vvv= Rename `nerves_system_rpi3` here to `custom_rpi3`
# @app :nerves_system_rpi3
@app :custom_rpi3
end
# =^^^= The rest of this file remains the same
Building the System
カスタムシステムディレクトリの準備ができたので、プロジェクトの mix.exs
からそれを指すようにするだけです。この例では、custom_rpi3
システムディレクトリが、nervesファームウェアプロジェクトのディレクトリと同じディレクトリにあると仮定しています。
~/projects
├── custom_rpi3
└── your_project
新しいプロジェクトを開始する場合は、1つのターゲットだけをサポートするように生成することができます。rpi3
をcustom_rpi3
に更新します。
mix nerves.new your_project --target rpi3
#=vvv= Update your_project/mix.exs to accept your new :custom_rpi3 target
# ...
@all_targets [:rpi3, :custom_rpi3]
# =^^^^^^^^^^=
defp deps do
[
# Dependencies for all targets
# ...
# Dependencies for specific targets
{:nerves_system_rpi3, "~> 1.6", runtime: false, targets: :rpi},
{:custom_rpi3, path: "../custom_rpi3", runtime: false, targets: :custom_rpi3, nerves: [compile: true]}, # <===
]
end
注意:nerves :[compile: true]オプションを依存関係に含めると、システムが自動的にコンパイルされるようになります。この動作をさせたくない場合はこのオプションを削除しますが、その場合にはファームウェアをビルドする前に、
mix compile
タスクでシステムを手動でコンパイルする必要があります。
MIX_TARGET
にカスタムシステムを参照するように設定し、ファームウェアをビルドします。
cd ~/projects/your_project
export MIX_TARGET=custom_rpi3
mix deps.get
mix firmware
このプロセスは、初回は通常のファームウェアビルドよりもかなり時間がかかります(15~30分)。このプロセスが終了すると、公式のrpi3
システムと同等のものを正常に構築できることが確認できます。カスタムシステムが構築された後は、アプリケーションの変更やファームウェアの再構築を通常通り行うことができます。カスタムシステムは、システムのソースプロジェクト自体に変更を加えた場合にのみ再構築されます。
Buildroot Package Configuration
BuildrootはLinuxからしか使えないため、NervesはNervesシステム構成シェルと呼ばれる抽象化レイヤーを提供し、Linux以外のプラットフォームでLinuxベースのDockerコンテナを使うことで、LinuxとLinux以外の開発ホストで同じ手順を使えるようにしています。この環境にアクセスするには、カスタムシステムのソースディレクトリからmix nerves.system.shell
タスクを実行します。
$ mix deps.get
Mix environment
MIX_TARGET: custom_rpi3
MIX_ENV: dev
Running dependency resolution...
Dependency resolution completed:
# <-SNIP->
* Getting nerves (Hex package)
Checking package (https://repo.hex.pm/tarballs/nerves-1.3.0.tar)
# <-SNIP->
$ mix nerves.system.shell
Mix environment
MIX_TARGET: custom_rpi3
MIX_ENV: dev
==> nerves
Compiling 25 files (.ex)
Generated nerves app
Preparing Nerves Shell
Creating build directory...
Cleaning up...
Nerves /nerves/build >
Nerves /nerves/build >
シェルプロンプトに入ると、Nervesシステムをカスタマイズするためのワークフローは、 make menuconfig
と make savedefconfig
を使って、Nervesの外でBuildrootを使う場合と同じです。これは、Linuxと非Linuxの両方のプラットフォームで、効果的なサブシェルであることを覚えておいてください。設定の更新と、オプションとして「手動で」システムを再構築することが終わったら、exit
を入力するか、CTRL+D
を押すことで、通常のシェルに戻ることができます。
主なパッケージ設定のワークフローは、設定したい内容に応じて3つのカテゴリーに分かれています。
-
make menuconfig
を実行して基本パッケージを選択する。 -
make linux-menuconfig
で Linux カーネルとカーネルモジュールを変更する。 -
make busybox-menuconfig
で、より多くのコマンドラインユーティリティを有効にする。
注:システム構成シェルの中で
make
を使って「手動」でシステムを構築することができます。これは、さまざまな変更を試しながら素早く反復するためです。プロジェクトでシステムを試す準備ができたら、シェルを終了して、プロジェクトのディレクトリからmix firmware
で再構築を行います。そのため、Buildroot の使用経験があり、make clean
ステップを省略できる場合を除き、make
の前に常にmake clean
を実行することをお勧めします。
menuconfig
インターフェースを終了すると、変更内容が一時的に保存されます。システムのソースディレクトリに戻して保存するには、以下の適切な手順に従ってください。
1 make menuconfig
した場合
make savedefconfig
を実行して、Systemの nerves_defconfig
を更新します。
2 make linux-menuconfig
した場合
カーネルの設定が完了したら、make linux-update-defconfig
を使って、Linuxの設定をデフォルトの設定ファイルに保存します。保存先のファイルは、プロジェクトのルート(または作業しているカーネルのバージョン)にある linux-4.9.defconfig
です。
注意: もし、あなたのシステムにまだカスタムのLinux設定がない場合は、 システムディレクトリにある新しいLinuxのdefconfigを指すように、 (
make menuconfig
を使って)Buildrootの設定を更新する必要があります。そのパスは、通常$(NERVES_DEFCONFIG_DIR)/linux-x.y_defconfig
のようなものです。
3 make busybox-menuconfig
した場合
残念ながら、BusyBoxのdefconfigを簡単に保存する方法は今のところありません。代わりにしなければならないのは、BusyBoxの完全な設定を保存して、それをnerves_defconfig
に含めるように設定することです。あなたがLinux以外のホストでDocker経由でNerves System Shellを使用していて、カスタムシステムのソースディレクトリがcustom_rpi3
という名前だとすると、以下のようにする必要があります(バージョン識別子はあなたにとって異なるかもしれません)。
cp build/busybox-1.27.2/.config /nerves/env/custom_rpi3/busybox_defconfig
Linux の設定と同様に、Buildroot の設定がまだの場合、カスタム設定を指すように更新する必要があります。これは、make menuconfig
で Target Packages に移動し、BusyBox パッケージの Additional BusyBox configuration fragment files オプションを見つけることで実現できますが、このオプションは既に有効になっており、ベースコンフィグレーションが指定されているはずです。この例に沿って進めていくと、正しい設定値は以下のようになります。
${NERVES_DEFCONFIG_DIR}/busybox_defconfig
特にパッケージを追加する必要がある場合には、Buildroot user manualが非常に役立ちます。様々なNervesシステムのリポジトリには、多くの一般的な使用例があるので、それらもチェックしてみてください。
Adding a custom Buildroot Package
Buildrootに含まれていない、elixir_makeでコンパイルするには複雑すぎるElixir以外のプログラムがある場合は、それをビルドする方法の説明をシステムに追加する必要があります。これは、「カスタムBuildrootパッケージ」と呼ばれ、Nervesシステムに追加するプロセスは、Buildrootとほぼ同じです。これは、Buildrootマニュアルの新しいパッケージの追加の章で説明されています。Nervesとの主な違いは、ディレクトリです。
このプロセスでは、パッケージをBuildrootにアップストリームでコントリビュートすることに意味があるかどうかを検討してください。
Nervesシステムには、カスタムシステムディレクトリのルートに以下のファイルが必要です。
-
Config.in
- 各パッケージのConfig.in
ファイルを含みます。 -
external.mk
- 各パッケージの<パッケージ名>.mk
ファイルを含む。 -
packages
- カスタムパッケージディレクトリを含むディレクトリ
package
ディレクトリ内の各ディレクトリには、以下の2つのものが含まれています。
-
Config.in
- パッケージ情報の定義 -
<パッケージ名>.mk
- パッケージのビルド方法を定義します。
ですので、 libfoo
パッケージをビルドしたい場合は、まず Config.in
と external.mk
ファイルをシステムのベースディレクトリに作成します。
/Config.in
:
menu "Custom Packages"
source "$NERVES_DEFCONFIG_DIR/packages/libfoo/Config.in"
endmenu
/external.mk
:
include $(sort $(wildcard $(NERVES_DEFCONFIG_DIR)/packages/*/*.mk))
続いて、パッケージディレクトリとパッケージファイルを作成します。
mkdir -p packages/libfoo
touch packages/libfoo/Config.in
touch packages/libfoo/libfoo.mk
この時点で、これらのファイルに何を追加すべきかについては、Buildroot の公式ドキュメントに従う必要があります。最も簡単な方法は、Buildroot で類似のパッケージを見つけ、適切に名前を変更した上で内容をコピー/ペーストすることです。
Creating an Artifact
Nervesシステムの構築は、多くのシステムリソースを必要とし、完成までに長い時間を要することがよくあります。Nervesシステムの構成に満足し、リリースの準備ができたら、アーティファクトを作成することができます。アーティファクトは、Nervesシステムのコンパイル済みバージョンで、 mix deps.get
を呼び出すと取得できます。アーティファクトは、 nerves_package
設定の artifact_sites
リストで指定されたヘルパーの1つを使って取得しようとします。
現在、3種類のヘルパーがいます。
{:github_releases, "organization/repo"}
{:github_api, "organization/repo", username: "", token: "", tag: ""}
{:prefix, "url", opts \\ []}
artifact_sites
は、アーティファクトへの場所のパスを宣言するだけです。これは、アーティファクトの名前がNervesによって定義され、正しいものをダウンロードするために使われるからです。Nervesシステムのアーティファクト名は、 <name>-portable-<version>-<checksum>.tar.gz
という構造になっています。ファイルの最後のチェックサムは、 nerves_package
設定の チェックサム
リストで指定されたファイルとディレクトリの内容に基づいて計算されます。注意しなければならないのは、成果物の作成後にチェックサムファイルやディレクトリの内容を変更した場合、成果物は一致せず、使用できないということです。したがって、アーティファクトを作成する前に、まず artifact_sites
を定義する必要があります。
アーティファクトを作成するには、プロジェクトをビルドして、カスタムNervesシステムのディレクトリ内から mix nerves.artifact
を呼び出すだけです。例えば、システム名が custom_rpi3
でバージョンが 0.1.0
の場合、現在の作業ディレクトリに custom_rpi3-portable-0.1.0-ABCDEF0.tar.gz
のようなファイルができます。このファイルは、artifact_sites
で指定した場所に置く必要があります。Github Releasesヘルパーを使用している場合は、Githubでタグからリリースを作成してから、ファイルをアップロードする必要があります。
これで、メインプロジェクトで :path
の依存関係を使う代わりに、 :github
の依存関係を使えば、他の人との共有が容易になります。
# Update the `custom_rpi3` dep in your `deps/0` function.
{:custom_rpi3, github: "YourGitHubUserName/custom_rpi3", runtime: false, targets: :custom_rpi3}
また、システムパッケージをhexに公開することもできます。この場合、mix.exs
ファイルに何も変更を加える必要はありません。
mix hex.publish
メインプロジェクトに戻り、depsを更新します。
# make sure you check the version here.
{:custom_rpi3, "~> 1.7", runtime: false, targets: :custom_rpi3}
Custom System Maintenance
Nervesシステムをカスタマイズし、成果物を作成し、パッケージを公開した後、おそらく元のシステムの最新の更新を追跡したいと思うでしょう。「Getting Setup to Build a System」で説明したgit
の手順を踏んでいれば、 upstream
というリモートがあるはずです。これを確認するには、次のようにします。
$ git remote -v
origin git@github.com:YourGitHubUserName/custom_rpi3.git (fetch)
origin git@github.com:YourGitHubUserName/custom_rpi3.git (push)
upstream https://github.com/nerves-project/nerves_system_rpi3.git (fetch)
upstream https://github.com/nerves-project/nerves_system_rpi3.git (push)
システムをアップデートする準備ができたら(たとえばNervesが新しいバージョンを公開した後)、 upstream
の変更をマージすればいいのです。例えば、 v1.7.1
の nerves_system_rpi3
で始めた場合、 v1.7.2
が公開されたら、以下のようにしてカスタムシステムをアップグレードできます。
git fetch --all
git merge upstream/main
# Solve any merge conflicts
git push origin main
また、GitHubのインターフェイスを使って行うこともできます。
https://github.com/YourGitHubUserName/custom_rpi3/compare/main...nerves-project:main?expand=1