Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ad31648
First draft of C API design
rfsaliev Jan 7, 2026
e196831
First C API implementation draft with sample
rfsaliev Jan 12, 2026
6ca5115
Some code refactoring
rfsaliev Jan 13, 2026
19201d1
Improve error handling and add LeanVec support
rfsaliev Jan 19, 2026
5941e16
Add basic thread pool configuration support
rfsaliev Jan 20, 2026
b1e85f4
Set default visibility hidden
rfsaliev Jan 20, 2026
47e8096
Add FP16 simple storage
rfsaliev Jan 20, 2026
3ce98f9
Add search parameters support
rfsaliev Jan 20, 2026
0a014de
Add LVQ and SQ storage kinds support
rfsaliev Jan 20, 2026
c5009bb
Cleanup code in index build dispatching
rfsaliev Jan 20, 2026
a1547d8
Add custom thread pool support
rfsaliev Jan 21, 2026
9c4cd43
Add some vamana parameters getters/setters
rfsaliev Jan 21, 2026
4e6181a
Extend/improve error handling
rfsaliev Jan 22, 2026
cf45cd0
Update C API design document
rfsaliev Jan 22, 2026
e045deb
Add index save/load API (#251)
rfsaliev Feb 25, 2026
62cca5b
Add dynamic Vamana index support (#252)
rfsaliev Mar 9, 2026
c2f03b9
[C API] Refactor C API implementation to make it portable to the publ…
rfsaliev Mar 10, 2026
04bbff0
Apply formatting via pre-commit hook
rfsaliev Mar 10, 2026
3103a68
Merge remote-tracking branch 'origin/main' into dev/c-api
rfsaliev Mar 27, 2026
ec4260c
Fix copyright issues
rfsaliev Mar 27, 2026
1478cde
[C-API] Add getter and setter for index threadpool size (#305)
rfsaliev Apr 16, 2026
39119a4
Fix: cmake version compatibility issue in C API CMakeLists.txt (#318)
rfsaliev May 8, 2026
66a0549
Merge remote-tracking branch 'origin/main' into dev/c-api
rfsaliev Jun 8, 2026
03f514b
Add C API tests for error handling, indexing, and search parameters (…
rfsaliev Jun 11, 2026
83c6196
Add license header to C API tests README.md
rfsaliev Jun 11, 2026
db44de8
[C API] Add support for filtered TopK search in C API (#352)
rfsaliev Jul 17, 2026
3fae3ac
[C API] Add memory accounting (get_memory_usage / get_memory_breakdow…
yuejiaointel Jul 17, 2026
40c05eb
Merge remote-tracking branch 'origin/main' into dev/c-api
rfsaliev Aug 10, 2026
08d9289
[C API] CI for C API (#362)
ethanglaser Aug 11, 2026
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: 58 additions & 0 deletions .github/scripts/build-c-api-bindings.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/bin/bash
# Copyright 2026 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Configure, build, install and package the C API bindings.
#
# Inputs (all optional, with defaults suitable for a local run):
# ENABLE_LVQ_LEANVEC ON to statically link the LVQ/LeanVec backend
# REQUIRE_LTO_ARCHIVE ON to fail (not warn) if the compiler can't consume the
# LTO archive; set in CI, left off for local builds
# SUFFIX artifact name suffix (e.g. -public-only)
# WORKSPACE repository root; defaults to this script's repo so it
# also runs outside the container

set -e

# In the manylinux/rockylinux containers the pinned gcc-toolset lives behind an
# scl profile script; harmless no-op on a plain runner.
source /etc/bashrc 2>/dev/null || true

# Repo root, derived from this script's location so no git metadata is needed.
WORKSPACE="${WORKSPACE:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
BUILD_DIR="${WORKSPACE}/build_c_api"
INSTALL_DIR="${WORKSPACE}/install_c_api"
ENABLE_LVQ_LEANVEC="${ENABLE_LVQ_LEANVEC:-OFF}"
REQUIRE_LTO_ARCHIVE="${REQUIRE_LTO_ARCHIVE:-OFF}"

echo "compiler: $(${CXX:-c++} --version | head -1)"

rm -rf "${BUILD_DIR}" "${INSTALL_DIR}"

cmake -B"${BUILD_DIR}" -S"${WORKSPACE}/bindings/c" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \
-DCMAKE_INSTALL_LIBDIR=lib \
-DSVS_BUILD_C_API_TESTS=ON \
-DSVS_RUNTIME_ENABLE_LVQ_LEANVEC="${ENABLE_LVQ_LEANVEC}" \
-DSVS_REQUIRE_LTO_ARCHIVE="${REQUIRE_LTO_ARCHIVE}"

cmake --build "${BUILD_DIR}" -j"$(nproc)"

# Install only the C API component: the dependency headers that a full install
# would also emit are not part of the shipped interface.
cmake --install "${BUILD_DIR}" --component C_API

tar -czf "${WORKSPACE}/svs-c-api${SUFFIX}.tar.gz" -C "${INSTALL_DIR}" .
echo "Packaged ${WORKSPACE}/svs-c-api${SUFFIX}.tar.gz"
1 change: 1 addition & 0 deletions .github/scripts/build-cpp-runtime-bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ CMAKE_ARGS=(
"-DCMAKE_INSTALL_PREFIX=/workspace/install_cpp_bindings"
"-DCMAKE_INSTALL_LIBDIR=lib"
"-DSVS_RUNTIME_ENABLE_LVQ_LEANVEC=${ENABLE_LVQ_LEANVEC:-ON}"
"-DSVS_REQUIRE_LTO_ARCHIVE=${REQUIRE_LTO_ARCHIVE:-OFF}"
"-DSVS_RUNTIME_ENABLE_IVF=ON"
"-DSVS_EXPERIMENTAL_CLANG_TIDY=ON"
)
Expand Down
85 changes: 85 additions & 0 deletions .github/scripts/test-c-api-bindings.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/bin/bash
# Copyright 2026 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Integration test for the packaged C API: verifies the tarball is a usable
# package rather than just a successful compile. Runs against the artifact only,
# with no access to the build tree.
#
# Inputs:
# SUFFIX artifact name suffix (e.g. -public-only)
# WORKSPACE repository root; defaults to this script's repo so it also runs
# outside the container

set -e

# Match build-c-api-bindings.sh: pick up the container's pinned gcc-toolset.
source /etc/bashrc 2>/dev/null || true

# Repo root, derived from this script's location so no git metadata is needed.
WORKSPACE="${WORKSPACE:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
STAGE_DIR="${WORKSPACE}/c_api_integration"

# Prefer the artifact downloaded by the workflow, else a tarball built locally.
TARBALL="${WORKSPACE}/c_api_artifact/svs-c-api${SUFFIX}.tar.gz"
if [ ! -e "${TARBALL}" ]; then
TARBALL="${WORKSPACE}/svs-c-api${SUFFIX}.tar.gz"
fi

INSTALL_DIR="${STAGE_DIR}/install"
CONSUMER_BUILD="${STAGE_DIR}/consumer-build"

rm -rf "${STAGE_DIR}"
mkdir -p "${INSTALL_DIR}"
tar -xzf "${TARBALL}" -C "${INSTALL_DIR}"

echo "::group::Package contents"
find "${INSTALL_DIR}" -type f -o -type l | sort
echo "::endgroup::"

LIBDIR="${INSTALL_DIR}/lib"
LIB="${LIBDIR}/libsvs_c_api.so"
if [ ! -e "${LIB}" ]; then
echo "ERROR: ${LIB} missing from the package"
exit 1
fi

echo "::group::Strong exported symbols"
nm -D --defined-only "${LIB}" | awk '$2=="T"{print $3}' | sort
echo "::endgroup::"

# Only the documented svs_* C ABI may be exported with strong linkage. This also
# guards the statically linked LVQ/LeanVec backend against leaking symbols.
#
# std:: template instantiations (_ZNSt/_ZSt) are excluded: GCC emits some of these
# with strong linkage from the LTO archive, and they are standard-library code
# rather than SVS implementation detail. The check still catches any leak of an
# actual svs/proprietary internal.
LEAKED=$(nm -D --defined-only "${LIB}" | awk '$2=="T"{print $3}' \
| grep -v '^svs_' | grep -vE '^_Z+(N?)St' || true)
if [ -n "${LEAKED}" ]; then
echo "ERROR: non-svs_ symbols exported from the C API:"
echo "${LEAKED}"
exit 1
fi

# Build a standalone C project against the installed CMake package, the way a
# downstream integration would. Catches exported-target defects (a missing
# find_dependency, or a C++ requirement leaking onto a C consumer) that a
# build-tree-only test cannot see.
cmake -B"${CONSUMER_BUILD}" -S"${WORKSPACE}/bindings/c/tests/consumer" \
-DCMAKE_PREFIX_PATH="${INSTALL_DIR}"
cmake --build "${CONSUMER_BUILD}"

LD_LIBRARY_PATH="${LIBDIR}" "${CONSUMER_BUILD}/c_api_consumer"
47 changes: 47 additions & 0 deletions .github/scripts/test-c-api-unit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/bin/bash
# Copyright 2026 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Run the C API unit tests and samples out of an existing build tree.
#
# Inputs:
# WORKSPACE repository root; defaults to this script's repo so it also runs
# outside the container

set -e

# Match build-c-api-bindings.sh: pick up the container's pinned gcc-toolset.
source /etc/bashrc 2>/dev/null || true

# Repo root, derived from this script's location so no git metadata is needed.
WORKSPACE="${WORKSPACE:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
BUILD_DIR="${WORKSPACE}/build_c_api"

# LVQ/LeanVec need a specific ISA. The tests already accept
# SVS_ERROR_UNSUPPORTED_HW (but never SVS_ERROR_NOT_IMPLEMENTED), so this is
# reported for triage rather than used to skip anything.
echo "vendor: $(grep -m1 vendor_id /proc/cpuinfo || echo unknown)"
echo "model: $(grep -m1 'model name' /proc/cpuinfo || echo unknown)"
echo "avx512: $(grep -o 'avx512[a-z_0-9]*' /proc/cpuinfo | sort -u | tr '\n' ' ')"

ctest --test-dir "${BUILD_DIR}" --output-on-failure --no-tests=error

# The samples are the only executable check that the public headers are usable
# from C and that an end-to-end build/search runs. They regressed to a non-zero
# exit once already, so they are part of the gate.
for sample in c_api_simple c_api_save_load c_api_dynamic; do
echo "::group::${sample}"
"${BUILD_DIR}/samples/${sample}"
echo "::endgroup::"
done
123 changes: 123 additions & 0 deletions .github/workflows/build-c-api-bindings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Copyright 2026 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: Build and test C API bindings

on:
push:
branches:
- main
pull_request:
workflow_dispatch:

permissions:
contents: read

# This allows a subsequently queued workflow run to interrupt previous runs
concurrency:
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
cancel-in-progress: true

jobs:
build-c-api-bindings:
name: Build and unit tests for C API (${{ matrix.name }})
runs-on: ubuntu-22.04
strategy:
matrix:
# Mirrors build-cpp-runtime-bindings.yml.
include:
- name: "with static library"
enable_lvq_leanvec: "ON"
require_lto: "ON"
suffix: ""
- name: "public only"
enable_lvq_leanvec: "OFF"
require_lto: "OFF"
suffix: "-public-only"
fail-fast: false

steps:
- uses: actions/checkout@v6

- name: Build Docker image
run: docker build -t svs-manylinux228:latest -f docker/x86_64/manylinux228/Dockerfile .

- name: Build C API bindings in Docker container
run: |
docker run --rm \
-v ${{ github.workspace }}:/workspace \
-w /workspace \
-e ENABLE_LVQ_LEANVEC=${{ matrix.enable_lvq_leanvec }} \
-e REQUIRE_LTO_ARCHIVE=${{ matrix.require_lto }} \
-e SUFFIX=${{ matrix.suffix }} \
svs-manylinux228:latest \
/bin/bash .github/scripts/build-c-api-bindings.sh

- name: Upload C API bindings artifacts
uses: actions/upload-artifact@v7
with:
name: svs-c-api${{ matrix.suffix }}
path: svs-c-api${{ matrix.suffix }}.tar.gz
retention-days: 7

# Run unit tests that were built as part of this job
- name: Run unit tests in Docker container
run: |
docker run --rm \
-v ${{ github.workspace }}:/workspace \
-w /workspace \
svs-manylinux228:latest \
/bin/bash /workspace/.github/scripts/test-c-api-unit.sh

# Run integration tests against the packaged artifact. Eventually this should
# run the setup and test scope of the actual downstream integrations; for now it
# just confirms the tarball is functional - it installs, exports only the svs_*
# C ABI, and can be consumed from a standalone C project.
test:
name: Integration tests for C API (${{ matrix.name }})
needs: build-c-api-bindings
runs-on: ubuntu-22.04
strategy:
matrix:
include:
- name: "with static library"
suffix: ""
- name: "public only"
suffix: "-public-only"
fail-fast: false

steps:
- uses: actions/checkout@v6

- name: Build Docker image
run: docker build -t svs-manylinux228:latest -f docker/x86_64/manylinux228/Dockerfile .

# Need to download for a new job
- name: Download C API package
uses: actions/download-artifact@v8
with:
name: svs-c-api${{ matrix.suffix }}
path: c_api_artifact

- name: List available artifacts
run: ls -la c_api_artifact/

- name: Test packaged C API in Docker container
run: |
docker run --rm \
-v ${{ github.workspace }}:/workspace \
-w /workspace \
-e SUFFIX=${{ matrix.suffix }} \
svs-manylinux228:latest \
/bin/bash .github/scripts/test-c-api-bindings.sh
3 changes: 3 additions & 0 deletions .github/workflows/build-cpp-runtime-bindings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ jobs:
include:
- name: "with static library"
enable_lvq_leanvec: "ON"
require_lto: "ON"
suffix: ""
- name: "public only"
enable_lvq_leanvec: "OFF"
require_lto: "OFF"
suffix: "-public-only"
fail-fast: false

Expand All @@ -57,6 +59,7 @@ jobs:
-v ${{ github.workspace }}:/workspace \
-w /workspace \
-e ENABLE_LVQ_LEANVEC=${{ matrix.enable_lvq_leanvec }} \
-e REQUIRE_LTO_ARCHIVE=${{ matrix.require_lto }} \
-e SUFFIX=${{ matrix.suffix }} \
svs-manylinux228:latest \
/bin/bash .github/scripts/build-cpp-runtime-bindings.sh
Expand Down
Loading
Loading