NervesでEXLAを使えるようにしたい。
exlaを追加して、XLA_TARGET_PLATFORMをaarch64-linux-gnuを指定することで、Nervesのファームウエアをビルドする事ができました。
やったこと
export XLA_TARGET=cpu
export XLA_TARGET_PLATFORM=aarch64-linux-gnu
export MIX_TARGET=rpi4
nerves livebookのレポジトリーをcloneする
depsに
{:exla, "~> 0.8.0"}
を追加
mix firmwareを実行
実機での動作は未確認ですが、ファームの作成はできました
Raspi Zeroの場合
当初、Raspi ZeroでNxを使用したくて、
MIX_TARGET=rpi0
でビルドをしていました。
これだと、以下のようなエラーが発生し、ビルドできませんでせいた。
CPUがARMv6で、aarch64-linux-gnuに適合していないためではないかと思います。
rpi0でのビルドは以下の試行錯誤をしてみましたが、ダメでした。
~~~省略~~~
/home/masa/.nerves/artifacts/nerves_toolchain_armv6_nerves_linux_gnueabihf-linux_x86_64-13.2.0/bin/armv6-nerves-linux-gnueabihf-g++ -fPIC -I/home/masa/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include -Icache/xla_extension/include -Wall -Wno-sign-compare -Wno-unused-parameter -Wno-missing-field-initializers -Wno-comment -std=c++17 -w -DLLVM_VERSION_STRING= -O3 -c c_src/exla/exla_cuda.cc -o cache/objs/exla_cuda.o
c_src/exla/exla_nif_util.cc: In function 'int exla::nif::get(ErlNifEnv*, ERL_NIF_TERM, exla::int64*)':
c_src/exla/exla_nif_util.cc:51:25: error: cannot convert 'nif_int64_t*' {aka 'long int*'} to 'ErlNifSInt64*' {aka 'long long int*'}
51 | reinterpret_cast<nif_int64_t*>(var));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| nif_int64_t* {aka long int*}
In file included from c_src/exla/exla_nif_util.h:11,
from c_src/exla/exla_nif_util.cc:1:
/home/masa/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include/erl_nif_api_funcs.h:134:88: note: initializing argument 3 of 'int enif_get_int64(ErlNifEnv*, ERL_NIF_TERM, ErlNifSInt64*)'
134 | ERL_NIF_API_FUNC_DECL(int,enif_get_int64,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifSInt64* ip));
| ~~~~~~~~~~~~~~^~
/home/masa/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include/erl_nif.h:371:76: note: in definition of macro 'ERL_NIF_API_FUNC_DECL'
371 | # define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) extern RET_TYPE NAME ARGS
| ^~~~
c_src/exla/exla_nif_util.cc: In function 'int exla::nif::get(ErlNifEnv*, ERL_NIF_TERM, exla::uint64*)':
c_src/exla/exla_nif_util.cc:75:26: error: cannot convert 'nif_uint64_t*' {aka 'long unsigned int*'} to 'ErlNifUInt64*' {aka 'long long unsigned int*'}
75 | reinterpret_cast<nif_uint64_t*>(var));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| nif_uint64_t* {aka long unsigned int*}
/home/masa/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include/erl_nif_api_funcs.h:135:89: note: initializing argument 3 of 'int enif_get_uint64(ErlNifEnv*, ERL_NIF_TERM, ErlNifUInt64*)'
135 | ERL_NIF_API_FUNC_DECL(int,enif_get_uint64,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifUInt64* ip));
| ~~~~~~~~~~~~~~^~
/home/masa/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include/erl_nif.h:371:76: note: in definition of macro 'ERL_NIF_API_FUNC_DECL'
371 | # define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) extern RET_TYPE NAME ARGS
| ^~~~
make: *** [Makefile:87: cache/objs/exla_nif_util.o] ã¨ã©ã¼ 1
make: *** æªå®äºã®ã¸ã§ããå¾
ã£ã¦ã
ã¾ã....
In file included from cache/xla_extension/include/xla/pjrt/pjrt_future.h:29,
from cache/xla_extension/include/xla/pjrt/pjrt_client.h:47,
from c_src/exla/exla_client.h:14,
from c_src/exla/exla_client.cc:1:
cache/xla_extension/include/xla/tsl/concurrency/async_value.h:388:45: error: static assertion failed
388 | sizeof(NotifierListNode*) == 8);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
cache/xla_extension/include/xla/tsl/concurrency/async_value.h:388:45: note: the comparison reduces to '(4 == 8)'
In file included from cache/xla_extension/include/xla/pjrt/pjrt_future.h:29,
from cache/xla_extension/include/xla/pjrt/pjrt_client.h:47,
from c_src/exla/exla_client.h:14,
from c_src/exla/exla.cc:3:
cache/xla_extension/include/xla/tsl/concurrency/async_value.h:388:45: error: static assertion failed
388 | sizeof(NotifierListNode*) == 8);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
cache/xla_extension/include/xla/tsl/concurrency/async_value.h:388:45: note: the comparison reduces to '(4 == 8)'
型に関するエラーが発生。
XLAをビルドしてみる
XLA自体もコンパイルすれば解決するのではないか?
XLA_BUILD=trueにしてXLA自体Buildする事で解決しないか試してみる。
export XLA_BUILD=true
/bin/sh: 4: bazel: not found
エラーになる
https://github.com/elixir-nx/xla
の手順に従っていれてみる
bazelをインストール。
asdf plugin-add bazel
asdf install bazel 6.5.0
asdf global bazel 6.5.0
python -m venv python_for_xla
pip install numpy
INFO: Analyzed target //xla/extension:xla_extension (154 packages loaded, 13912 targets configured).
INFO: Found 1 target...
checking cached actions
[0 / 1,190] [Prepa] BazelWorkspaceStatusAction stable-status.txt ... (4 actions, 1 running)
[421 / 2,748] Compiling llvm/lib/Demangle/RustDemangle.cpp [for tool]; 0s local ... (16 actions, 15 running)
ERROR: /home/masa/.cache/xla_extension/xla-fd58925adee147d38c25a085354e15427a12d00a/xla/service/cpu/BUILD:1017:11: Compiling xla/service/cpu/runtime_conv2d_acl.cc failed: (Exit 1): armv6-nerves-linux-gnueabihf-gcc failed: error executing command (from target //xla/service/cpu:runtime_conv2d_acl) /home/masa/.nerves/artifacts/nerves_toolchain_armv6_nerves_linux_gnueabihf-linux_x86_64-13.2.0/bin/armv6-nerves-linux-gnueabihf-gcc -U_FORTIFY_SOURCE -fstack-protector -Wall -Wunused-but-set-parameter ... (remaining 133 arguments skipped)
armv6-nerves-linux-gnueabihf-gcc: error: unrecognized command-line option '-msse3'
Target //xla/extension:xla_extension failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 70.276s, Critical Path: 0.97s
INFO: 439 processes: 398 internal, 41 local.
FAILED: Build did NOT complete successfully
make: *** [Makefile:26: /home/masa/.cache/xla/0.8.0/build/xla_extension-0.8.0-aarch64-linux-gnu-cpu.tar.gz] ã¨ã©ã¼ 1
-msse3
X86CPU用のオプションが指定されていて、コンパイルエラーになっている。
XLAのソースに含まれてる、Dockerのビルド環境でビルとしてみる。
XLAのソースに含まれてる、Dockerのビルド環境で
XLA_TARGET_PLATFORM=aarch64-linux-gnu
を指定して、GPU関係の処理をなくして
ビルとしてみる。
~~~省略~~~
[4,268 / 5,521] Compiling mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp; 159s local ... (16 actions running)
[4,269 / 5,521] Compiling mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp; 161s local ... (16 actions, 15 running)
[4,270 / 5,521] Compiling mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp; 163s local ... (16 actions running)
[4,271 / 5,521] Compiling mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp; 164s local ... (16 actions running)
ERROR: /root/.cache/bazel/_bazel_root/1927049d2feb3cbc465f5b0419907c8f/external/llvm-project/mlir/BUILD.bazel:5302:11: Compiling mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp failed: (Exit 1): gcc failed: error executing command (from target @llvm-project//mlir:LLVMDialect) /usr/bin/gcc -U_FORTIFY_SOURCE -fstack-protector -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer -g0 -O2 '-D_FORTIFY_SOURCE=1' -DNDEBUG -ffunction-sections ... (remaining 86 arguments skipped)
gcc: fatal error: Killed signal terminated program cc1plus
compilation terminated.
[4,273 / 5,521] Compiling llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp; 77s local ... (14 actions running)
Target //xla/extension:xla_extension failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 1112.280s, Critical Path: 210.67s
INFO: 4287 processes: 252 internal, 4035 local.
FAILED: Build did NOT complete successfully
make: *** [Makefile:26: /build/0.8.0/build/xla_extension-0.8.0-x86_64-linux-gnu-cpu.tar.gz] Error 1
** (Mix) Could not compile with "make" (exit status: 2).
You need to have gcc and make installed. If you are using
Ubuntu or any other Debian-based system, install the packages
"build-essential". Also install "erlang-dev" package if not
included in your Erlang/OTP version. If you're on Fedora, run
"dnf group install 'Development Tools'".
コンパイルがかなり進んだんだけど、エラーが発生。
EXLAのコンパイル環境を変えてみる
XLAのビルドするのは大変そうなので、XLAのバイナリーを使い、EXLAのビルドでコンパイルエラーがでない環境を模索してみる。
EXLAのビルド環境のコンパイラーがXLAをコンパイルした時の環境と大きく異なってる事が原因ではないか?
XLAのコンパイルは、 between 7.5 and 9.3(https://github.com/elixir-nx/xla)となっている。
Dockerでgcc 8.3.0の環境を作って、そこでmix firmwareを実行してEXLAのビルドをしてみる。
Nerves environment
MIX_TARGET: rpi0
MIX_ENV: dev
02:18:44.182 [info] Downloading a precompiled XLA archive for target aarch64-linux-gnu-cpu
02:18:52.576 [info] Successfully downloaded the XLA archive
==> exla
/root/.nerves/artifacts/nerves_toolchain_armv6_nerves_linux_gnueabihf-linux_x86_64-13.2.0/bin/armv6-nerves-linux-gnueabihf-g++ -fPIC -I/root/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include -Icache/xla_extension/include -Wall -Wno-sign-compare -Wno-unused-parameter -Wno-missing-field-initializers -Wno-comment -std=c++17 -w -DLLVM_VERSION_STRING= -O3 -c c_src/exla/exla.cc -o cache/objs/exla.o
/root/.nerves/artifacts/nerves_toolchain_armv6_nerves_linux_gnueabihf-linux_x86_64-13.2.0/bin/armv6-nerves-linux-gnueabihf-g++ -fPIC -I/root/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include -Icache/xla_extension/include -Wall -Wno-sign-compare -Wno-unused-parameter -Wno-missing-field-initializers -Wno-comment -std=c++17 -w -DLLVM_VERSION_STRING= -O3 -c c_src/exla/exla_client.cc -o cache/objs/exla_client.o
/root/.nerves/artifacts/nerves_toolchain_armv6_nerves_linux_gnueabihf-linux_x86_64-13.2.0/bin/armv6-nerves-linux-gnueabihf-g++ -fPIC -I/root/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include -Icache/xla_extension/include -Wall -Wno-sign-compare -Wno-unused-parameter -Wno-missing-field-initializers -Wno-comment -std=c++17 -w -DLLVM_VERSION_STRING= -O3 -c c_src/exla/exla_nif_util.cc -o cache/objs/exla_nif_util.o
c_src/exla/exla_nif_util.cc: In function 'int exla::nif::get(ErlNifEnv*, ERL_NIF_TERM, exla::int64*)':
c_src/exla/exla_nif_util.cc:51:25: error: cannot convert 'nif_int64_t*' {aka 'long int*'} to 'ErlNifSInt64*' {aka 'long long int*'}
51 | reinterpret_cast<nif_int64_t*>(var));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| nif_int64_t* {aka long int*}
In file included from c_src/exla/exla_nif_util.h:11,
from c_src/exla/exla_nif_util.cc:1:
/root/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include/erl_nif_api_funcs.h:134:88: note: initializing argument 3 of 'int enif_get_int64(ErlNifEnv*, ERL_NIF_TERM, ErlNifSInt64*)'
134 | ERL_NIF_API_FUNC_DECL(int,enif_get_int64,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifSInt64* ip));
| ~~~~~~~~~~~~~~^~
/root/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include/erl_nif.h:371:76: note: in definition of macro 'ERL_NIF_API_FUNC_DECL'
371 | # define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) extern RET_TYPE NAME ARGS
| ^~~~
c_src/exla/exla_nif_util.cc: In function 'int exla::nif::get(ErlNifEnv*, ERL_NIF_TERM, exla::uint64*)':
c_src/exla/exla_nif_util.cc:75:26: error: cannot convert 'nif_uint64_t*' {aka 'long unsigned int*'} to 'ErlNifUInt64*' {aka 'long long unsigned int*'}
75 | reinterpret_cast<nif_uint64_t*>(var));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| nif_uint64_t* {aka long unsigned int*}
/root/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include/erl_nif_api_funcs.h:135:89: note: initializing argument 3 of 'int enif_get_uint64(ErlNifEnv*, ERL_NIF_TERM, ErlNifUInt64*)'
135 | ERL_NIF_API_FUNC_DECL(int,enif_get_uint64,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifUInt64* ip));
| ~~~~~~~~~~~~~~^~
/root/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include/erl_nif.h:371:76: note: in definition of macro 'ERL_NIF_API_FUNC_DECL'
371 | # define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) extern RET_TYPE NAME ARGS
| ^~~~
make: *** [Makefile:87: cache/objs/exla_nif_util.o] Error 1
make: *** Waiting for unfinished jobs....
In file included from cache/xla_extension/include/xla/pjrt/pjrt_future.h:29,
from cache/xla_extension/include/xla/pjrt/pjrt_client.h:47,
from c_src/exla/exla_client.h:14,
from c_src/exla/exla_client.cc:1:
cache/xla_extension/include/xla/tsl/concurrency/async_value.h:388:45: error: static assertion failed
388 | sizeof(NotifierListNode*) == 8);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
cache/xla_extension/include/xla/tsl/concurrency/async_value.h:388:45: note: the comparison reduces to '(4 == 8)'
In file included from cache/xla_extension/include/xla/pjrt/pjrt_future.h:29,
from cache/xla_extension/include/xla/pjrt/pjrt_client.h:47,
from c_src/exla/exla_client.h:14,
from c_src/exla/exla.cc:3:
cache/xla_extension/include/xla/tsl/concurrency/async_value.h:388:45: error: static assertion failed
388 | sizeof(NotifierListNode*) == 8);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
cache/xla_extension/include/xla/tsl/concurrency/async_value.h:388:45: note: the comparison reduces to '(4 == 8)'
make: *** [Makefile:87: cache/objs/exla_client.o] Error 1
make: *** [Makefile:87: cache/objs/exla.o] Error 1
could not compile dependency :exla, "mix compile" failed. Errors may have been logged above. You can recompile this dependency with "mix deps.compile exla --force", update it with "mix deps.update exla" or clean it with "mix deps.clean exla"
==> nerves_livebook
** (Mix) Could not compile with "make" (exit status: 2).
You need to have gcc and make installed. If you are using
Ubuntu or any other Debian-based system, install the packages
"build-essential". Also install "erlang-dev" package if not
included in your Erlang/OTP version. If you're on Fedora, run
"dnf group install 'Development Tools'".
root@30b71ec52b69:/workspaces/docker/nerves_livebook#
コンパイルエラー発生
raspi zero 用のXLA_TARGET_PLATFORMを指定
raspi zero 用のXLA_TARGET_PLATFORMを指定
XLAを別途ビルとして、XLA_ARCHIVE_URLに指定
環境変数は次の通り
XLA_ARCHIVE_URL=http://localhost:8000/xla_extension-0.8.0-arm-linux-gnueabihf-cpu.tar.gz
XLA_TARGET=cpu
XLA_BUILD=false
XLA_TARGET_PLATFORM=arm-linux-gnueabihf
/home/masa/.nerves/artifacts/nerves_toolchain_armv6_nerves_linux_gnueabihf-linux_x86_64-13.2.0/bin/armv6-nerves-linux-gnueabihf-g++ -fPIC -I/home/masa/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include -Icache/xla_extension/include -Wall -Wno-sign-compare -Wno-unused-parameter -Wno-missing-field-initializers -Wno-comment -std=c++17 -w -DLLVM_VERSION_STRING= -O3 -c c_src/exla/exla_cuda.cc -o cache/objs/exla_cuda.o
c_src/exla/exla_nif_util.cc: In function 'int exla::nif::get(ErlNifEnv*, ERL_NIF_TERM, exla::int64*)':
c_src/exla/exla_nif_util.cc:51:25: error: cannot convert 'nif_int64_t*' {aka 'long int*'} to 'ErlNifSInt64*' {aka 'long long int*'}
51 | reinterpret_cast<nif_int64_t*>(var));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| nif_int64_t* {aka long int*}
In file included from c_src/exla/exla_nif_util.h:11,
from c_src/exla/exla_nif_util.cc:1:
/home/masa/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include/erl_nif_api_funcs.h:134:88: note: initializing argument 3 of 'int enif_get_int64(ErlNifEnv*, ERL_NIF_TERM, ErlNifSInt64*)'
134 | ERL_NIF_API_FUNC_DECL(int,enif_get_int64,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifSInt64* ip));
| ~~~~~~~~~~~~~~^~
/home/masa/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include/erl_nif.h:371:76: note: in definition of macro 'ERL_NIF_API_FUNC_DECL'
371 | # define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) extern RET_TYPE NAME ARGS
| ^~~~
c_src/exla/exla_nif_util.cc: In function 'int exla::nif::get(ErlNifEnv*, ERL_NIF_TERM, exla::uint64*)':
c_src/exla/exla_nif_util.cc:75:26: error: cannot convert 'nif_uint64_t*' {aka 'long unsigned int*'} to 'ErlNifUInt64*' {aka 'long long unsigned int*'}
75 | reinterpret_cast<nif_uint64_t*>(var));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| nif_uint64_t* {aka long unsigned int*}
/home/masa/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include/erl_nif_api_funcs.h:135:89: note: initializing argument 3 of 'int enif_get_uint64(ErlNifEnv*, ERL_NIF_TERM, ErlNifUInt64*)'
135 | ERL_NIF_API_FUNC_DECL(int,enif_get_uint64,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifUInt64* ip));
| ~~~~~~~~~~~~~~^~
/home/masa/.nerves/artifacts/nerves_system_rpi0-portable-1.28.0/staging/usr/lib/erlang/erts-15.0/include/erl_nif.h:371:76: note: in definition of macro 'ERL_NIF_API_FUNC_DECL'
371 | # define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) extern RET_TYPE NAME ARGS
| ^~~~
make: *** [Makefile:87: cache/objs/exla_nif_util.o] ã¨ã©ã¼ 1
make: *** æªå®äºã®ã¸ã§ããå¾ã£ã¦ãã¾ã....
In file included from cache/xla_extension/include/xla/pjrt/pjrt_future.h:29,
from cache/xla_extension/include/xla/pjrt/pjrt_client.h:47,
from c_src/exla/exla_client.h:14,
from c_src/exla/exla_client.cc:1:
cache/xla_extension/include/xla/tsl/concurrency/async_value.h:388:45: error: static assertion failed
388 | sizeof(NotifierListNode*) == 8);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
cache/xla_extension/include/xla/tsl/concurrency/async_value.h:388:45: note: the comparison reduces to '(4 == 8)'
In file included from cache/xla_extension/include/xla/pjrt/pjrt_future.h:29,
from cache/xla_extension/include/xla/pjrt/pjrt_client.h:47,
from c_src/exla/exla_client.h:14,
from c_src/exla/exla.cc:3:
cache/xla_extension/include/xla/tsl/concurrency/async_value.h:388:45: error: static assertion failed
388 | sizeof(NotifierListNode*) == 8);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
cache/xla_extension/include/xla/tsl/concurrency/async_value.h:388:45: note: the comparison reduces to '(4 == 8)'
make: *** [Makefile:85: cache/objs/exla_client.o] ã¨ã©ã¼ 1
make: *** [Makefile:85: cache/objs/exla.o] ã¨ã©ã¼ 1
could not compile dependency :exla, "mix compile" failed. Errors may have been logged above. You can recompile this dependency with "mix deps.compile exla --force", update it with "mix deps.update exla" or clean it with "mix deps.clean exla"
==> nerves_livebook
** (Mix) Could not compile with "make" (exit status: 2).
You need to have gcc and make installed. If you are using
Ubuntu or any other Debian-based system, install the packages
"build-essential". Also install "erlang-dev" package if not
included in your Erlang/OTP version. If you're on Fedora, run
"dnf group install 'Development Tools'".