Current section
2 Versions
Jump to
Current section
2 Versions
Compare versions
8
files changed
+170
additions
-36
deletions
| @@ -6,6 +6,8 @@ project(nx_eigen_nif LANGUAGES CXX) | |
| 6 6 | set(ERL_INCLUDE_DIR "" CACHE PATH "Path to Erlang/ERTS include directory (contains erl_nif.h)") |
| 7 7 | set(EIGEN_DIR "" CACHE PATH "Path to Eigen include directory (contains Eigen/)") |
| 8 8 | set(FINE_INCLUDE "" CACHE PATH "Path to Fine C include directory (contains fine.hpp)") |
| 9 | + # Output directory for the NIF .so (passed as MIX_APP_PATH/priv by elixir_make) |
| 10 | + set(APP_PRIV "" CACHE PATH "Output priv directory (set by elixir_make via MIX_APP_PATH)") |
| 9 11 | |
| 10 12 | set(CMAKE_CXX_STANDARD 17) |
| 11 13 | set(CMAKE_CXX_STANDARD_REQUIRED ON) |
| @@ -24,9 +26,16 @@ set_target_properties(nx_eigen PROPERTIES | |
| 24 26 | SUFFIX ".so" # Erlang loads NIFs as .so even on macOS |
| 25 27 | ) |
| 26 28 | |
| 27 | - # Always place the built NIF exactly where :code.priv_dir expects it. |
| 29 | + # Place the built NIF where elixir_make/cc_precompiler expect it. |
| 30 | + # APP_PRIV is passed by the Makefile when MIX_APP_PATH is set (elixir_make sets it). |
| 31 | + # Fall back to ${CMAKE_SOURCE_DIR}/priv for standalone cmake invocations. |
| 32 | + if(NOT APP_PRIV STREQUAL "") |
| 33 | + set(NIF_OUTPUT_DIR "${APP_PRIV}") |
| 34 | + else() |
| 35 | + set(NIF_OUTPUT_DIR "${CMAKE_SOURCE_DIR}/priv") |
| 36 | + endif() |
| 28 37 | set_target_properties(nx_eigen PROPERTIES |
| 29 | - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/priv" |
| 38 | + LIBRARY_OUTPUT_DIRECTORY "${NIF_OUTPUT_DIR}" |
| 30 39 | ) |
| 31 40 | |
| 32 41 | target_compile_options(nx_eigen PRIVATE -O3) |
| @@ -15,7 +15,7 @@ endif | |
| 15 15 | EIGEN_VERSION = 3.4.0 |
| 16 16 | EIGEN_DIR ?= $(CURDIR)/eigen-$(EIGEN_VERSION) |
| 17 17 | EIGEN_INCLUDE = $(EIGEN_DIR) |
| 18 | - FINE_INCLUDE = $(CURDIR)/deps/fine/c_include |
| 18 | + FINE_INCLUDE ?= $(error FINE_INCLUDE is not set. Use mix compile instead of bare make.) |
| 19 19 | |
| 20 20 | # FFT library choice |
| 21 21 | # The NIF calls a pluggable C interface (see c_src/nx_eigen_fft.h). |
| @@ -32,7 +32,7 @@ NX_EIGEN_FFT_LIB ?= fftw | |
| 32 32 | NX_EIGEN_FFT_SO ?= |
| 33 33 | |
| 34 34 | CFLAGS = -fPIC -I$(ERL_INCLUDE_DIR) -I$(EIGEN_INCLUDE) -I$(FINE_INCLUDE) -Ic_src -O3 -std=c++17 |
| 35 | - LDFLAGS = -shared |
| 35 | + LDFLAGS = -shared -fvisibility=hidden |
| 36 36 | |
| 37 37 | # Resolve FFT sources and link flags |
| 38 38 | FFT_SRCS = |
| @@ -88,7 +88,11 @@ else | |
| 88 88 | LDFLAGS += -Wl,-rpath,'$$ORIGIN' -Wl,-rpath,'$$ORIGIN/../lib' |
| 89 89 | endif |
| 90 90 | |
| 91 | - LIB_NAME = priv/libnx_eigen.so |
| 91 | + # When invoked by elixir_make, MIX_APP_PATH points to _build/env/lib/app. |
| 92 | + # Writing the .so there (rather than project-root priv/) is required so that |
| 93 | + # cc_precompiler can find the artifact when building the release tarball. |
| 94 | + PRIV_DIR = $(if $(MIX_APP_PATH),$(MIX_APP_PATH)/priv,priv) |
| 95 | + LIB_NAME = $(PRIV_DIR)/libnx_eigen.so |
| 92 96 | |
| 93 97 | # Optional CMake build (useful for cross-compilation via toolchain files) |
| 94 98 | USE_CMAKE ?= 0 |
| @@ -99,7 +103,7 @@ CMAKE_TOOLCHAIN_FILE ?= | |
| 99 103 | CMAKE_ARGS ?= |
| 100 104 | SKIP_DOWNLOADS ?= 0 |
| 101 105 | |
| 102 | - all: check-deps priv $(LIB_NAME) |
| 106 | + all: check-deps $(PRIV_DIR) $(LIB_NAME) |
| 103 107 | |
| 104 108 | # Check dependencies without rebuilding |
| 105 109 | check-deps: |
| @@ -109,17 +113,19 @@ check-deps: | |
| 109 113 | (echo "Failed to download Eigen. Please install manually or set EIGEN_DIR=/path/to/eigen"; exit 1); \ |
| 110 114 | fi |
| 111 115 | |
| 112 | - priv: |
| 116 | + $(PRIV_DIR): |
| 113 117 | @mkdir -p priv |
| 118 | + @mkdir -p "$(PRIV_DIR)" |
| 114 119 | |
| 115 | - $(LIB_NAME): c_src/nx_eigen_nif.cpp c_src/nx_eigen_fft.h $(FFT_SRCS) | check-deps priv |
| 120 | + $(LIB_NAME): c_src/nx_eigen_nif.cpp c_src/nx_eigen_fft.h $(FFT_SRCS) | check-deps $(PRIV_DIR) |
| 116 121 | ifeq ($(USE_CMAKE),1) |
| 117 122 | $(CMAKE) -S $(CURDIR) -B $(CMAKE_BUILD_DIR) -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) \ |
| 118 123 | $(if $(CMAKE_TOOLCHAIN_FILE),-DCMAKE_TOOLCHAIN_FILE=$(CMAKE_TOOLCHAIN_FILE),) \ |
| 119 124 | $(CMAKE_ARGS) \ |
| 120 125 | -DERL_INCLUDE_DIR=$(ERL_INCLUDE_DIR) -DEIGEN_DIR=$(EIGEN_DIR) -DFINE_INCLUDE=$(FINE_INCLUDE) \ |
| 121 126 | -DNX_EIGEN_FFT_LIB=$(NX_EIGEN_FFT_LIB) \ |
| 122 | - $(if $(NX_EIGEN_FFT_SO),-DNX_EIGEN_FFT_SO=$(NX_EIGEN_FFT_SO),) |
| 127 | + $(if $(NX_EIGEN_FFT_SO),-DNX_EIGEN_FFT_SO=$(NX_EIGEN_FFT_SO),) \ |
| 128 | + $(if $(MIX_APP_PATH),-DAPP_PRIV=$(MIX_APP_PATH)/priv,) |
| 123 129 | $(CMAKE) --build $(CMAKE_BUILD_DIR) --config $(CMAKE_BUILD_TYPE) --parallel |
| 124 130 | else |
| 125 131 | $(CXX) $(CFLAGS) $(FFT_CFLAGS) c_src/nx_eigen_nif.cpp $(FFT_SRCS) $(LDFLAGS) $(FFT_LDFLAGS) -o $(LIB_NAME) |
| @@ -1,6 +1,22 @@ | |
| 1 1 | # NxEigen |
| 2 2 | |
| 3 | - An Elixir Nx backend that binds the [Eigen C++ library](https://eigen.tuxfamily.org) for efficient numerical computing on embedded systems, specifically targeting the Arduino Uno Q. |
| 3 | + [](https://github.com/polvalente/nx_eigen/actions/workflows/ci.yml) |
| 4 | + [](https://hex.pm/packages/nx_eigen) |
| 5 | + [](https://hexdocs.pm/nx_eigen) |
| 6 | + |
| 7 | + **High-performance numerical computing for Elixir on embedded systems.** |
| 8 | + |
| 9 | + NxEigen is an [Nx](https://github.com/elixir-nx/nx) backend that binds the [Eigen C++ library](https://eigen.tuxfamily.org) to provide efficient linear algebra and tensor operations. It's specifically optimized for embedded Linux systems like the Arduino Uno Q, bringing BLAS-like performance without external dependencies. |
| 10 | + |
| 11 | + ## Why NxEigen? |
| 12 | + |
| 13 | + - **Native performance**: C++ implementation with Eigen's optimized matrix operations |
| 14 | + - **Embedded-ready**: Designed for resource-constrained devices; no heavy dependencies |
| 15 | + - **Complete Nx integration**: Drop-in replacement for other Nx backends |
| 16 | + - **Hardware acceleration**: Optimized builds for ARM platforms (NEON, crypto extensions) |
| 17 | + - **Zero-dependency math**: Includes static-linked FFTW3 in precompiled binaries |
| 18 | + |
| 19 | + Perfect for running machine learning inference, signal processing, and control algorithms on edge devices. |
| 4 20 | |
| 5 21 | ## Features |
| 6 22 | |
| @@ -384,29 +400,20 @@ Check you have the optimized binary: | |
| 384 400 | ls ~/.cache/elixir_make/nx_eigen-nif-* |
| 385 401 | ``` |
| 386 402 | |
| 387 | - ### Documentation |
| 388 | - |
| 389 | - - **[ARDUINO_UNO_Q_QUICKSTART.md](ARDUINO_UNO_Q_QUICKSTART.md)** - TL;DR setup guide |
| 390 | - - **[ARDUINO_UNO_Q.md](ARDUINO_UNO_Q.md)** - Complete deployment guide with examples |
| 391 | - - **[TARGET_DETECTION_ISSUE.md](TARGET_DETECTION_ISSUE.md)** - Technical details on target detection |
| 392 | - |
| 393 403 | ## License |
| 394 404 | |
| 395 405 | Copyright (c) 2025 |
| 396 406 | |
| 397 407 | ## Documentation |
| 398 408 | |
| 399 | - ### Quick Links |
| 409 | + Full API documentation is available on [HexDocs](https://hexdocs.pm/nx_eigen). |
| 400 410 | |
| 401 | - - **[Arduino Uno Q Setup](ARDUINO_UNO_Q_QUICKSTART.md)** - Arduino Uno Q quick start guide |
| 402 | - - **[Precompilation Guide](PRECOMPILATION.md)** - Building precompiled binaries |
| 403 | - - **[Testing Precompiled Binaries](TESTING_PRECOMPILED.md)** - Testing precompiled binaries |
| 404 | - - **[Documentation Index](DOCUMENTATION_INDEX.md)** - Complete documentation overview |
| 405 | - |
| 406 | - ### API Documentation |
| 407 | - |
| 408 | - Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc): |
| 411 | + You can also generate documentation locally: |
| 409 412 | |
| 410 413 | ```bash |
| 411 414 | mix docs |
| 412 415 | ``` |
| 416 | + |
| 417 | + ### Additional Guides |
| 418 | + |
| 419 | + - **[Precompilation Guide](PRECOMPILATION.md)** - Building precompiled binaries for different platforms |
| @@ -1,7 +1,4 @@ | |
| 1 1 | %{ |
| 2 | - "nx_eigen-nif-2.17-aarch64-apple-darwin-0.1.0.tar.gz" => "sha256:19b2434ada585bdd8625a6a6efe51356155bc669a02f23d40228fc170c1c2c58", |
| 3 | - "nx_eigen-nif-2.17-aarch64-arduino-uno-q-linux-gnu-0.1.0.tar.gz" => "sha256:bf7297d3e55001a334aa49b39774a4f7619ba4155d1f8e1be90154e7e3f728b6", |
| 4 | - "nx_eigen-nif-2.17-aarch64-linux-gnu-0.1.0.tar.gz" => "sha256:d8d276ed2e8f5b18d2f91fbcf763faa0f9a998bded7095e973d786efced9255d", |
| 5 | - "nx_eigen-nif-2.17-x86_64-apple-darwin-0.1.0.tar.gz" => "sha256:1384fd7e53f322014ff3d5fbe69e2c696cd388f93fd8979bed8d698eb220e507", |
| 6 | - "nx_eigen-nif-2.17-x86_64-linux-gnu-0.1.0.tar.gz" => "sha256:e464b27433774f3e677d8fde15c570878d394b6b10e2098198271a621fbb2885", |
| 2 | + "nx_eigen-nif-2.17-aarch64-apple-darwin-0.1.1.tar.gz" => "sha256:786d066780e6db1570c047b7d3d0770a28387d1bfed34f62febf376d7a785b50", |
| 3 | + "nx_eigen-nif-2.17-aarch64-linux-gnu-0.1.1.tar.gz" => "sha256:6e735ff76220f83433bc02f382a91d4c21ff4ff581ede39f917c5430d5d785ac", |
| 7 4 | } |
| @@ -1,6 +1,6 @@ | |
| 1 1 | {<<"links">>,[{<<"GitHub">>,<<"https://github.com/polvalente/nx_eigen">>}]}. |
| 2 2 | {<<"name">>,<<"nx_eigen">>}. |
| 3 | - {<<"version">>,<<"0.1.0">>}. |
| 3 | + {<<"version">>,<<"0.1.1">>}. |
| 4 4 | {<<"description">>, |
| 5 5 | <<"High-performance numerical computing with Eigen backend">>}. |
| 6 6 | {<<"elixir">>,<<"~> 1.18">>}. |
Loading more files…