Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: WASM builds #331

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 8 additions & 50 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ jobs:
run: |
cmake -DCMAKE_BUILD_TYPE=Release -DUSEARCH_BUILD_LIB_C=1 -DUSEARCH_BUILD_TEST_CPP=0 -DUSEARCH_BUILD_BENCH_CPP=0 -B ./build_release
cmake --build ./build_release --config Release
zip -r usearch_macOS_${{ matrix.arch }}_${{ steps.version.outputs.version }}.zip build_release/libusearch_c.so c/usearch.h
zip -r usearch_macOS_${{ matrix.arch }}_${{ steps.version.outputs.version }}.zip build_release/libusearch_c.* c/usearch.h

- name: Upload archive
uses: xresloader/upload-to-github-release@v1
Expand All @@ -195,13 +195,9 @@ jobs:
update_latest_release: true

wasm_c_library:
name: WASM builds for C libraries on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
name: WASM builds for C libraries
runs-on: ubuntu-22.04
needs: versioning
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, macOS-11, windows-2022]
steps:
- uses: actions/checkout@v3
with:
Expand All @@ -224,52 +220,14 @@ jobs:
tar xf wasi-sdk-${WASI_VERSION_FULL}-linux.tar.gz
rm -rf wasi-sdk-${WASI_VERSION_FULL}-linux.tar.gz
export WASI_SDK_PATH=/home/runner/work/usearch/usearch/wasi-sdk-${WASI_VERSION_FULL}
archs=("x86_64" "arm64")
targets=("threads")
cd ./c
for arch in "${archs[@]}"
for target in "${targets[@]}"
do
../wasi-sdk-20.0/bin/clang++ --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -o libusearch_c.so -O3 lib.cpp -I. -I ../include/ -I ../fp16/include/ -shared --target=wasm32-wasi-threads -Wl,--no-entry -nostdlib -D_WASI_EMULATED_MMAN -march="$arch"
tar -czvf usearch_wasm_linux_"$arch"_${{ steps.version.outputs.version }}.tar.gz libusearch_c.so
mv usearch_wasm_linux_"$arch"_${{ steps.version.outputs.version }}.tar.gz ../ && rm -rf libusearch_c.so
../wasi-sdk-${WASI_VERSION_FULL}/bin/clang++ --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -o libusearch_c-${target}.wasm -O3 lib.cpp -I. -I ../include/ -I ../fp16/include/ -shared --target=wasm32-wasi-$target -Wl,--no-entry -mexec-model=reactor -D_WASI_EMULATED_MMAN -lwasi-emulated-mman
tar -czvf usearch_wasm_${target}_${{ steps.version.outputs.version }}.tar.gz libusearch_c-${target}.wasm
mv usearch_wasm_${target}_${{ steps.version.outputs.version }}.tar.gz ../ && rm -rf libusearch_c-${target}.wasm
done
if: matrix.os == 'ubuntu-22.04'

- name: Build library on MacOS
run: |
export WASI_VERSION=20
export WASI_VERSION_FULL=${WASI_VERSION}.0
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VERSION}/wasi-sdk-${WASI_VERSION_FULL}-macos.tar.gz
tar xf wasi-sdk-${WASI_VERSION_FULL}-macos.tar.gz
rm -rf wasi-sdk-${WASI_VERSION_FULL}-macos.tar.gz
export WASI_SDK_PATH=/Users/runner/work/usearch/usearch/wasi-sdk-${WASI_VERSION_FULL}
archs=("x86_64" "arm64")
cd ./c
for arch in "${archs[@]}"
do
../wasi-sdk-20.0/bin/clang++ --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -o libusearch_c.so -O3 lib.cpp -I. -I ../include/ -I ../fp16/include/ -shared --target=wasm32-wasi-threads -Wl,--no-entry -nostdlib -D_WASI_EMULATED_MMAN -march="$arch"
zip -r usearch_wasm_macos_"$arch"_${{ steps.version.outputs.version }}.zip libusearch_c.so
mv usearch_wasm_macos_"$arch"_${{ steps.version.outputs.version }}.zip ../ && rm -rf libusearch_c.so
done
if: matrix.os == 'macOS-11'

- name: Build library on Windows
run: |
export WASI_VERSION=20
export WASI_VERSION_FULL=${WASI_VERSION}.0
curl -LOJ https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VERSION}/wasi-sdk-${WASI_VERSION_FULL}.m-mingw.tar.gz
tar xf wasi-sdk-${WASI_VERSION_FULL}.m-mingw.tar.gz
rm -rf wasi-sdk-${WASI_VERSION_FULL}.m-mingw.tar.gz
export WASI_SDK_PATH=/d/a/usearch/usearch/wasi-sdk-${WASI_VERSION_FULL}+m
archs=("x64" "x86")
cd ./c
for arch in "${archs[@]}"
do
../wasi-sdk-20.0+m/bin/clang++ --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -o libusearch_c.so -O3 lib.cpp -I. -I ../include/ -I ../fp16/include/ -shared --target=wasm32-wasi-threads -Wl,--no-entry -nostdlib -D_WASI_EMULATED_MMAN -march="$arch"
tar -cvf usearch_wasm_windows_"$arch"_${{ steps.version.outputs.version }}.tar.gz libusearch_c.so
mv usearch_wasm_windows_"$arch"_${{ steps.version.outputs.version }}.tar.gz ../ && rm -rf libusearch_c.so
done
shell: bash
if: matrix.os == 'windows-2022'

- name: Upload archive
uses: xresloader/upload-to-github-release@v1
Expand Down
25 changes: 25 additions & 0 deletions c/lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ search_result_t search_(index_dense_t* index, void const* vector, scalar_kind_t

extern "C" {

__attribute__((export_name("usearch_init")))
USEARCH_EXPORT usearch_index_t usearch_init(usearch_init_options_t* options, usearch_error_t* error) {

assert(options && error);
Expand All @@ -127,15 +128,18 @@ USEARCH_EXPORT usearch_index_t usearch_init(usearch_init_options_t* options, use
return result_ptr;
}

__attribute__((export_name("usearch_free")))
USEARCH_EXPORT void usearch_free(usearch_index_t index, usearch_error_t*) {
delete reinterpret_cast<index_dense_t*>(index);
}

__attribute__((export_name("usearch_serialized_length")))
USEARCH_EXPORT size_t usearch_serialized_length(usearch_index_t index, usearch_error_t*) {
assert(index);
return reinterpret_cast<index_dense_t*>(index)->serialized_length();
}

__attribute__((export_name("usearch_save")))
USEARCH_EXPORT void usearch_save(usearch_index_t index, char const* path, usearch_error_t* error) {

assert(index && path && error);
Expand All @@ -144,6 +148,7 @@ USEARCH_EXPORT void usearch_save(usearch_index_t index, char const* path, usearc
*error = result.error.release();
}

__attribute__((export_name("usearch_load")))
USEARCH_EXPORT void usearch_load(usearch_index_t index, char const* path, usearch_error_t* error) {

assert(index && path && error);
Expand All @@ -152,6 +157,7 @@ USEARCH_EXPORT void usearch_load(usearch_index_t index, char const* path, usearc
*error = result.error.release();
}

__attribute__((export_name("usearch_view")))
USEARCH_EXPORT void usearch_view(usearch_index_t index, char const* path, usearch_error_t* error) {

assert(index && path && error);
Expand All @@ -160,6 +166,7 @@ USEARCH_EXPORT void usearch_view(usearch_index_t index, char const* path, usearc
*error = result.error.release();
}

__attribute__((export_name("usearch_metadata")))
USEARCH_EXPORT void usearch_metadata(char const* path, usearch_init_options_t* options, usearch_error_t* error) {

assert(path && options && error);
Expand All @@ -178,6 +185,7 @@ USEARCH_EXPORT void usearch_metadata(char const* path, usearch_init_options_t* o
options->metric = NULL;
}

__attribute__((export_name("usearch_save_buffer")))
USEARCH_EXPORT void usearch_save_buffer(usearch_index_t index, void* buffer, size_t length, usearch_error_t* error) {

assert(index && buffer && length && error);
Expand All @@ -187,6 +195,7 @@ USEARCH_EXPORT void usearch_save_buffer(usearch_index_t index, void* buffer, siz
*error = result.error.release();
}

__attribute__((export_name("usearch_load_buffer")))
USEARCH_EXPORT void usearch_load_buffer(usearch_index_t index, void const* buffer, size_t length,
usearch_error_t* error) {

Expand All @@ -197,6 +206,7 @@ USEARCH_EXPORT void usearch_load_buffer(usearch_index_t index, void const* buffe
*error = result.error.release();
}

__attribute__((export_name("usearch_view_buffer")))
USEARCH_EXPORT void usearch_view_buffer(usearch_index_t index, void const* buffer, size_t length,
usearch_error_t* error) {

Expand All @@ -207,6 +217,7 @@ USEARCH_EXPORT void usearch_view_buffer(usearch_index_t index, void const* buffe
*error = result.error.release();
}

__attribute__((export_name("usearch_metadata_buffer")))
USEARCH_EXPORT void usearch_metadata_buffer(void const* buffer, size_t length, usearch_init_options_t* options,
usearch_error_t* error) {

Expand All @@ -227,28 +238,34 @@ USEARCH_EXPORT void usearch_metadata_buffer(void const* buffer, size_t length, u
options->metric = NULL;
}

__attribute__((export_name("usearch_size")))
USEARCH_EXPORT size_t usearch_size(usearch_index_t index, usearch_error_t*) { //
return reinterpret_cast<index_dense_t*>(index)->size();
}

__attribute__((export_name("usearch_capacity")))
USEARCH_EXPORT size_t usearch_capacity(usearch_index_t index, usearch_error_t*) {
return reinterpret_cast<index_dense_t*>(index)->capacity();
}

__attribute__((export_name("usearch_dimensions")))
USEARCH_EXPORT size_t usearch_dimensions(usearch_index_t index, usearch_error_t*) {
return reinterpret_cast<index_dense_t*>(index)->dimensions();
}

__attribute__((export_name("usearch_connectivity")))
USEARCH_EXPORT size_t usearch_connectivity(usearch_index_t index, usearch_error_t*) {
return reinterpret_cast<index_dense_t*>(index)->connectivity();
}

__attribute__((export_name("usearch_reserve")))
USEARCH_EXPORT void usearch_reserve(usearch_index_t index, size_t capacity, usearch_error_t* error) {
assert(index && error);
if (!reinterpret_cast<index_dense_t*>(index)->reserve(capacity))
*error = "Out of memory!";
}

__attribute__((export_name("usearch_add")))
USEARCH_EXPORT void usearch_add( //
usearch_index_t index, usearch_key_t key, void const* vector, usearch_scalar_kind_t kind, //
usearch_error_t* error) {
Expand All @@ -259,16 +276,19 @@ USEARCH_EXPORT void usearch_add(
*error = result.error.release();
}

__attribute__((export_name("usearch_contains")))
USEARCH_EXPORT bool usearch_contains(usearch_index_t index, usearch_key_t key, usearch_error_t*) {
assert(index);
return reinterpret_cast<index_dense_t*>(index)->contains(key);
}

__attribute__((export_name("usearch_count")))
USEARCH_EXPORT size_t usearch_count(usearch_index_t index, usearch_key_t key, usearch_error_t*) {
assert(index);
return reinterpret_cast<index_dense_t*>(index)->count(key);
}

__attribute__((export_name("usearch_search")))
USEARCH_EXPORT size_t usearch_search( //
usearch_index_t index, void const* vector, usearch_scalar_kind_t kind, size_t results_limit, //
usearch_key_t* found_keys, usearch_distance_t* found_distances, usearch_error_t* error) {
Expand All @@ -284,6 +304,7 @@ USEARCH_EXPORT size_t usearch_search(
return result.dump_to(found_keys, found_distances);
}

__attribute__((export_name("usearch_get")))
USEARCH_EXPORT size_t usearch_get( //
usearch_index_t index, usearch_key_t key, size_t count, //
void* vectors, usearch_scalar_kind_t kind, usearch_error_t*) {
Expand All @@ -292,6 +313,7 @@ USEARCH_EXPORT size_t usearch_get( //
return get_(reinterpret_cast<index_dense_t*>(index), key, count, vectors, scalar_kind_to_cpp(kind));
}

__attribute__((export_name("usearch_remove")))
USEARCH_EXPORT size_t usearch_remove(usearch_index_t index, usearch_key_t key, usearch_error_t* error) {

assert(index && error);
Expand All @@ -301,6 +323,7 @@ USEARCH_EXPORT size_t usearch_remove(usearch_index_t index, usearch_key_t key, u
return result.completed;
}

__attribute__((export_name("usearch_rename")))
USEARCH_EXPORT size_t usearch_rename( //
usearch_index_t index, usearch_key_t from, usearch_key_t to, usearch_error_t* error) {

Expand All @@ -311,6 +334,7 @@ USEARCH_EXPORT size_t usearch_rename( //
return result.completed;
}

__attribute__((export_name("usearch_distance")))
USEARCH_EXPORT usearch_distance_t usearch_distance( //
void const* vector_first, void const* vector_second, //
usearch_scalar_kind_t scalar_kind, size_t dimensions, //
Expand All @@ -321,6 +345,7 @@ USEARCH_EXPORT usearch_distance_t usearch_distance( //
return metric((byte_t const*)vector_first, (byte_t const*)vector_second);
}

__attribute__((export_name("usearch_exact_search")))
USEARCH_EXPORT void usearch_exact_search( //
void const* dataset, size_t dataset_count, size_t dataset_stride, //
void const* queries, size_t queries_count, size_t queries_stride, //
Expand Down