diff --git a/.github/scripts/build-c-api-bindings.sh b/.github/scripts/build-c-api-bindings.sh index 6967b6de..e0a8a495 100755 --- a/.github/scripts/build-c-api-bindings.sh +++ b/.github/scripts/build-c-api-bindings.sh @@ -45,7 +45,6 @@ cmake -B"${BUILD_DIR}" -S"${WORKSPACE}/bindings/c" \ -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ -DCMAKE_INSTALL_LIBDIR=lib \ -DSVS_BUILD_C_API_TESTS=ON \ - -DSVS_BUILD_EXAMPLES=ON \ -DSVS_RUNTIME_ENABLE_LVQ_LEANVEC="${ENABLE_LVQ_LEANVEC}" \ -DSVS_REQUIRE_LTO_ARCHIVE="${REQUIRE_LTO_ARCHIVE}" diff --git a/.github/scripts/test-c-api-bindings.sh b/.github/scripts/test-c-api-bindings.sh index 81476a1e..45397e5b 100755 --- a/.github/scripts/test-c-api-bindings.sh +++ b/.github/scripts/test-c-api-bindings.sh @@ -39,6 +39,7 @@ fi INSTALL_DIR="${STAGE_DIR}/install" CONSUMER_BUILD="${STAGE_DIR}/consumer-build" +EXAMPLES_BUILD="${STAGE_DIR}/examples-build" rm -rf "${STAGE_DIR}" mkdir -p "${INSTALL_DIR}" @@ -83,3 +84,16 @@ cmake -B"${CONSUMER_BUILD}" -S"${WORKSPACE}/bindings/c/tests/consumer" \ cmake --build "${CONSUMER_BUILD}" LD_LIBRARY_PATH="${LIBDIR}" "${CONSUMER_BUILD}/c_api_consumer" + +# Build and run the examples +cmake -B"${EXAMPLES_BUILD}" -S"${WORKSPACE}/examples/c" \ + -DCMAKE_PREFIX_PATH="${INSTALL_DIR}" +cmake --build "${EXAMPLES_BUILD}" + +for example in c_api_simple c_api_save_load c_api_dynamic; do + echo "::group::${example}" + # Run from the build directory: save_load creates its index in the working + # directory, which must be writable. + (cd "${EXAMPLES_BUILD}" && LD_LIBRARY_PATH="${LIBDIR}" "./${example}") + echo "::endgroup::" +done diff --git a/.github/scripts/test-c-api-unit.sh b/.github/scripts/test-c-api-unit.sh index 7ea6e322..4bd9b968 100755 --- a/.github/scripts/test-c-api-unit.sh +++ b/.github/scripts/test-c-api-unit.sh @@ -13,7 +13,7 @@ # 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. +# Run the C API unit tests out of an existing build tree. # # Inputs: # WORKSPACE repository root; defaults to this script's repo so it also runs @@ -36,12 +36,3 @@ 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 diff --git a/bindings/c/CMakeLists.txt b/bindings/c/CMakeLists.txt index 1b5e7805..7a7c50ec 100644 --- a/bindings/c/CMakeLists.txt +++ b/bindings/c/CMakeLists.txt @@ -274,6 +274,6 @@ endif() if(SVS_BUILD_EXAMPLES) add_subdirectory( "${CMAKE_CURRENT_SOURCE_DIR}/../../examples/c" - "${CMAKE_CURRENT_BINARY_DIR}/samples" + "${CMAKE_CURRENT_BINARY_DIR}/examples" ) endif() diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt index c23b1a02..a1d0ebac 100644 --- a/examples/c/CMakeLists.txt +++ b/examples/c/CMakeLists.txt @@ -12,12 +12,29 @@ # See the License for the specific language governing permissions and # limitations under the License. -foreach(SAMPLE_NAME simple save_load dynamic) - set(SAMPLE_TARGET c_api_${SAMPLE_NAME}) - list(APPEND SAMPLE_TARGETS ${SAMPLE_TARGET}) - add_executable(${SAMPLE_TARGET} ${SAMPLE_NAME}.c) +# These build two ways: +# +# - as a subdirectory of the C API build, which bindings/c adds when +# SVS_BUILD_EXAMPLES is on; +# - as a standalone project against an *installed* C API package, which is how +# CI runs them. The examples need nothing from the build tree, so testing +# them against the package makes them consumers of the shipped headers and +# exported target instead of only of freshly compiled objects. +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + cmake_minimum_required(VERSION 3.21) + project(svs_c_api_examples LANGUAGES C) + find_package(svs_c_api REQUIRED) + set(EXAMPLE_LINK_TARGET svs::svs_c_api) +else() + set(EXAMPLE_LINK_TARGET svs_c_api) +endif() + +foreach(EXAMPLE_NAME simple save_load dynamic) + set(EXAMPLE_TARGET c_api_${EXAMPLE_NAME}) + list(APPEND EXAMPLE_TARGETS ${EXAMPLE_TARGET}) + add_executable(${EXAMPLE_TARGET} ${EXAMPLE_NAME}.c) - target_link_libraries(${SAMPLE_TARGET} PRIVATE svs_c_api) -endforeach(SAMPLE_NAME) + target_link_libraries(${EXAMPLE_TARGET} PRIVATE ${EXAMPLE_LINK_TARGET}) +endforeach(EXAMPLE_NAME) -add_custom_target(c_api_samples ALL DEPENDS ${SAMPLE_TARGETS}) +add_custom_target(c_api_examples ALL DEPENDS ${EXAMPLE_TARGETS}) diff --git a/examples/c/dynamic.c b/examples/c/dynamic.c index 9f74cc43..b11341b5 100644 --- a/examples/c/dynamic.c +++ b/examples/c/dynamic.c @@ -131,7 +131,7 @@ int main() { // LeanVec/LVQ are only available in builds that include the compression // backend. When they are unavailable the build reports NOT_IMPLEMENTED (or // UNSUPPORTED_HW on hardware lacking the required ISA); fall back to simple - // storage so this sample stays runnable against a public build. + // storage so this example stays runnable against a public build. if (!storage) { svs_error_code_t code = svs_error_get_code(error); if (code == SVS_ERROR_NOT_IMPLEMENTED || code == SVS_ERROR_UNSUPPORTED_HW) { diff --git a/examples/c/save_load.c b/examples/c/save_load.c index 97cc5995..aac11cc1 100644 --- a/examples/c/save_load.c +++ b/examples/c/save_load.c @@ -133,7 +133,7 @@ int main() { // LeanVec/LVQ are only available in builds that include the compression // backend. When they are unavailable the build reports NOT_IMPLEMENTED (or // UNSUPPORTED_HW on hardware lacking the required ISA); fall back to simple - // storage so this sample stays runnable against a public build. + // storage so this example stays runnable against a public build. if (!storage) { svs_error_code_t code = svs_error_get_code(error); if (code == SVS_ERROR_NOT_IMPLEMENTED || code == SVS_ERROR_UNSUPPORTED_HW) { diff --git a/examples/c/simple.c b/examples/c/simple.c index 6d00e496..403858dd 100644 --- a/examples/c/simple.c +++ b/examples/c/simple.c @@ -121,7 +121,7 @@ int main() { // LeanVec/LVQ are only available in builds that include the compression // backend. When they are unavailable the build reports NOT_IMPLEMENTED (or // UNSUPPORTED_HW on hardware lacking the required ISA); fall back to simple - // storage so this sample stays runnable against a public build. + // storage so this example stays runnable against a public build. if (!storage) { svs_error_code_t code = svs_error_get_code(error); if (code == SVS_ERROR_NOT_IMPLEMENTED || code == SVS_ERROR_UNSUPPORTED_HW) {