Packages

Signal Protocol cryptographic primitives NIF implementation

Current section

Files

Jump to
libsignal_protocol_nif c_src build_nif.sh
Raw

c_src/build_nif.sh

#!/bin/sh
# c_src/build_nif.sh
#
# Runs at consumer compile time via the post-compile hook in rebar.config.
# Skips if the NIF binaries are already present. Otherwise:
# 1. Detects the platform triplet via uname.
# 2. Tries to download the matching pre-built tarball from this version's
# GitHub Release.
# 3. Falls back to cmake + make in c_src/ if the download fails, the
# platform isn't supported, or LIBSIGNAL_NIF_BUILD_FROM_SOURCE=1 is set.
#
# The script ships inside the Hex tarball under c_src/ so it's available to
# downstream consumers as well as to local dev builds.
set -e
# Repo coordinates for the GitHub Release that hosts the pre-built tarballs.
REPO="Hydepwns/libsignal-protocol-nif"
# Resolve the project root from the script location. Works whether the script
# is invoked from the project root or from a deps tree.
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
# Read VERSION; missing or empty means we can't build a release URL, so we
# skip the download and go straight to source build.
VERSION=""
if [ -f "${PROJECT_ROOT}/VERSION" ]; then
VERSION="$(cat "${PROJECT_ROOT}/VERSION" | tr -d '[:space:]')"
fi
# Skip everything if the NIF binaries are already in priv/.
if [ -f "${PROJECT_ROOT}/priv/signal_nif.so" ] && \
[ -f "${PROJECT_ROOT}/priv/libsignal_protocol_nif.so" ]; then
exit 0
fi
mkdir -p "${PROJECT_ROOT}/priv"
# Detect target triplet. Match what the release workflow names its tarballs.
SYSTEM="$(uname -s)"
MACHINE="$(uname -m)"
TRIPLET=""
EXT=""
case "${SYSTEM}-${MACHINE}" in
Darwin-arm64) TRIPLET="aarch64-apple-darwin" ;;
Darwin-x86_64) TRIPLET="x86_64-apple-darwin" ;;
Linux-aarch64) TRIPLET="aarch64-unknown-linux-gnu" ;;
Linux-arm64) TRIPLET="aarch64-unknown-linux-gnu" ;;
Linux-x86_64) TRIPLET="x86_64-unknown-linux-gnu" ;;
esac
# NIFs emit .so on every platform we support (BEAM looks for .so on macOS too).
EXT="so"
# Try the pre-built download unless explicitly opted out.
if [ -n "${TRIPLET}" ] && [ -n "${VERSION}" ] && \
[ -z "${LIBSIGNAL_NIF_BUILD_FROM_SOURCE:-}" ] && \
command -v curl >/dev/null 2>&1; then
NAME="libsignal_protocol_nif-${TRIPLET}-${VERSION}"
URL="https://github.com/${REPO}/releases/download/v${VERSION}/${NAME}.tar.gz"
TMP="/tmp/${NAME}.$$"
echo "Fetching pre-built NIF: ${URL}"
if curl -fsSL -o "${TMP}.tar.gz" "${URL}" 2>/dev/null; then
mkdir -p "${TMP}"
if tar -xzf "${TMP}.tar.gz" -C "${TMP}" 2>/dev/null; then
cp "${TMP}/${NAME}/signal_nif.${EXT}" "${PROJECT_ROOT}/priv/"
cp "${TMP}/${NAME}/libsignal_protocol_nif.${EXT}" "${PROJECT_ROOT}/priv/"
rm -rf "${TMP}" "${TMP}.tar.gz"
echo "Pre-built NIF installed for ${TRIPLET}."
exit 0
fi
rm -rf "${TMP}" "${TMP}.tar.gz"
fi
echo "Pre-built download unavailable; falling back to source build."
fi
# Source build fallback. Requires cmake + libsodium + openssl headers on the
# system; on macOS the keg-only openssl@3 needs DYLD_LIBRARY_PATH at run time.
if ! command -v cmake >/dev/null 2>&1; then
echo "ERROR: cmake not found and no pre-built binary available."
echo " Install cmake, libsodium-dev, and libssl-dev (Debian) or"
echo " brew install libsodium openssl@3 cmake (macOS)."
echo " Or download a release tarball manually from"
echo " https://github.com/${REPO}/releases"
exit 1
fi
echo "Building NIF from source in c_src/..."
cd "${PROJECT_ROOT}/c_src"
cmake . -DCMAKE_BUILD_TYPE=Release
make
# Clean in-tree cmake droppings so they don't pollute future rebar3 hex builds.
rm -rf CMakeFiles CMakeCache.txt cmake_install.cmake Makefile
echo "Source build complete."