9
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

記事Elixir NIFを使ってみるでNIFを使ってみました。
この記事では、NIFの動作を確認できたんですが、ちょっと心配な事があります。

Nervesの場合、ファームウエアの作成(=compile)はhostで行い、実行はtargetのマシーンで行われます。
hostでcompileするときに、targetのアーキテクチャでクロスコンパイルされる必要があるんですが、その考慮を何もしていません。

適切にクロスcompileされるか、確かめてみます

やってみる

プロジェクトを作成

mix nerves.new test001

mixのdepsにhello_nifを加える

      {:hello_nif, git: "https://github.com/masahiro-999/hello_nif", branch: "main"}

mix deps.getmix firmwareを実行

hello_nifがコンパイルされています。

==> hello_nif
gcc -o multiply.so -shared -fPIC -I/home/masa/.asdf/installs/erlang/27.0.1/erts-15.0.1/include multiply.c
Compiling 1 file (.ex)
Generated hello_nif app

実行結果1

案の定、エラーが発生して、再起動を繰り返しました

image.png

multiply.soが含まれていない様子です。
クロスコンパイル以前に、パッケージとしての問題がありました。

修正

load_nifでカレントディレクトリのファイルを取得するようにしていたことが問題
multiply.soを prev ディレクトリに置く様に修正。
:code.priv_dir(:hello_nif)を使って、場所を取得するように修正

  def load_nif() do
    :erlang.load_nif(:code.priv_dir(:hello_nif) ++ ~c"/multiply", 0)
  end

実行結果2

mix firmwareを実行すると次のエラーが発生

Updating base firmware image with Erlang release...
scrub-otp-release.sh: ERROR: Unexpected executable format for '/home/masa/nerves/test001/_build/m5stack_core_mp135_dev/_nerves-tmp/rootfs_overlay/srv/erlang/lib/hello_nif-0.1.0/priv/multiply.so'

Got:
 readelf:Advanced Micro Devices X86-64;0x0

Expecting:
 readelf:ARM;0x5000400, Version5 EABI, hard-float ABI

This file was compiled for the host or a different target and probably
will not work.

Check the following:

1. If this file comes from a library, that library may be compiling to
/home/masa/.nerves/artifacts/nerves_system_m5stack_core_mp135-portable-0.0.7/scripts/scrub-otp-release.sh: line 153: deps: command not found
   its source directory under . Manually clean up the source
   directory and try building again.

2. Are you using a path dependency in your mix deps? If so, run
   'mix clean' in that directory to avoid pulling in any of its
   build products.

3. Did you recently upgrade or change your Nerves system? If so,
   try cleaning and rebuilding this project and its deps.

4. Are you building outside of Nerves' mix integration? If so,
   make sure that you've sourced 'nerves-env.sh'.

If you are very sure you know what you are doing, you may place an empty
file in the same directory as the offending file(s) called '.noscrub'.
This will explicitly disable scrubbing for that directory.

If you're still having trouble, please file an issue on Github
at https://github.com/nerves-project/nerves_system_br/issues.

ああ~~。やっぱりクロスコンパイルできてない事がわかりました。

Nervesで使えているライブラリーを真似する

正しい方法がわかりません。Nerves projectの方のパッケージを参考にすることにしました。

Circuits i2cのMakefileのMakefileを見てみます。

コンパイルするコマンドが$(CC)となっていました。

この変更で、ターゲットに適したコンパイラーが使われるようになり、エラーが解消されました。

Makefile
PREFIX = $(MIX_APP_PATH)/priv
BUILD  = $(MIX_APP_PATH)/obj

NIF = $(PREFIX)/multiply.so

SRC = c_src/multiply.c

ERLANG_INCLUDE_DIR = $(shell erl -eval 'io:format("~s", [code:lib_dir(erl_interface, include)])' -s init stop -noshell)
ERTS_INCLUDE_DIR = $(shell erl -eval 'io:format("~s", [code:root_dir() ++ "/erts-" ++ erlang:system_info(version) ++ "/include"])' -s init stop -noshell)

all: compile

compile:
	mkdir -p $(PREFIX)
	$(CC) -o $(NIF) -shared -fPIC -I$(ERTS_INCLUDE_DIR) $(SRC)

clean:
	rm -f $(NIF)

実行結果

Core MP135(ARM CPU)で実行して、実行できました

iex(2)> HelloNif.multiply(2,3)
6
iex(3)> 
9
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?