ナウでヤングでcoolなNervesを、久々に触った際に遭遇した事象。
Eralng/OTP22(erlang: 22.3.2、elixir: 1.10.3-otp-22 )の環境でNerves 1.6.3を利用していた際に、以下のエラーが発生。
** (Mix) Major version mismatch between host and target Erlang/OTP versions
Host version: 22
Target version: 23
メッセージを読むに、Erlang/OTPのバージョン23が要求されている。
しかし、Nerves 1.6.3のHexDocsのインストール箇所を確認したが、2020/7/29時点でasdfのインストールで指定されているのはErlang/OTP22であった。
※Nerves1.6.3のインストール手順:
https://hexdocs.pm/nerves/1.6.3/installation.html#all-platforms
ギャップがあったので、エラー発生理由と対処方法を調べてみた。
エラー発生理由
mix.exs
に定義している「nerves_system_*
」(nerves_system_rpi0
など)で指定されているバージョンが、Erlang/OTP23を要求しているため。
nerves_system_rpi0のリリースタグを例に挙げると、v1.11.13とv1.12.0では要求されるErlangのバージョンが異なっている。
- v1.11.13(2020/5/27 10:00JSTリリース): Erlang 22.3.4.1
- v1.12.0(2020/6/17 4:11JSTリリース): Erlang/OTP 23.0.2
https://github.com/nerves-project/nerves_system_rpi4/releases/tag/v1.11.3
https://github.com/nerves-project/nerves_system_rpi4/releases/tag/v1.12.0
https://github.com/nerves-project/nerves_system_rpi0/blob/main/CHANGELOG.md
他の「nerves_system_*
」のリリースも同様にv1.11とv1.12(nerves_system_bbbのみ、v2.6とv2.7)を境に、Erlang/OTP23が要求される。
そして、2020/07/29時点にNerves1.6.3でmix nerves.new
でプロジェクトを作成すると、mix.exsで定義される「nerves_system_*
」にはv1.12(と2.7)が指定されていた。
# Run "mix help deps" to learn about dependencies.
defp deps do
[
# Dependencies for all targets
{:nerves, "~> 1.6.0", runtime: false},
〜中略〜
# Dependencies for specific targets
{:nerves_system_rpi, "~> 1.12", runtime: false, targets: :rpi},
{:nerves_system_rpi0, "~> 1.12", runtime: false, targets: :rpi0},
{:nerves_system_rpi2, "~> 1.12", runtime: false, targets: :rpi2},
{:nerves_system_rpi3, "~> 1.12", runtime: false, targets: :rpi3},
{:nerves_system_rpi3a, "~> 1.12", runtime: false, targets: :rpi3a},
{:nerves_system_rpi4, "~> 1.12", runtime: false, targets: :rpi4},
{:nerves_system_bbb, "~> 2.7", runtime: false, targets: :bbb},
{:nerves_system_x86_64, "~> 1.12", runtime: false, targets: :x86_64},
]
end
このため、mix deps.get
後にmix firmware
を行うと、要求されるErlangのバージョンが23になるため、Erlang/OTP23でビルドしていないとエラーとなってしまう。
補足:エラーメッセージ全文
以下、自分の環境で出力されたエラーメッセージの全文。
** (Mix) Major version mismatch between host and target Erlang/OTP versions
Host version: 22
Target version: 23
This will likely cause Erlang code compiled for the target to fail in
unexpected ways.
The easiest way to resolve this issue is to install the same version of
Erlang/OTP on your host. See the Nerves installation guide for doing this
using the `asdf` version manager.
The Nerves System (nerves_system_*) dependency determines the OTP version
running on the target. It is possible that a recent update to the Nerves
System pulled in a new version of Erlang/OTP. If you are using an official
Nerves System, you can verify this by reviewing the CHANGELOG.md file that
comes with the release. Run 'mix deps' to see the Nerves System version and
go to that system's repository on https://github.com/nerves-project.
If you need to run a particular version of Erlang/OTP on your target, you can
either lock the nerves_system_* dependency in your mix.exs to an older
version. Note that this route prevents you from receiving security updates
from the official systems. The other option is to build a custom Nerves
system. See the Nerves documentation for building a custom system and then
run 'make menuconfig' and look for the Erlang options.
対処方法
以下、2種類の対処方法がある。
- OTPのバージョンを上げる
- OTPのバージョンを上げずに、
nerves_system_*
側で対応する
対処方法1: OTPのバージョンを上げる
こちらは正攻法。
Erlang23をインストールし、その後にElixirをOTP23でインストールする。
Erlangのインストールに時間がかかる点がネック。
asdfのlocalコマンドを利用すれば、特定のディレクトリ配下だけをErlang/OTPを変更可能なので、Nervesを利用する以外ではErlangのバージョンを上げたくない場合に活用できる。
$asdf install erlang 23.0.3
$asdf local erlang 23.0.3
$asdf install elixir 1.10.4-otp-23
$asdf local elixir 1.10.4-otp-23
対処方法2: OTPのバージョンを上げずに、nerves_system_*側で対応する
こちらは、暫定的な対応。
諸事情により、Erlang/OTPのバージョンを上げるのが難しい場合に実施する。
最終的には、Nervesのバージョンが上がっていくに連れてErlang/OTPのバージョンを上げざるを得なくなるが、バージョンアップよりは対応にかかる時間は(瞬間的には)少なく済む。
具体的な実施内容としては、以下の通り。
- mix.exsの「nerves_system_*」関連の指定バージョン値を変更する
-
mix deps.update --all
を実行する。(すでにmix deps.get
を実施している場合のみ。未実施の場合は、mix deps.get
で良い。)
まず、mix.exs
内のdeps箇所で指定されている「nerves_system_*
」のバージョンを、自分の環境のErlang/OTPのバージョンで動作可能なバージョンに変更する。指定バージョンは、CHANGELOG.mdを参考にして決める。
※以下の例では、Erlang 22.3.2に対応するために、「nerves_system_*
」のバージョンをv1.11.1ベース(bbbのみ2.6)に修正する。
# Run "mix help deps" to learn about dependencies.
defp deps do
[
# Dependencies for all targets
{:nerves, "~> 1.6.0", runtime: false},
〜中略〜
# Dependencies for specific targets
{:nerves_system_rpi, "~> 1.11.1", runtime: false, targets: :rpi},
{:nerves_system_rpi0, "~> 1.11.1", runtime: false, targets: :rpi0},
{:nerves_system_rpi2, "~> 1.11.1", runtime: false, targets: :rpi2},
{:nerves_system_rpi3, "~> 1.11.1", runtime: false, targets: :rpi3},
{:nerves_system_rpi3a, "~> 1.11.1", runtime: false, targets: :rpi3a},
{:nerves_system_rpi4, "~> 1.11.1", runtime: false, targets: :rpi4},
{:nerves_system_bbb, "~> 2.6", runtime: false, targets: :bbb},
{:nerves_system_x86_64, "~> 1.11.1", runtime: false, targets: :x86_64},
]
end
mix.exsの修正後、mix deps.get
を実行する。
ただし、既にmix deps.get
を実行している場合は、以下のようなエラーが出る。
** (Mix) Hex dependency resolution failed, change the version requirements of your dependencies or unlock them (by using mix deps.update or mix deps.unlock). If you are unable to resolve the conflicts you can try overriding with {:dependency, "~> 1.0", override: true}
そのため、エラーメッセージにあるように、mix deps.update
を実行する。
ただし、引数なしで実施すると、以下のように引数を指定するようにエラーメッセージが出る。
$ mix deps.update
** (Mix) "mix deps.update" expects dependencies as arguments or the --all option to update all dependencies
メッセージに従い、--all
を付与して実行する。
$ mix deps.update --all
実行後、コンソールにダウングレードの情報が出力される。
Resolving Hex dependencies...
Dependency resolution completed:
〜(中略)〜
Downgraded:
nerves_system_bbb 2.7.1 => 2.6.1
nerves_system_br 1.12.0 => 1.11.2
nerves_system_rpi 1.12.1 => 1.11.1
nerves_system_rpi0 1.12.1 => 1.11.1
nerves_system_rpi2 1.12.1 => 1.11.1
nerves_system_rpi3 1.12.1 => 1.11.1
nerves_system_rpi3a 1.12.1 => 1.11.1
nerves_system_rpi4 1.12.1 => 1.11.2
nerves_system_x86_64 1.12.1 => 1.11.1
New:
nerves_system_linter 0.3.0
* Updating nerves_system_rpi (Hex package)
* Updating nerves_system_rpi0 (Hex package)
* Updating nerves_system_rpi2 (Hex package)
* Updating nerves_system_rpi3 (Hex package)
* Updating nerves_system_rpi3a (Hex package)
* Updating nerves_system_rpi4 (Hex package)
* Updating nerves_system_bbb (Hex package)
* Updating nerves_system_x86_64 (Hex package)
* Updating nerves_system_br (Hex package)
* Getting nerves_system_linter (Hex package)
Nerves environment
MIX_TARGET: rpi0
MIX_ENV: dev
Resolving Nerves artifacts...
Resolving nerves_system_rpi0
=> Trying https://github.com/nerves-project/nerves_system_rpi0/releases/download/v1.11.1/nerves_system_rpi0-portable-1.11.1-38F032F.tar.gz
|==================================================| 100% (141 / 141) MB
=> Success
Cached nerves_toolchain_armv6_rpi_linux_gnueabi
$
この後でmix firmware
を実行すれば、Major version mismatch between host and target Erlang/OTP versions
のエラーは発生しなくなる。
まとめ
Nerves1.6.3のリリース時期は「2020/5/7 3:52JST」のため、その後にリリースされた「nerves_system_*」の関連情報がHexDocsに反映されていないのは致し方ないとは言え、少しモヤっとはします。
※ただし、GitHub上のdocs/Installation.md
自体は、2020/6/17時点で更新はされていました。HexDocsへの反映が未だけのようです。
https://github.com/nerves-project/nerves/commit/50ef2a6933eeae4ca05254f88677badc70cc5c28#diff-045d5d7186acf52b74848a7dfbdde200
今後のバージョンアップでも同様なことが起こる可能性はあるので、Nerves自体のGitHubリポジトリとあわせてnerves_system_*のGitHubリポジトリをWatchしておくと良いかもしれません。
と、この記事を書いている間にも、2020/7/30 5:35JSTに「v2.0.0-rc.0」のTagが出ていましたね。
https://github.com/nerves-project/nerves_system_rpi0/releases/tag/v2.0.0-rc.0
正式版のv2.0.0のリリース、およびNervesのバージョンアップも近いかも。