Skip to content
Closed
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
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,4 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*

allure-*

!build_android.sh
allure-*
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ include_directories(${PROJECT_ROOT_DIR}/src)
option(BUILD_PYTHON_BINDINGS "Build Python bindings using pybind11" OFF)
message(STATUS "BUILD_PYTHON_BINDINGS:${BUILD_PYTHON_BINDINGS}")

option(BUILD_C_BINDINGS "Build C bindings (libzvec_c) for Rust/FFI consumers" OFF)
message(STATUS "BUILD_C_BINDINGS:${BUILD_C_BINDINGS}")

option(BUILD_TOOLS "Build tools" ON)
message(STATUS "BUILD_TOOLS:${BUILD_TOOLS}")

Expand Down
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ git_version(ZVEC_VERSION ${CMAKE_CURRENT_SOURCE_DIR})
cc_directory(ailego)
cc_directory(core)
cc_directory(db)
if(BUILD_PYTHON_BINDINGS)
if(BUILD_PYTHON_BINDINGS OR BUILD_C_BINDINGS)
cc_directory(binding)
endif()
50 changes: 47 additions & 3 deletions src/ailego/io/file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,50 @@ static inline int OpenSafely(const char *path, int flags) {
return fd;
}

static inline bool SetCloseOnExec(int fd) {
int current_flags = fcntl(fd, F_GETFD);
while (current_flags == -1 && errno == EINTR) {
current_flags = fcntl(fd, F_GETFD);
}
if (current_flags == -1) {
return false;
}
if ((current_flags & FD_CLOEXEC) != 0) {
return true;
}

int ret = fcntl(fd, F_SETFD, current_flags | FD_CLOEXEC);
while (ret == -1 && errno == EINTR) {
ret = fcntl(fd, F_SETFD, current_flags | FD_CLOEXEC);
}
return ret == 0;
}

static inline int OpenWithCloseOnExec(const char *path, int flags) {
#ifdef O_CLOEXEC
int cloexec_fd = OpenSafely(path, flags | O_CLOEXEC);
if (cloexec_fd != -1) {
return cloexec_fd;
}
if (errno != EINVAL) {
return -1;
}
#endif

int fd = OpenSafely(path, flags);
if (fd == -1) {
return -1;
}
if (!SetCloseOnExec(fd)) {
int ret = close(fd);
while (ret == -1 && errno == EINTR) {
ret = close(fd);
}
return -1;
}
return fd;
}

static inline void CloseSafely(int fd) {
int ret = close(fd);
while (ret == -1 && errno == EINTR) {
Expand Down Expand Up @@ -144,7 +188,7 @@ bool File::create(const char *path, size_t len, bool direct) {
(void)direct;
#endif

int fd = OpenSafely(path, flags);
int fd = OpenWithCloseOnExec(path, flags);
ailego_false_if_lt_zero(fd);

#ifdef F_NOCACHE
Expand Down Expand Up @@ -178,7 +222,7 @@ bool File::open(const char *path, bool rdonly, bool direct) {
(void)direct;
#endif

int fd = OpenSafely(path, flags);
int fd = OpenWithCloseOnExec(path, flags);
ailego_false_if_lt_zero(fd);

#ifdef F_NOCACHE
Expand Down Expand Up @@ -724,4 +768,4 @@ void File::MemoryWarmup(void *addr, size_t len) {
}

} // namespace ailego
} // namespace zvec
} // namespace zvec
8 changes: 7 additions & 1 deletion src/binding/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,10 @@ include(${PROJECT_ROOT_DIR}/cmake/option.cmake)
git_version(ZVEC_VERSION ${CMAKE_CURRENT_SOURCE_DIR})

# Add repository
cc_directory(python)
if(BUILD_PYTHON_BINDINGS)
cc_directory(python)
endif()

if(BUILD_C_BINDINGS)
cc_directory(c)
endif()
70 changes: 70 additions & 0 deletions src/binding/c/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
include(${PROJECT_ROOT_DIR}/cmake/bazel.cmake)
include(${PROJECT_ROOT_DIR}/cmake/option.cmake)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# ── nlohmann/json (header-only) ──────────────────────────────────────────────
include(FetchContent)
FetchContent_Declare(
nlohmann_json
GIT_REPOSITORY https://github.com/nlohmann/json.git
GIT_TAG v3.11.3
GIT_SHALLOW TRUE
)
set(JSON_BuildTests OFF CACHE BOOL "" FORCE)
set(JSON_Install OFF CACHE BOOL "" FORCE)
set(JSON_MultipleHeaders OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(nlohmann_json)

# ── Build zvec_c as a shared library ─────────────────────────────────────────
add_library(zvec_c SHARED zvec_c.cc)

target_include_directories(zvec_c
PRIVATE
${PROJECT_ROOT_DIR}/src
${PROJECT_ROOT_DIR}/src/include
)

target_link_libraries(zvec_c PRIVATE nlohmann_json::nlohmann_json)

# Replicate the same whole-archive / force_load strategy used by the Python
# binding so every algorithm implementation is included in the shared lib.
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_libraries(zvec_c PRIVATE
-Wl,--whole-archive
$<TARGET_FILE:core_knn_flat_static>
$<TARGET_FILE:core_knn_flat_sparse_static>
$<TARGET_FILE:core_knn_hnsw_static>
$<TARGET_FILE:core_knn_hnsw_sparse_static>
$<TARGET_FILE:core_knn_ivf_static>
$<TARGET_FILE:core_knn_cluster_static>
$<TARGET_FILE:core_mix_reducer_static>
$<TARGET_FILE:core_metric_static>
$<TARGET_FILE:core_utility_static>
$<TARGET_FILE:core_quantizer_static>
-Wl,--no-whole-archive
zvec_db
)
elseif (APPLE)
target_link_libraries(zvec_c PRIVATE
-Wl,-force_load,$<TARGET_FILE:core_knn_flat_static>
-Wl,-force_load,$<TARGET_FILE:core_knn_flat_sparse_static>
-Wl,-force_load,$<TARGET_FILE:core_knn_hnsw_static>
-Wl,-force_load,$<TARGET_FILE:core_knn_hnsw_sparse_static>
-Wl,-force_load,$<TARGET_FILE:core_knn_ivf_static>
-Wl,-force_load,$<TARGET_FILE:core_knn_cluster_static>
-Wl,-force_load,$<TARGET_FILE:core_mix_reducer_static>
-Wl,-force_load,$<TARGET_FILE:core_metric_static>
-Wl,-force_load,$<TARGET_FILE:core_utility_static>
-Wl,-force_load,$<TARGET_FILE:core_quantizer_static>
zvec_db
)
endif()

# Install so that Rust's build.rs (cmake crate) can find it under $OUT_DIR/lib
install(TARGETS zvec_c
LIBRARY DESTINATION lib
RUNTIME DESTINATION lib # Windows DLL goes here too
)
install(FILES zvec_c.h DESTINATION include)
Loading