3
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?

AtomVM: ESP32 用 NIF に出てくる用語について調べてみる

Last updated at Posted at 2025-12-13

はじめに

先日、最小 NIF を自作して AtomVM(ESP32-S3)上で動かしてみました。

その過程で、前提として知っておくべき用語やルールがいくつか出てきました。仕組みをしっかり理解していないと、NIF の実装自体が正しくても AtomVM 側に組み込めず、切り分けが難しくなりそうです。

忘れないうちに整理しておきます。

piyopiyo-board-2025-12.png

※ 写真はイメージです

概要

現時点で理解できた内容を、先に整理します。

  • AtomVM(ESP32)のビルドは、ESP-IDF のコンポーネントの集まりとして構成されている
    • 自作 NIF も ESP-IDF のコンポーネントとして追加する
  • コンポーネントを追加する最小セット
    • CMakeLists.txt
    • (任意だが便利)Kconfig
  • NIF が読み込まれないときの主な原因
    • リンクで落ちて、登録コードが最終成果物に含まれていない
    • CONFIG_... のシンボル名が、Kconfig と C 側の条件で一致していない
    • NIF 名の文字列("Elixir.Module:fun/arity")が一致していない

AtomVM 側のコンポーネントの置き場所

AtomVM の ESP32 向けプロジェクトは、だいたい次のディレクトリで作業します。

my_atomvm_esp32_path="$HOME/Projects/atomvm/AtomVM/src/platforms/esp32"
cd "$my_atomvm_esp32_path"

この配下に components/ があり、ESP-IDF のコンポーネントを追加します。主に2つのやり方が考えられます。

  • components/ 配下に追加したいコンポーネントの実体を置く
  • components/ 配下へ追加したいコンポーネントをシンボリックリンクする
シンボリックリンクする場合の例
my_atomvm_esp32_path="$HOME/Projects/atomvm/AtomVM/src/platforms/esp32"
my_nif_src="$HOME/Projects/atomvm_hello_nif"
my_nif_dest="$my_atomvm_esp32_path/components/atomvm_hello_nif"

ln -sfn "$my_nif_src" "$my_nif_dest"

この形にしておくと、自作部品を AtomVM 本体から切り離して管理できます。

自作部品の構成

ESP-IDF のコンポーネントとして扱うために、最低限そろえておきたい構成を整理します。

  • CMakeLists.txt
  • (任意)Kconfig
  • ソースコード
    • nifs/*.c
  • ヘッダファイル
    • nifs/include/*.h

CMakeLists.txt

CMakeLists.txt でやりたいことは、主に 2 つです。

  1. C ファイルを ESP-IDF のコンポーネントとして登録する(idf_component_register
  2. リンク時に登録コードが落ちないようにする(--whole-archive を効かせる)

まず、コンポーネント登録はこの形になります。

idf_component_register(
    SRCS ${SAMPLE_APP_HELLO_COMPONENT_SRCS}
    INCLUDE_DIRS "nifs/include"
    PRIV_REQUIRES "libatomvm" "avm_sys"
)

リンク時に参照されていないと判断されると、NIF 登録コードごと最終成果物から消えることがあるようです。

自分の場合は、次のように --whole-archive を明示して回避できました。

idf_build_set_property(
    LINK_OPTIONS "-Wl,--whole-archive;${CMAKE_CURRENT_BINARY_DIR}/lib${COMPONENT_NAME}.a;-Wl,--no-whole-archive"
    APPEND
)

Kconfig

Kconfig は必須ではありませんが、idf.py menuconfig からコンポーネントの ON/OFF を切り替えられるので、切り分けが楽になります。

重要なのはKconfig の config FOO は C 側では CONFIG_FOO になることです。ここが一致していないと、設定を有効にしても登録コードがコンパイルされません。

たとえば Kconfig が次の定義なら、

config AVM_SAMPLE_APP_HELLO_NIF_ENABLE
    bool "Enable sample hello NIF"
    default n

C 側はこの名前になります。

#ifdef CONFIG_AVM_SAMPLE_APP_HELLO_NIF_ENABLE
REGISTER_NIF_COLLECTION(
    sample_app_hello,
    sample_app_hello_init,
    sample_app_hello_destroy,
    sample_app_hello_get_nif
)
#endif

自分はここが不一致になっていて、結果として REGISTER_NIF_COLLECTION(...) がビルドに入っていませんでした。menuconfig で有効にしても変化がない場合、まずここを疑うのが早そうです。

NIF 名

AtomVM が NIF を探すときのキーは文字列です。1 文字でも違うと解決されません。

基本形は次のとおりです。

"Elixir.モジュール名:関数名/アリティ"

おわりに

AtomVM(ESP32)は ESP-IDF のコンポーネントとして組み立てられているため、自作 NIF もその流儀に合わせて追加するのが近道でした。

そしてNIF がロードされない問題は、NIF 実装そのものよりも、部品の組み込み(リンク、Kconfig、名前)で起きることが多い、というのが今回の学びでした。

🎌 🎌 🎌

3
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
3
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?