Packages

MLX machine learning framework bindings for Erlang

Current section

Files

Jump to
mlx c_src Makefile
Raw

c_src/Makefile

# MLX Erlang NIF Makefile
# Detect OS
UNAME_S := $(shell uname -s)
# Compiler
CXX = clang++
CC = clang
# C++ Standard
CXXSTD = -std=c++17
# Optimization
OPTIMIZE = -O3 -DNDEBUG
# Warning flags
WARNINGS = -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers
# Debug flags (for debug builds)
DEBUG_FLAGS = -g -DDEBUG
# Erlang/OTP paths
ERL_INTERFACE_DIR = $(shell erl -eval 'io:format("~s~n", [code:lib_dir(erl_interface)])' -s init stop -noshell)
ERTS_DIR = $(shell erl -eval 'io:format("~s~n", [code:root_dir()])' -s init stop -noshell)/erts-$(shell erl -eval 'io:format("~s~n", [erlang:system_info(version)])' -s init stop -noshell)
# Include directories
INCLUDES = -I$(ERL_INTERFACE_DIR)/include \
-I$(ERTS_DIR)/include
# Platform-specific settings
ifeq ($(UNAME_S),Darwin)
# macOS settings
INCLUDES += -I/opt/homebrew/include \
-I/usr/local/include \
-I/opt/homebrew/include/mlx
LDFLAGS = -L/opt/homebrew/lib \
-L/usr/local/lib \
-lmlx \
-framework Accelerate \
-framework Metal \
-framework MetalKit \
-framework MetalPerformanceShaders \
-framework Foundation \
-undefined dynamic_lookup \
-shared
# Universal binary support
ARCH_FLAGS = -arch arm64 -arch x86_64
SO_EXT = .so
SHARED_FLAGS = -fPIC -shared
endif
ifeq ($(UNAME_S),Linux)
# Linux settings
INCLUDES += -I/usr/local/include \
-I/usr/include/mlx \
-I/usr/local/cuda/include
LDFLAGS = -L/usr/local/lib \
-L/usr/local/cuda/lib64 \
-lmlx \
-lm \
-lpthread \
-lcudart \
-lcublas \
-shared
SO_EXT = .so
SHARED_FLAGS = -fPIC -shared
endif
# Compiler flags
CXXFLAGS = $(CXXSTD) $(OPTIMIZE) $(WARNINGS) $(INCLUDES) $(SHARED_FLAGS) $(ARCH_FLAGS)
CFLAGS = $(OPTIMIZE) $(WARNINGS) $(INCLUDES) $(SHARED_FLAGS) $(ARCH_FLAGS)
# Source files
CPP_SOURCES = mlx_nif.cpp \
mlx_advanced_nif.cpp \
mlx_nn_nif.cpp \
mlx_optimizers_nif.cpp \
mlx_random_nif.cpp \
mlx_transforms_nif.cpp \
mlx_fft_nif.cpp \
mlx_io_nif.cpp \
mlx_streaming_nif.cpp \
mlx_metal_kernels.cpp
# Object files
OBJECTS = $(CPP_SOURCES:.cpp=.o)
# Target library
TARGET = ../priv/mlx_nif$(SO_EXT)
# Default target
all: $(TARGET)
# Create priv directory if it doesn't exist
../priv:
mkdir -p ../priv
# Build the shared library
$(TARGET): ../priv $(OBJECTS)
$(CXX) $(OBJECTS) -o $@ $(LDFLAGS)
@echo "Built MLX NIF: $@"
# Compile C++ source files
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
# Debug build
debug: CXXFLAGS += $(DEBUG_FLAGS)
debug: OPTIMIZE = -O0
debug: $(TARGET)
# Clean build artifacts
clean:
rm -f *.o $(TARGET)
@echo "Cleaned build artifacts"
# Install MLX dependencies (macOS with Homebrew)
install-deps-macos:
brew install mlx
@echo "Installed MLX dependencies for macOS"
# Install MLX dependencies (Linux)
install-deps-linux:
# This would typically involve building MLX from source
@echo "Please install MLX from source on Linux"
@echo "See: https://github.com/ml-explore/mlx"
# Check if MLX is available
check-mlx:
@echo "Checking for MLX installation..."
ifeq ($(UNAME_S),Darwin)
@if [ -f /opt/homebrew/lib/libmlx.dylib ] || [ -f /usr/local/lib/libmlx.dylib ]; then \
echo "✓ MLX found"; \
else \
echo "✗ MLX not found. Run 'make install-deps-macos'"; \
exit 1; \
fi
endif
ifeq ($(UNAME_S),Linux)
@if [ -f /usr/local/lib/libmlx.so ]; then \
echo "✓ MLX found"; \
else \
echo "✗ MLX not found. Please install MLX from source"; \
exit 1; \
fi
endif
# Test the NIF
test: $(TARGET)
cd .. && rebar3 eunit
# Format code
format:
clang-format -i *.cpp *.h
# Static analysis
analyze:
clang-static-analyzer $(CXXFLAGS) $(CPP_SOURCES)
# Memory check (requires valgrind on Linux)
memcheck: $(TARGET)
ifeq ($(UNAME_S),Linux)
cd .. && valgrind --tool=memcheck --leak-check=full erl -pa _build/default/lib/*/ebin -eval "mlx_nif:test_basic()" -s init stop
else
@echo "Memory checking with valgrind is only available on Linux"
endif
# Benchmark build (optimized for performance)
benchmark: OPTIMIZE = -O3 -march=native -mtune=native -DNDEBUG
benchmark: $(TARGET)
# Profile build (with profiling symbols)
profile: CXXFLAGS += -pg
profile: LDFLAGS += -pg
profile: $(TARGET)
# Print build configuration
config:
@echo "Build Configuration:"
@echo " OS: $(UNAME_S)"
@echo " Compiler: $(CXX)"
@echo " C++ Standard: $(CXXSTD)"
@echo " Optimization: $(OPTIMIZE)"
@echo " Includes: $(INCLUDES)"
@echo " LDFLAGS: $(LDFLAGS)"
@echo " Target: $(TARGET)"
# Help
help:
@echo "MLX Erlang NIF Build System"
@echo ""
@echo "Targets:"
@echo " all - Build the NIF library (default)"
@echo " debug - Build with debug symbols"
@echo " clean - Remove build artifacts"
@echo " check-mlx - Check if MLX is installed"
@echo " install-deps-macos - Install MLX via Homebrew (macOS)"
@echo " install-deps-linux - Instructions for Linux"
@echo " test - Build and run tests"
@echo " format - Format source code"
@echo " analyze - Run static analysis"
@echo " memcheck - Run memory leak detection (Linux only)"
@echo " benchmark - Build optimized for benchmarking"
@echo " profile - Build with profiling enabled"
@echo " config - Show build configuration"
@echo " help - Show this help"
# Dependencies
mlx_nif.o: mlx_nif.cpp mlx_nif.h
mlx_advanced_nif.o: mlx_advanced_nif.cpp mlx_nif.h
mlx_nn_nif.o: mlx_nn_nif.cpp mlx_nif.h
mlx_optimizers_nif.o: mlx_optimizers_nif.cpp mlx_nif.h
mlx_random_nif.o: mlx_random_nif.cpp mlx_nif.h
mlx_transforms_nif.o: mlx_transforms_nif.cpp mlx_nif.h
mlx_fft_nif.o: mlx_fft_nif.cpp mlx_nif.h
mlx_io_nif.o: mlx_io_nif.cpp mlx_nif.h
mlx_streaming_nif.o: mlx_streaming_nif.cpp mlx_nif.h
mlx_metal_kernels.o: mlx_metal_kernels.cpp mlx_nif.h
.PHONY: all debug clean install-deps-macos install-deps-linux check-mlx test format analyze memcheck benchmark profile config help