diff --git a/.github/workflows/build-c-api-bindings.yml b/.github/workflows/build-c-api-bindings.yml new file mode 100644 index 00000000..782c06e1 --- /dev/null +++ b/.github/workflows/build-c-api-bindings.yml @@ -0,0 +1,82 @@ +# 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: + name: ${{ matrix.cxx }}, ${{ matrix.build_type }} + runs-on: ubuntu-22.04 + strategy: + matrix: + build_type: [RelWithDebInfo] + cxx: [g++-11, g++-12, clang++-15] + include: + - cxx: g++-11 + cc: gcc-11 + - cxx: g++-12 + cc: gcc-12 + - cxx: clang++-15 + cc: clang-15 + fail-fast: false + + steps: + - uses: actions/checkout@v6 + + - name: Install OpenMP runtime + env: + CXX: ${{ matrix.cxx }} + run: | + sudo apt-get update + # The default libgomp shipped with GCC does not match the clang + # toolchain, so install the LLVM OpenMP runtime (libomp) for clang. + if [[ "${CXX}" == clang* ]]; then + sudo apt-get install -y libomp-15-dev + fi + + - name: Configure build + working-directory: ${{ runner.temp }} + env: + CXX: ${{ matrix.cxx }} + CC: ${{ matrix.cc }} + TEMP_WORKSPACE: ${{ runner.temp }} + run: | + cmake -B${TEMP_WORKSPACE}/build -S${GITHUB_WORKSPACE}/bindings/c \ + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ + -DSVS_BUILD_C_API_TESTS=ON + + - name: Build C API, tests and samples + working-directory: ${{ runner.temp }}/build + run: make -j$(nproc) + + - name: Run C API tests + env: + CTEST_OUTPUT_ON_FAILURE: 1 + working-directory: ${{ runner.temp }}/build + run: ctest -C ${{ matrix.build_type }} --output-on-failure diff --git a/bindings/c/CMakeLists.txt b/bindings/c/CMakeLists.txt index dd9847d2..b88ab589 100644 --- a/bindings/c/CMakeLists.txt +++ b/bindings/c/CMakeLists.txt @@ -201,6 +201,9 @@ endif() if(SVS_BUILD_C_API_TESTS) + # Add test to CTest + include(CTest) + enable_testing() if(CMAKE_BUILD_TYPE STREQUAL "Debug") target_compile_options(${TARGET_NAME} PRIVATE --coverage) target_link_options(${TARGET_NAME} PRIVATE --coverage) diff --git a/bindings/c/src/data_builder/leanvec.hpp b/bindings/c/src/data_builder/leanvec.hpp index 87588c7e..13ba58a5 100644 --- a/bindings/c/src/data_builder/leanvec.hpp +++ b/bindings/c/src/data_builder/leanvec.hpp @@ -77,11 +77,11 @@ class LeanVecDataBuilder { } }; -template +template struct lib:: - DispatchConverter> { + DispatchConverter> { using From = const svs::c_runtime::Storage*; - using To = LeanVecDataBuilder; + using To = LeanVecDataBuilder; static int64_t match(From from) { if (from->kind == SVS_STORAGE_KIND_LEANVEC) { diff --git a/bindings/c/src/data_builder/lvq.hpp b/bindings/c/src/data_builder/lvq.hpp index 7a9e8ca5..d7d5912a 100644 --- a/bindings/c/src/data_builder/lvq.hpp +++ b/bindings/c/src/data_builder/lvq.hpp @@ -75,12 +75,12 @@ class LVQDataBuilder { } }; -template +template struct lib::DispatchConverter< const c_runtime::Storage*, - LVQDataBuilder> { + LVQDataBuilder> { using From = const svs::c_runtime::Storage*; - using To = LVQDataBuilder; + using To = LVQDataBuilder; static int64_t match(From from) { if (from->kind == SVS_STORAGE_KIND_LVQ) { diff --git a/bindings/c/src/data_builder/simple.hpp b/bindings/c/src/data_builder/simple.hpp index 36482909..1f016241 100644 --- a/bindings/c/src/data_builder/simple.hpp +++ b/bindings/c/src/data_builder/simple.hpp @@ -61,10 +61,10 @@ class SimpleDataBuilder { } }; -template -struct lib::DispatchConverter> { +template +struct lib::DispatchConverter> { using From = const svs::c_runtime::Storage*; - using To = SimpleDataBuilder; + using To = SimpleDataBuilder; static int64_t match(From from) { if constexpr (svs::is_arithmetic_v) { diff --git a/bindings/c/src/data_builder/sq.hpp b/bindings/c/src/data_builder/sq.hpp index a062ff7b..f2fd9559 100644 --- a/bindings/c/src/data_builder/sq.hpp +++ b/bindings/c/src/data_builder/sq.hpp @@ -59,10 +59,10 @@ template > class SQDat } }; -template -struct lib::DispatchConverter> { +template +struct lib::DispatchConverter> { using From = const svs::c_runtime::Storage*; - using To = SQDataBuilder; + using To = SQDataBuilder; static int64_t match(From from) { if (from->kind == SVS_STORAGE_KIND_SQ) { diff --git a/bindings/c/tests/c_api_index.cpp b/bindings/c/tests/c_api_index.cpp index 07dce2c4..6bd19d29 100644 --- a/bindings/c/tests/c_api_index.cpp +++ b/bindings/c/tests/c_api_index.cpp @@ -231,17 +231,23 @@ CATCH_TEST_CASE("C API Index Build and Search", "[c_api][index][build][search]") DIMENSION / 2, SVS_DATA_TYPE_INT4, SVS_DATA_TYPE_INT8, error ); CATCH_REQUIRE(check_storage_support(storage, error) == true); - run_build_and_search(storage); + if (storage != nullptr) { + run_build_and_search(storage); + } // LVQ: primary = int4, residual = int8 storage = svs_storage_create_lvq(SVS_DATA_TYPE_INT4, SVS_DATA_TYPE_INT8, error); CATCH_REQUIRE(check_storage_support(storage, error) == true); - run_build_and_search(storage); + if (storage != nullptr) { + run_build_and_search(storage); + } // Scalar Quantization: int8 storage = svs_storage_create_sq(SVS_DATA_TYPE_INT8, error); CATCH_REQUIRE(check_storage_support(storage, error) == true); - run_build_and_search(storage); + if (storage != nullptr) { + run_build_and_search(storage); + } svs_error_free(error); }