Skip to content

Merge branch 'main-dev' #281

Merge branch 'main-dev'

Merge branch 'main-dev' #281

Workflow file for this run

name: Release
on:
push:
branches: ["main"]
env:
GH_TOKEN: ${{ secrets.SEMANTIC_RELEASE_TOKEN }}
PYTHONUTF8: 1
PYTHON_VERSION: 3.11
DOTNET_VERSION: 8.0.x
NODE_VERSION: 20
JAVA_VERSION: 21
GO_VERSION: "^1.21.0"
ANDROID_NDK_VERSION: 26.3.11579264
ANDROID_SDK_VERSION: 21
EMSCRIPTEN_VERSION: 3.1.47
MINGW_VERSION: 12.2.0
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: write
pages: write
id-token: write
packages: write
jobs:
versioning:
name: Update Version
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
persist-credentials: false
- name: Run TinySemVer
uses: ashvardanian/tinysemver@v3.0.0
with:
verbose: "true"
version-file: "VERSION"
update-version-in: |
package.json:"version": "(\d+\.\d+\.\d+)"
package-lock.json:"usearch",\n\s+"version": "(\d+\.\d+\.\d+)"
CITATION.cff:^version: (\d+\.\d+\.\d+)
Cargo.toml:^version = "(\d+\.\d+\.\d+)"
Cargo.lock:name = "usearch"\nversion = "(\d+\.\d+\.\d+)"
wasmer.toml:^version = "(\d+\.\d+\.\d+)"
conanfile.py:version = "(\d+\.\d+\.\d+)"
java/README.md:usearchVersion = '(\d+\.\d+\.\d+)'
java/README.md:version: '(\d+\.\d+\.\d+)'
README.md:version = {(\d+\.\d+\.\d+)}
csharp/nuget/nuget-package.props:>(\d+\.\d+\.\d+)</Version>
CMakeLists.txt:VERSION (\d+\.\d+\.\d+)
update-major-version-in: |
include/usearch/index.hpp:^#define USEARCH_VERSION_MAJOR (\d+)
update-minor-version-in: |
include/usearch/index.hpp:^#define USEARCH_VERSION_MINOR (\d+)
update-patch-version-in: |
include/usearch/index.hpp:^#define USEARCH_VERSION_PATCH (\d+)
dry-run: "false"
push: "true"
create-release: "true"
github-token: ${{ secrets.SEMANTIC_RELEASE_TOKEN }}
rebase:
name: Rebase Dev. Branch
needs: versioning
runs-on: ubuntu-22.04
steps:
- name: Checkout the latest code
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Perform rebase
run: |
git fetch origin main
git checkout main-dev
git rebase origin/main
- name: Push changes
uses: CasperWA/push-protected@v2
with:
token: ${{ secrets.SEMANTIC_RELEASE_TOKEN }}
branch: main-dev
unprotect_reviews: True
force: True
create_linux_deb_package:
name: Create Debian Package
runs-on: ubuntu-22.04
needs: versioning
env:
CC: clang
CXX: clang++
AR: llvm-ar
NM: llvm-nm
RANLIB: llvm-ranlib
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
target: x86_64-linux-gnu
- arch: arm64
target: aarch64-linux-gnu
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Get version
id: set_version
run: |
version=$(cat VERSION)
echo "version=$version" >> $GITHUB_OUTPUT
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y clang lld make crossbuild-essential-arm64 crossbuild-essential-armhf libjemalloc-dev
- name: Build C/C++
run: |
# Configure and build the project
cmake -B build_release \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_EXPORT_COMPILE_COMMANDS=1 \
-DCMAKE_C_COMPILER_TARGET=${{ matrix.target }} \
-DCMAKE_CXX_COMPILER_TARGET=${{ matrix.target }} \
-DCMAKE_SYSTEM_NAME=Linux \
-DCMAKE_SYSTEM_PROCESSOR=${{ matrix.arch }} \
-DUSEARCH_BUILD_LIB_C=1 \
-DUSEARCH_BUILD_SQLITE=1 \
-DUSEARCH_BUILD_TEST_CPP=0 \
-DUSEARCH_BUILD_BENCH_CPP=0
cmake --build build_release --config Release
cp build_release/libusearch_c.so "usearch_linux_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}.so"
cp build_release/libusearch_sqlite.so "usearch_sqlite_linux_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}.so"
mkdir -p "usearch_linux_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}/DEBIAN"
touch "usearch_linux_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}/DEBIAN/control"
mkdir -p "usearch_linux_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}/usr/local/lib"
mkdir "usearch_linux_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}/usr/local/include"
cp c/usearch.h "usearch_linux_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}/usr/local/include/"
cp build_release/libusearch_c.so "usearch_linux_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}/usr/local/lib/"
echo -e "Package: usearch\nVersion: ${{ steps.set_version.outputs.version }}\nMaintainer: Ash Vardanian\nArchitecture: ${{ matrix.arch }}\nDescription: Faster & Smaller Single-File Search Engine for Vectors & Texts" > "usearch_linux_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}/DEBIAN/control"
dpkg-deb --build "usearch_linux_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}"
- name: Upload native library for Java
uses: actions/upload-artifact@v5
with:
name: native-libs-linux-${{ matrix.arch }}
path: build_release/libusearch_c.so
retention-days: 1
- name: Upload library
uses: xresloader/upload-to-github-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
file: "*.so;*.deb"
update_latest_release: true
create_windows_dll_library:
name: Create Dll Library for Windows
runs-on: windows-2022
needs: versioning
strategy:
fail-fast: false
matrix:
arch: [x64, x86, arm64]
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Setup CMake
uses: jwlawson/actions-setup-cmake@v2
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: ${{ env.GO_VERSION }}
cache: false
- name: Setup MinGW
if: matrix.arch != 'arm64'
uses: egor-tensin/setup-mingw@v2
with:
platform: ${{ matrix.arch }}
version: ${{ env.MINGW_VERSION }}
- name: Setup MSVC for ARM64
if: matrix.arch == 'arm64'
uses: microsoft/setup-msbuild@v2
- name: Get version
id: set_version
shell: bash
run: |
version=$(cat VERSION)
echo "version=$version" >> $GITHUB_OUTPUT
- name: Build library (MinGW)
if: matrix.arch != 'arm64'
run: |
cmake -DCMAKE_BUILD_TYPE=Release -DUSEARCH_BUILD_LIB_C=1 -DUSEARCH_BUILD_SQLITE=0 -DUSEARCH_BUILD_TEST_CPP=0 -DUSEARCH_BUILD_BENCH_CPP=0 -B ./build_release
cmake --build ./build_release --config Release
tar -cvf usearch_windows_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}.tar .\build_release\libusearch_c.dll .\c\usearch.h
- name: Build library (MSVC ARM64)
if: matrix.arch == 'arm64'
run: |
cmake -G "Visual Studio 17 2022" -A ARM64 -DCMAKE_BUILD_TYPE=Release -DUSEARCH_BUILD_LIB_C=1 -DUSEARCH_BUILD_SQLITE=0 -DUSEARCH_BUILD_TEST_CPP=0 -DUSEARCH_BUILD_BENCH_CPP=0 -B ./build_release
cmake --build ./build_release --config Release
tar -cvf usearch_windows_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}.tar .\build_release\libusearch_c.dll .\c\usearch.h
- name: Upload native library for Java
uses: actions/upload-artifact@v5
with:
name: native-libs-windows-${{ matrix.arch }}
path: build_release/libusearch_c.dll
retention-days: 1
- name: Upload archive
uses: xresloader/upload-to-github-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
file: "usearch_windows_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}.tar"
update_latest_release: true
create_macos_dylib_library:
name: Create Library for MacOS
runs-on: macos-15
needs: versioning
strategy:
fail-fast: false
matrix:
arch: [arm64, x86_64]
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: ${{ env.GO_VERSION }}
cache: false
- name: Get version
id: set_version
run: |
version=$(cat VERSION)
echo "version=$version" >> $GITHUB_OUTPUT
- name: Build library
run: |
cmake -DCMAKE_BUILD_TYPE=Release \
-DUSEARCH_BUILD_LIB_C=1 \
-DUSEARCH_BUILD_SQLITE=1 \
-DUSEARCH_BUILD_TEST_CPP=0 \
-DUSEARCH_BUILD_BENCH_CPP=0 \
-DCMAKE_OSX_ARCHITECTURES=${{ matrix.arch }} \
-B ./build_release
cmake --build ./build_release --config Release
zip -r usearch_macos_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}.zip build_release/libusearch_c.dylib c/usearch.h
mv build_release/libusearch_sqlite.dylib usearch_sqlite_macos_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}.dylib
- name: Upload native library for Java
uses: actions/upload-artifact@v5
with:
name: native-libs-macos-${{ matrix.arch }}
path: build_release/libusearch_c.dylib
retention-days: 1
- name: Upload library
uses: xresloader/upload-to-github-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
file: "*.dylib"
update_latest_release: true
- name: Upload archive
uses: xresloader/upload-to-github-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
file: "*.zip"
update_latest_release: true
create_android_library:
name: Create Android Libraries
runs-on: ubuntu-22.04
needs: versioning
strategy:
fail-fast: false
matrix:
include:
- processor: armv7a
abi: armeabi-v7a
target: armv7-linux-androideabi
arch: arm32
- processor: aarch64
abi: arm64-v8a
target: aarch64-linux-android
arch: arm64
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Get version
id: set_version
run: |
version=$(cat VERSION)
echo "version=$version" >> $GITHUB_OUTPUT
- name: Install NDK
run: |
${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager --install "ndk;${{ env.ANDROID_NDK_VERSION }}"
- name: Build C/C++
run: |
cmake -B build_artifacts \
-D CMAKE_BUILD_TYPE=Release \
-D CMAKE_TOOLCHAIN_FILE=${ANDROID_HOME}/ndk/${{ env.ANDROID_NDK_VERSION }}/build/cmake/android.toolchain.cmake \
-D CMAKE_ANDROID_STL_TYPE=c++_static \
-D ANDROID_PLATFORM=${{ env.ANDROID_SDK_VERSION }} \
-D ANDROID_ABI=${{ matrix.abi }} \
-D USEARCH_BUILD_LIB_C=1 \
-D USEARCH_BUILD_TEST_CPP=0 \
-D USEARCH_BUILD_BENCH_CPP=0
cmake --build build_artifacts --config Release
- name: Package library
run: |
zip -r usearch_android_${{ matrix.arch }}_${{ steps.set_version.outputs.version }}.zip build_artifacts/libusearch_c.so c/usearch.h
- name: Upload native library for Java
uses: actions/upload-artifact@v5
with:
name: native-libs-android-${{ matrix.arch }}
path: build_artifacts/libusearch_c.so
retention-days: 1
- name: Upload archive
uses: xresloader/upload-to-github-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
file: "*.zip"
update_latest_release: true
build_jni_linux:
name: Build JNI for Linux
runs-on: ubuntu-24.04
needs: versioning
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
target: x86_64-linux-gnu
- arch: arm64
target: aarch64-linux-gnu
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Set up Java
uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: "adopt"
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y clang lld make crossbuild-essential-arm64 crossbuild-essential-armhf
- name: Build JNI library
run: |
cmake -B build_artifacts \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER_TARGET=${{ matrix.target }} \
-DCMAKE_CXX_COMPILER_TARGET=${{ matrix.target }} \
-DCMAKE_SYSTEM_NAME=Linux \
-DCMAKE_SYSTEM_PROCESSOR=${{ matrix.arch }} \
-DUSEARCH_BUILD_JNI=1 \
-DUSEARCH_BUILD_TEST_CPP=0 \
-DUSEARCH_BUILD_BENCH_CPP=0 \
-DUSEARCH_BUILD_LIB_C=0 \
-DUSEARCH_USE_FP16LIB=1 \
-DUSEARCH_USE_SIMSIMD=1 \
-DSIMSIMD_TARGET_HASWELL=1 \
-DSIMSIMD_TARGET_SKYLAKE=1 \
-DSIMSIMD_TARGET_ICE=1 \
-DSIMSIMD_TARGET_GENOA=1 \
-DSIMSIMD_TARGET_SAPPHIRE=1 \
-DSIMSIMD_TARGET_NEON=1 \
-DSIMSIMD_TARGET_NEON_BF16=1 \
-DSIMSIMD_TARGET_NEON_F16=1 \
-DSIMSIMD_TARGET_NEON_I8=1 \
-DSIMSIMD_TARGET_SVE=1 \
-DSIMSIMD_TARGET_SVE_BF16=1 \
-DSIMSIMD_TARGET_SVE_F16=1 \
-DSIMSIMD_TARGET_SVE_I8=1 \
-DSIMSIMD_TARGET_SVE2=1 \
-DSIMSIMD_DYNAMIC_DISPATCH=1
cmake --build build_artifacts --config Release -j
- name: Upload JNI library artifact
uses: actions/upload-artifact@v5
with:
name: usearch-jni-linux-${{ matrix.arch }}
path: build_artifacts/libusearch_jni.so
retention-days: 1
build_jni_windows:
name: Build JNI for Windows
runs-on: windows-2022
needs: versioning
strategy:
fail-fast: false
matrix:
include:
- arch: x64
cmake_arch: x64
simsimd_target_x86: 1
simsimd_target_arm: 0
- arch: x86
cmake_arch: Win32
simsimd_target_x86: 1
simsimd_target_arm: 0
- arch: arm64
cmake_arch: ARM64
simsimd_target_x86: 0
simsimd_target_arm: 1
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Set up Java
uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: "adopt"
- name: Build JNI library
run: |
cmake -B build_artifacts -A ${{ matrix.cmake_arch }} `
-DCMAKE_BUILD_TYPE=Release `
-DUSEARCH_BUILD_JNI=1 `
-DUSEARCH_BUILD_TEST_CPP=0 `
-DUSEARCH_BUILD_BENCH_CPP=0 `
-DUSEARCH_BUILD_LIB_C=0 `
-DUSEARCH_USE_FP16LIB=1 `
-DUSEARCH_USE_SIMSIMD=1 `
-DSIMSIMD_TARGET_NEON=${{ matrix.simsimd_target_arm }} `
-DSIMSIMD_TARGET_HASWELL=${{ matrix.simsimd_target_x86 }} `
-DSIMSIMD_TARGET_SKYLAKE=${{ matrix.simsimd_target_x86 }} `
-DSIMSIMD_TARGET_ICE=${{ matrix.simsimd_target_x86 }} `
-DSIMSIMD_TARGET_GENOA=0 `
-DSIMSIMD_TARGET_SAPPHIRE=0 `
-DSIMSIMD_DYNAMIC_DISPATCH=1
cmake --build build_artifacts --config Release
- name: Upload JNI library artifact
uses: actions/upload-artifact@v5
with:
name: usearch-jni-windows-${{ matrix.arch }}
path: build_artifacts/libusearch_jni.dll
retention-days: 1
build_jni_macos:
name: Build JNI for macOS
runs-on: macos-15
needs: versioning
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
cmake_arch: x86_64
- arch: arm64
cmake_arch: arm64
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Set up Java
uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: "adopt"
- name: Build JNI library
run: |
cmake -B build_artifacts \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_OSX_ARCHITECTURES=${{ matrix.cmake_arch }} \
-DUSEARCH_BUILD_JNI=1 \
-DUSEARCH_BUILD_TEST_CPP=0 \
-DUSEARCH_BUILD_BENCH_CPP=0 \
-DUSEARCH_BUILD_LIB_C=0 \
-DUSEARCH_USE_FP16LIB=1 \
-DUSEARCH_USE_SIMSIMD=1 \
-DSIMSIMD_TARGET_HASWELL=1 \
-DSIMSIMD_TARGET_NEON=1 \
-DSIMSIMD_TARGET_NEON_BF16=1 \
-DSIMSIMD_TARGET_NEON_F16=1 \
-DSIMSIMD_TARGET_NEON_I8=1 \
-DSIMSIMD_DYNAMIC_DISPATCH=1
cmake --build build_artifacts --config Release
- name: Upload JNI library artifact
uses: actions/upload-artifact@v5
with:
name: usearch-jni-macos-${{ matrix.arch }}
path: build_artifacts/libusearch_jni.dylib
retention-days: 1
build_jni_android:
name: Build JNI for Android
runs-on: ubuntu-24.04
needs: versioning
strategy:
fail-fast: false
matrix:
include:
- processor: armv7a
abi: armeabi-v7a
arch: arm32
- processor: aarch64
abi: arm64-v8a
arch: arm64
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Set up Java
uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: "adopt"
- name: Install NDK
run: |
${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager --install "ndk;${{ env.ANDROID_NDK_VERSION }}"
- name: Build JNI library
run: |
cmake -B build_artifacts \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_HOME}/ndk/${{ env.ANDROID_NDK_VERSION }}/build/cmake/android.toolchain.cmake \
-DCMAKE_ANDROID_STL_TYPE=c++_static \
-DANDROID_PLATFORM=${{ env.ANDROID_SDK_VERSION }} \
-DANDROID_ABI=${{ matrix.abi }} \
-DUSEARCH_BUILD_JNI=1 \
-DUSEARCH_BUILD_TEST_CPP=0 \
-DUSEARCH_BUILD_BENCH_CPP=0 \
-DUSEARCH_BUILD_LIB_C=0 \
-DUSEARCH_USE_FP16LIB=1 \
-DUSEARCH_USE_SIMSIMD=1 \
-DSIMSIMD_TARGET_NEON=1 \
-DSIMSIMD_TARGET_NEON_BF16=1 \
-DSIMSIMD_TARGET_NEON_F16=1 \
-DSIMSIMD_TARGET_NEON_I8=1 \
-DSIMSIMD_DYNAMIC_DISPATCH=1
cmake --build build_artifacts --config Release
- name: Upload JNI library artifact
uses: actions/upload-artifact@v5
with:
name: usearch-jni-android-${{ matrix.arch }}
path: build_artifacts/libusearch_jni.so
retention-days: 1
create_wasm_library:
name: Create WASM Libraries
runs-on: ubuntu-22.04
needs: versioning
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Get version
id: set_version
run: |
version=$(cat VERSION)
echo "version=$version" >> $GITHUB_OUTPUT
- name: Setup Emscripten
uses: mymindstorm/setup-emsdk@v14
with:
version: ${{ env.EMSCRIPTEN_VERSION }}
- name: Build WASM with CMake
run: |
emcmake cmake -B build_wasm \
-DCMAKE_BUILD_TYPE=Release \
-DUSEARCH_BUILD_LIB_C=ON \
-DUSEARCH_BUILD_TEST_CPP=OFF \
-DUSEARCH_BUILD_TEST_C=OFF \
-DUSEARCH_BUILD_BENCH_CPP=OFF \
-DUSEARCH_BUILD_SQLITE=OFF \
-DUSEARCH_USE_OPENMP=OFF \
-DUSEARCH_USE_SIMSIMD=ON \
-DUSEARCH_USE_JEMALLOC=OFF
emmake cmake --build build_wasm --config Release
cd build_wasm
tar -czf ../usearch_wasm_${{ steps.set_version.outputs.version }}.tar.gz libusearch_c.* ../c/usearch.h
zip -r ../usearch_wasm_${{ steps.set_version.outputs.version }}.zip libusearch_c.* ../c/usearch.h
- name: Upload archives
uses: xresloader/upload-to-github-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
file: "usearch_wasm_*.tar.gz;usearch_wasm_*.zip"
update_latest_release: true
publish_checksums:
name: Compute Assets Checksums
runs-on: ubuntu-22.04
needs:
[
versioning,
create_linux_deb_package,
create_windows_dll_library,
create_macos_dylib_library,
create_android_library,
create_wasm_library,
publish_java,
build_docs,
]
steps:
- name: Get last release ID
id: last_release
run: |
response=$(curl -s -H "Authorization: Bearer ${{ secrets.SEMANTIC_RELEASE_TOKEN }}" \
"https://api.github.com/repos/${{ github.repository }}/releases/latest")
echo "last_release_id=$(echo "$response" | jq -r '.id')" >> $GITHUB_OUTPUT
- name: Download release assets
uses: robinraju/release-downloader@v1.12
with:
latest: true
fileName: "*"
out-file-path: "downloads"
tarBall: true
zipBall: true
- name: Generate hash list
id: hash_list
run: |
cd $GITHUB_WORKSPACE/downloads
{
echo "## Hashes"
for asset_name in $(ls); do
asset_hash=$(sha256sum $asset_name | awk '{print $1}')
echo "* $asset_name : \`$asset_hash\`"
done
} > hashes.md
echo "hash_body<<EOF" >> $GITHUB_OUTPUT
cat hashes.md >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Upload hashes to release
uses: irongut/EditRelease@v1.2.0
with:
token: ${{ secrets.SEMANTIC_RELEASE_TOKEN }}
id: ${{ steps.last_release.outputs.last_release_id }}
prerelease: false
replacebody: false
body: ${{ steps.hash_list.outputs.hash_body }}
build_wheels:
name: Build Python Wheels
runs-on: ${{ matrix.os }}
needs: versioning
strategy:
matrix:
os: [ubuntu-24.04, macos-14, windows-2022]
python-version: ["38", "39", "310", "311", "312", "313", "313t", "314", "314t"]
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Setup Docker
if: matrix.os == 'ubuntu-24.04'
uses: docker/setup-docker-action@v4
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Setup QEMU
if: matrix.os == 'ubuntu-24.04' # We only need QEMU for Linux builds
uses: docker/setup-qemu-action@v3
- name: Install cibuildwheel
run: python -m pip install cibuildwheel
- name: Build wheels
run: cibuildwheel --output-dir wheelhouse
env:
CIBW_BUILD: cp${{ matrix.python-version }}-*
CIBW_ENABLE: cpython-freethreading # No-GIL 3.13t builds
CIBW_TEST_SKIP: "*-win_arm64" # Too complex to emulate Windows ARM
- name: Upload wheels
uses: actions/upload-artifact@v5
with:
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
path: ./wheelhouse/*.whl
overwrite: true
publish_python:
name: Publish Python
needs: build_wheels
runs-on: ubuntu-22.04
environment:
name: pypi
url: https://pypi.org/p/usearch
permissions:
id-token: write
steps:
- name: Download artifacts
uses: actions/download-artifact@v6
with:
# unpacks all CIBW artifacts into dist/
pattern: cibw-*
path: dist
merge-multiple: true
- name: Publish to PyPi
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist
verbose: true
print-hash: true
build_javascript:
name: Build JavaScript Native Modules
needs: versioning
strategy:
fail-fast: false
matrix:
arch: [x64, x86]
# Windows pre-build is not working
# - windows-latest
os: [macos-14, ubuntu-24.04]
exclude:
- arch: x86
os: macos-14
- arch: x86
os: ubuntu-24.04
runs-on: ${{ matrix.os }}
env:
CC: gcc
CXX: g++
steps:
- name: Checkout the latest code
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
architecture: ${{ matrix.arch }}
- name: Update compilers
if: matrix.os == 'ubuntu-24.04'
run: |
sudo apt update
sudo apt install -y cmake build-essential libjemalloc-dev libomp-dev
sudo apt install -y gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu g++-aarch64-linux-gnu
# NPM installation fails spuriously all the time
- name: Install Dependencies
run: |
npm ci --ignore-scripts || npm ci --ignore-scripts || npm ci --ignore-scripts
- run: npm run prebuild-single
if: matrix.os != 'macos-14'
- run: npm run prebuild-darwin-x64+arm64
env:
CC: clang
CXX: clang++
if: matrix.os == 'macos-14'
- run: file prebuilds/*/*
if: matrix.os == 'macos-14'
- name: Extra for cross build
if: matrix.os == 'ubuntu-24.04'
env:
CC: aarch64-linux-gnu-gcc
CXX: aarch64-linux-gnu-g++
AR: aarch64-linux-gnu-ar
AS: aarch64-linux-gnu-as
LD: aarch64-linux-gnu-ld
STRIP: aarch64-linux-gnu-strip
run: |
npm run prebuild-arm64
aarch64-linux-gnu-strip prebuilds/linux-arm64/*node
- name: Upload prebuilds
uses: actions/upload-artifact@v5
with:
name: prebuilds-${{ matrix.os }}-${{ matrix.arch }}
path: prebuilds
retention-days: 1
publish_javascript:
name: Publish JavaScript
needs: build_javascript
runs-on: ubuntu-22.04
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
- name: Download prebuilds
uses: actions/download-artifact@v6
with:
pattern: prebuilds-*
merge-multiple: true
path: prebuilds
- name: Look for links
run: find . -type f -links +1
# NPM installation fails spuriously all the time
- name: Install Dependencies
run: |
npm ci --ignore-scripts || npm ci --ignore-scripts || npm ci --ignore-scripts
- name: Build the JS from TS
run: npm run build-js
- name: Last minute test with prebuild artifact
run: npm run test
- name: Publish Dry Run
run: npm publish --dry-run
- name: Publish
uses: JS-DevTools/npm-publish@v3
with:
token: ${{ secrets.NPM_TOKEN }}
access: public
publish_rust:
name: Publish Rust
needs: versioning
runs-on: ubuntu-24.04
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Hide submodule Crates
run: |
mv simsimd/Cargo.toml simsimd/Cargo.toml.bak
mv stringzilla/Cargo.toml stringzilla/Cargo.toml.bak
- name: Set up Rust
uses: dtolnay/rust-toolchain@stable
- name: Publish to crates.io
uses: katyo/publish-crates@v2
with:
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}
publish_java:
name: Publish Java
needs:
[
versioning,
build_jni_linux,
build_jni_windows,
build_jni_macos,
build_jni_android,
]
runs-on: ubuntu-24.04
permissions:
contents: write
packages: write
env:
MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.ORG_GRADLE_PROJECT_SIGNINGKEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.ORG_GRADLE_PROJECT_SIGNINGPASSWORD }}
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Download all JNI libraries
uses: actions/download-artifact@v6
with:
pattern: usearch-jni-*
- name: Set up Java
uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: "adopt"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v5
- name: Build fat JAR with all platforms
run: |
# First build the JAR, which will build local native lib
# and overwrite "build/libs/usearch/shared"
gradle compileJava processResources
# Now organize the pre-built JNI libraries to overwrite the local one
mkdir -p build/libs/usearch/shared/{linux-amd64,linux-arm64,windows-amd64,windows-x86,windows-arm64,darwin-amd64,darwin-arm64,android-arm64,android-arm32}
# Linux
cp usearch-jni-linux-amd64/libusearch_jni.so build/libs/usearch/shared/linux-amd64/libusearch_jni.so || true
cp usearch-jni-linux-arm64/libusearch_jni.so build/libs/usearch/shared/linux-arm64/libusearch_jni.so || true
# Windows
cp usearch-jni-windows-x64/libusearch_jni.dll build/libs/usearch/shared/windows-amd64/libusearch_jni.dll || true
cp usearch-jni-windows-x86/libusearch_jni.dll build/libs/usearch/shared/windows-x86/libusearch_jni.dll || true
cp usearch-jni-windows-arm64/libusearch_jni.dll build/libs/usearch/shared/windows-arm64/libusearch_jni.dll || true
# macOS
cp usearch-jni-macos-amd64/libusearch_jni.dylib build/libs/usearch/shared/darwin-amd64/libusearch_jni.dylib || true
cp usearch-jni-macos-arm64/libusearch_jni.dylib build/libs/usearch/shared/darwin-arm64/libusearch_jni.dylib || true
# Android
cp usearch-jni-android-arm64/libusearch_jni.so build/libs/usearch/shared/android-arm64/libusearch_jni.so || true
cp usearch-jni-android-arm32/libusearch_jni.so build/libs/usearch/shared/android-arm32/libusearch_jni.so || true
echo "=== JNI libraries organized ==="
tree build/libs/usearch/shared || find build/libs/usearch/shared -name "libusearch_jni.*" | sort
# Now build the actual fatJar
gradle fatJar
- name: Verify fat JAR contents
run: |
echo "=== Verifying fat JAR contents ==="
jar tf build/libs/usearch-*.jar
# List native libraries found
echo "=== Native libraries in fat JAR ==="
jar tf build/libs/usearch-*.jar | grep -E "usearch-native.*\.(so|dll|dylib)" || echo "No native libraries found"
# Count native libraries
lib_count=$(jar tf build/libs/usearch-*.jar | grep -E "usearch-native.*\.(so|dll|dylib)" | wc -l)
echo "Found $lib_count native libraries in fat JAR"
# Just warn if count seems low, don't fail the build
if [ "$lib_count" -lt 5 ]; then
echo "WARNING: Found fewer native libraries than expected ($lib_count)"
fi
- name: Sign and publish fat JAR
run: gradle signLibraryPublication publish
- name: Log JAR contents
run: |
echo "=== JAR files created ==="
ls -la build/libs/*.jar
for jar in build/libs/*.jar; do
echo "=== Contents of $jar ==="
jar tf "$jar" | grep -E "(usearch-native|\.so|\.dll|\.dylib)" | sort
done
- name: Upload Java JAR to GitHub Release
uses: xresloader/upload-to-github-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
file: "build/libs/*.jar"
update_latest_release: true
publish_swift:
name: Publish ObjC & Swift
needs: versioning
runs-on: macos-15
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Build
run: swift build
- name: Run tests
run: swift test
# Publishes to both Docker Hub and GitHub Container Registry
# https://docs.github.com/en/actions/publishing-packages/publishing-docker-images#publishing-images-to-docker-hub-and-github-packages
publish_docker:
name: Publish Docker Image
needs: versioning
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to GitHub Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Extract tags & labels for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: |
unum/usearch
ghcr.io/${{ github.repository }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build_csharp:
name: Build C Dependencies for C#
needs: versioning
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, macos-15, windows-2022]
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Build C library for Linux
if: matrix.os == 'ubuntu-22.04'
run: |
sudo apt update
sudo apt install -y cmake build-essential libjemalloc-dev libomp-dev gcc-12 g++-12
cmake -B build_artifacts -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DUSEARCH_BUILD_TEST_CPP=0 -DUSEARCH_BUILD_TEST_C=0 -DUSEARCH_BUILD_LIB_C=1 -DUSEARCH_USE_OPENMP=1 -DUSEARCH_USE_SIMSIMD=1 -DUSEARCH_USE_JEMALLOC=1
cmake --build build_artifacts --config Release
mkdir -p "${{ github.workspace }}/csharp/lib/runtimes/linux-x64/native"
cp "${{ github.workspace }}/build_artifacts/libusearch_c.so" "${{ github.workspace }}/csharp/lib/runtimes/linux-x64/native"
- name: Build C library for MacOS
if: matrix.os == 'macos-15'
run: |
brew update
brew reinstall cmake
cmake -B build_artifacts -DCMAKE_BUILD_TYPE=Release -DUSEARCH_BUILD_TEST_CPP=0 -DUSEARCH_BUILD_TEST_C=0 -DUSEARCH_BUILD_LIB_C=1 -DUSEARCH_USE_OPENMP=0 -DUSEARCH_USE_SIMSIMD=1 -DUSEARCH_USE_JEMALLOC=0
cmake --build build_artifacts --config Release
mkdir -p "${{ github.workspace }}/csharp/lib/runtimes/osx-arm64/native"
cp "${{ github.workspace }}/build_artifacts/libusearch_c.dylib" "${{ github.workspace }}/csharp/lib/runtimes/osx-arm64/native"
- name: Build C library for Windows
if: matrix.os == 'windows-2022'
run: |
choco install cmake
cmake -B build_artifacts -DCMAKE_BUILD_TYPE=Release -DUSEARCH_BUILD_TEST_CPP=0 -DUSEARCH_BUILD_TEST_C=0 -DUSEARCH_BUILD_LIB_C=1 -DUSEARCH_USE_OPENMP=0 -DUSEARCH_USE_SIMSIMD=0 -DUSEARCH_USE_JEMALLOC=0
cmake --build build_artifacts --config Release
mkdir -p "${{ github.workspace }}\csharp\lib\runtimes\win-x64\native"
cp "${{ github.workspace }}\build_artifacts\libusearch_c.dll" "${{ github.workspace }}\csharp\lib\runtimes\win-x64\native"
- name: Upload Artifacts
uses: actions/upload-artifact@v5
with:
name: usearch-csharp-dependencies-${{ matrix.os }}
path: ${{ github.workspace }}/csharp/lib/**/*
publish_csharp:
name: Publish C#
runs-on: ubuntu-22.04
needs: [build_csharp]
env:
SOLUTION: ${{ github.workspace }}/csharp
USEARCH_LIBS: ${{ github.workspace }}/csharp/lib
NUGET_PACKAGES: ${{ github.workspace }}/csharp/packages
# NUGET_SOURCE: https://apiint.nugettest.org/v3/index.json
NUGET_SOURCE: https://api.nuget.org/v3/index.json
GITHUB_PACKAGES_SOURCE: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json
steps:
- name: Check out refreshed version
uses: actions/checkout@v6
with:
ref: "main"
- name: Pull Git submodules
run: git submodule update --init --recursive
- name: Download usearch libs artifact
uses: actions/download-artifact@v6
with:
pattern: usearch-csharp-dependencies-*
merge-multiple: true
path: ${{ env.USEARCH_LIBS }}
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Pack project
run: |
dotnet pack "${{ env.SOLUTION }}" -c Release --output ${{ env.NUGET_PACKAGES }}
working-directory: ${{ github.workspace }}
- name: Publish to NuGet
run: dotnet nuget push "${{ env.NUGET_PACKAGES }}/*.nupkg" --api-key "${{ secrets.NUGET_API }}" --source "${{ env.NUGET_SOURCE }}" --skip-duplicate
- name: Prepare publish to GitHub Registry
run: dotnet nuget add source --username ${{ github.repository_owner }} --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "${{ env.GITHUB_PACKAGES_SOURCE }}"
- name: Publish to GitHub Registry
run: dotnet nuget push "${{ env.NUGET_PACKAGES }}/*.nupkg" --api-key "${{ secrets.GITHUB_TOKEN }}" --source "github" --skip-duplicate
build_docs:
name: Build Docs
runs-on: ubuntu-22.04
if: ${{ always() }}
needs:
[
publish_python,
publish_javascript,
publish_rust,
publish_java,
publish_swift,
publish_docker,
publish_csharp,
]
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: "main"
- name: Install dependencies
run: |
sudo apt update &&
sudo apt install -y doxygen graphviz dia git &&
pip install -r docs/requirements.txt &&
npm install -g jsdoc typedoc
- name: Install USearch from PyPi
run: pip install usearch
# NPM installation fails spuriously all the time
- name: Build CJS JS
run: |
npm ci --ignore-scripts || npm ci --ignore-scripts || npm ci --ignore-scripts
npm run build-js
- name: Build documentation
run: cd docs && doxygen conf.dox && make html
- name: Copy assets
run: cp -r assets build/docs/html/
- name: Compress assets
run: tar -czvf docs.tar.gz build/docs/html/
- name: Upload docs to release
uses: xresloader/upload-to-github-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
file: docs.tar.gz
update_latest_release: true
deploy_docs_pages:
name: Deploy GitHub Pages
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-22.04
if: ${{ always() }}
needs: build_docs
steps:
- name: Download release assets
uses: robinraju/release-downloader@v1.12
with:
latest: true
fileName: docs.tar.gz
- name: Unpack docs
run: tar -xf ./docs.tar.gz
- name: Setup GitHub Pages
uses: actions/configure-pages@v5
- name: Upload artifacts
uses: actions/upload-pages-artifact@v3
with:
path: ./build/docs/html
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
deploy_docs_vercel:
name: Deploy Vercel
runs-on: ubuntu-22.04
if: ${{ always() }}
needs: build_docs
steps:
- name: Notify Vercel
uses: fjogeleit/http-request-action@v1
with:
url: ${{ secrets.DOCS_VERCEL }}
method: "POST"