Skip to content
Merged
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
325 changes: 20 additions & 305 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ cmake_policy(SET CMP0077 NEW)
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin" AND
(NOT DEFINED CMAKE_OSX_DEPLOYMENT_TARGET OR
CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL ""))
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING
set(ZVEC_MACOS_DEPLOYMENT_TARGET "$ENV{MACOSX_DEPLOYMENT_TARGET}")
if(NOT ZVEC_MACOS_DEPLOYMENT_TARGET)
set(ZVEC_MACOS_DEPLOYMENT_TARGET "11.0")
endif()
set(CMAKE_OSX_DEPLOYMENT_TARGET "${ZVEC_MACOS_DEPLOYMENT_TARGET}" CACHE STRING
"Minimum macOS version" FORCE)
endif()

Expand All @@ -22,308 +26,17 @@ if(MSVC)
endif()


# Parallelism for the external zvec build
set(ZVEC_BUILD_JOBS "" CACHE STRING "Parallel build jobs for external zvec project")
include(ProcessorCount)
if(NOT ZVEC_BUILD_JOBS)
ProcessorCount(ZVEC_BUILD_JOBS)
if(NOT ZVEC_BUILD_JOBS OR ZVEC_BUILD_JOBS EQUAL 0)
set(ZVEC_BUILD_JOBS 6)
endif()
endif()


# Path variables
# Build zvec and its dependencies.
set(ZVEC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/zvec)
set(ZVEC_BINARY_DIR ${CMAKE_BINARY_DIR}/zvec-build)
set(ZVEC_DEPENDENCY_LIB_DIR ${ZVEC_BINARY_DIR}/external/usr/local/lib)

get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(is_multi_config)
set(ZVEC_LIB_DIR ${ZVEC_BINARY_DIR}/lib/Release)
set(ZVEC_DEPENDENCY_LIB_DIR_MULTI_CONFIG ${ZVEC_DEPENDENCY_LIB_DIR}/Release)
else()
set(ZVEC_LIB_DIR ${ZVEC_BINARY_DIR}/lib)
endif()


# External build byproducts
if(WIN32)
set(ZVEC_DB_LIB ${ZVEC_LIB_DIR}/zvec.lib)
set(ZVEC_BYPRODUCTS
${ZVEC_LIB_DIR}/zvec_ailego.lib
${ZVEC_LIB_DIR}/zvec_core.lib
${ZVEC_LIB_DIR}/zvec_turbo.lib
${ZVEC_DB_LIB}
)
else()
set(ZVEC_DB_LIB ${ZVEC_LIB_DIR}/libzvec.a)
set(ZVEC_BYPRODUCTS
${ZVEC_LIB_DIR}/libzvec_ailego.a
${ZVEC_LIB_DIR}/libzvec_core.a
${ZVEC_LIB_DIR}/libzvec_turbo.a
${ZVEC_DB_LIB}
)
endif()

# ExternalProject does not preserve zvec's CMake target graph. Mirror its
# RaBitQ support checks and forward rabitq_fastscan -> rabitq_core explicitly.
set(ZVEC_RABITQ_SUPPORTED OFF)
set(ZVEC_RABITQ_LIBS)
if(NOT ANDROID AND NOT IOS AND CMAKE_SIZEOF_VOID_P EQUAL 8
AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64|AMD64)$"
AND (CMAKE_SYSTEM_NAME STREQUAL "Linux" OR (WIN32 AND MSVC)))
if(MSVC)
set(ZVEC_RABITQ_AVX2_FLAGS "/arch:AVX2")
set(ZVEC_RABITQ_AVX512_FLAGS "/arch:AVX512")
set(ZVEC_RABITQ_AVX512_POPCNT_FLAGS "/arch:AVX512")
else()
set(ZVEC_RABITQ_AVX2_FLAGS "-mavx2 -mfma")
set(ZVEC_RABITQ_AVX512_FLAGS "-mavx512f -mavx512bw -mavx512dq -mfma")
set(ZVEC_RABITQ_AVX512_POPCNT_FLAGS
"-mavx512f -mavx512bw -mavx512dq -mavx512vpopcntdq -mfma")
endif()

include(CheckCXXCompilerFlag)
set(ZVEC_RABITQ_SUPPORTED ON)
foreach(variant AVX2 AVX512 AVX512_POPCNT)
check_cxx_compiler_flag("${ZVEC_RABITQ_${variant}_FLAGS}"
ZVEC_COMPILER_SUPPORTS_RABITQ_${variant})
if(NOT ZVEC_COMPILER_SUPPORTS_RABITQ_${variant})
set(ZVEC_RABITQ_SUPPORTED OFF)
endif()
endforeach()
endif()
if(ZVEC_RABITQ_SUPPORTED)
foreach(component fastscan core)
list(APPEND ZVEC_RABITQ_LIBS
${ZVEC_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}rabitq_${component}${CMAKE_STATIC_LIBRARY_SUFFIX})
endforeach()
list(APPEND ZVEC_BYPRODUCTS ${ZVEC_RABITQ_LIBS})
endif()


# External build of zvec
include(ExternalProject)
set(ZVEC_BUILD_TARGETS
--target zvec_ailego
--target zvec_core
--target zvec_turbo
--target zvec
)
set(ZVEC_CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release)
set(ZVEC_BUILD_ENV)
if(APPLE)
list(APPEND ZVEC_CMAKE_ARGS
"-DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET}"
)
set(ZVEC_BUILD_ENV ${CMAKE_COMMAND} -E env
"MACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}"
)
endif()
if(MSVC)
list(APPEND ZVEC_CMAKE_ARGS
"-DBUILD_SHARED_LIBS=OFF"
"-DCMAKE_C_FLAGS=/MP"
"-DCMAKE_CXX_FLAGS=/MP"
"-DBUILD_TOOLS=OFF"
"-DCMAKE_POLICY_DEFAULT_CMP0091=NEW"
"-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded"
)
endif()
ExternalProject_Add(zvec
SOURCE_DIR ${ZVEC_SOURCE_DIR}
BINARY_DIR ${ZVEC_BINARY_DIR}
INSTALL_COMMAND "" # Skip installation
CMAKE_ARGS ${ZVEC_CMAKE_ARGS}
BUILD_ALWAYS ON
USES_TERMINAL_BUILD TRUE
TEST_COMMAND ""
BUILD_BYPRODUCTS
${ZVEC_BYPRODUCTS}
BUILD_COMMAND
${ZVEC_BUILD_ENV} ${CMAKE_COMMAND} --build <BINARY_DIR> --config Release --parallel ${ZVEC_BUILD_JOBS} ${ZVEC_BUILD_TARGETS}
)


# Add include and library search paths
include_directories(${ZVEC_SOURCE_DIR}/src/include/)
link_directories(${ZVEC_LIB_DIR} ${ZVEC_DEPENDENCY_LIB_DIR} ${ZVEC_DEPENDENCY_LIB_DIR_MULTI_CONFIG})


# --- Determine debug/release library names ---
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(GLOG_LIB glogd)
set(GFLAGS_LIB gflags_nothreads_debug)
else()
set(GLOG_LIB glog)
if(WIN32)
set(GFLAGS_LIB gflags_nothreads_static)
else()
set(GFLAGS_LIB gflags_nothreads)
endif()
endif()

# --- Dependency groups ---
find_package(Threads REQUIRED)

set(zvec_core_deps
${ZVEC_RABITQ_LIBS}
)

if (NOT WIN32)
set(zvec_ailego_deps
arrow
parquet
arrow_bundled_dependencies
${CMAKE_THREAD_LIBS_INIT}
${CMAKE_DL_LIBS}
)
set(zvec_db_deps
roaring
rocksdb
arrow
arrow_acero
arrow_bundled_dependencies
arrow_compute
parquet
antlr4-runtime
${GLOG_LIB}
${GFLAGS_LIB}
FastPFOR
lz4
snowball
utf8proc
)
else ()
set(zvec_ailego_deps
arrow_static
parquet_static
arrow_bundled_dependencies
${CMAKE_THREAD_LIBS_INIT}
${CMAKE_DL_LIBS}
)
set(zvec_db_deps
roaring
rocksdb
arrow_static
arrow_acero_static
arrow_bundled_dependencies
arrow_compute_static
parquet_static
antlr4-runtime-static
${GLOG_LIB}
${GFLAGS_LIB}
FastPFOR
lz4
snowball
utf8proc_static
rpcrt4
shlwapi
)
endif ()


# --- Create INTERFACE targets for Zvec components ---

# zvec_ailego: links libzvec_ailego.a + its deps
add_library(zvec-ailego INTERFACE)
if(WIN32)
target_link_libraries(zvec-ailego INTERFACE
zvec_ailego
${zvec_ailego_deps}
)
else()
target_link_libraries(zvec-ailego INTERFACE
-lzvec_ailego
${zvec_ailego_deps}
)
endif()

# Core and Turbo register factories through static initializers. Keep all their
# objects so algorithms and quantizers requested by name remain available.
add_library(zvec-core INTERFACE)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_libraries(zvec-core INTERFACE
-Wl,--whole-archive
zvec_core
zvec_turbo
-Wl,--no-whole-archive
-Wl,--start-group
zvec-ailego
${zvec_core_deps}
-Wl,--end-group
)
elseif(APPLE)
target_link_libraries(zvec-core INTERFACE
"-Wl,-force_load,${ZVEC_LIB_DIR}/libzvec_core.a"
"-Wl,-force_load,${ZVEC_LIB_DIR}/libzvec_turbo.a"
zvec-ailego
${zvec_core_deps}
)
elseif(ANDROID)
target_link_libraries(zvec-core INTERFACE
-Wl,--whole-archive
zvec_core
zvec_turbo
-Wl,--no-whole-archive
-Wl,--start-group
zvec-ailego
${zvec_core_deps}
-Wl,--end-group
)
elseif(WIN32)
target_link_libraries(zvec-core INTERFACE
zvec_core
zvec_turbo
zvec-ailego
${zvec_core_deps}
)
target_link_options(zvec-core INTERFACE
"/WHOLEARCHIVE:zvec_core"
"/WHOLEARCHIVE:zvec_turbo"
)
else()
message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}")
endif()

# zvec-db: links the engine DB static library + all deps.
add_library(zvec-db INTERFACE)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_libraries(zvec-db INTERFACE
${ZVEC_DB_LIB}
zvec-core
zvec-ailego
-Wl,--start-group
${zvec_db_deps}
-Wl,--end-group
)
elseif(APPLE)
target_link_libraries(zvec-db INTERFACE
${ZVEC_DB_LIB}
zvec-core
zvec-ailego
${zvec_db_deps}
)
elseif(ANDROID)
target_link_libraries(zvec-db INTERFACE
${ZVEC_DB_LIB}
zvec-core
zvec-ailego
-Wl,--start-group
${zvec_db_deps}
-Wl,--end-group
)
elseif(WIN32)
target_link_libraries(zvec-db INTERFACE
${ZVEC_DB_LIB}
zvec-core
zvec-ailego
${zvec_db_deps}
)
else()
message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}")
endif()
set(BUILD_SHARED_LIBS OFF)
set(BUILD_ZVEC_SHARED OFF)
set(BUILD_ZVEC_AILEGO_SHARED OFF)
set(BUILD_ZVEC_CORE_SHARED OFF)
set(BUILD_C_BINDINGS OFF)
set(BUILD_PYTHON_BINDINGS OFF)
set(BUILD_TOOLS OFF)
set(BUILD_CPP_EXAMPLES OFF)
add_subdirectory(${ZVEC_SOURCE_DIR} ${CMAKE_BINARY_DIR}/zvec-build EXCLUDE_FROM_ALL)


# --- The main target library ---
Expand All @@ -340,8 +53,6 @@ add_library(${PROJECT_NAME} SHARED
src/binding/types.cc
)

add_dependencies(${PROJECT_NAME} zvec)

target_include_directories(${PROJECT_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/node_modules/node-addon-api
Expand All @@ -352,9 +63,13 @@ target_include_directories(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME}
PRIVATE
${CMAKE_JS_LIB}
zvec-db
zvec
)

# Keep algorithm and quantizer factories registered by static initializers.
set_property(TARGET ${PROJECT_NAME} PROPERTY LINK_LIBRARY_OVERRIDE
"WHOLE_ARCHIVE,zvec_core,zvec_turbo")

if(MSVC)
target_link_libraries(${PROJECT_NAME} PRIVATE delayimp)
endif()
Expand Down
8 changes: 0 additions & 8 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,6 @@ After modifying the binding code, you should run the test suite to ensure your c
npm run test:unit
```

### Editor Configuration

If you are using **clangd** for code intelligence, you may want to merge the compilation database. This is necessary because the project relies on external submodules, which results in separate **compile_commands.json** files.

```bash
python ./scripts/merge_compile_commands.py
```

## Local Distribution

If you prefer to build the binding from source and generate a single, self-contained package (including the pre-built binary for your current platform), use the local packing script.
Expand Down
6 changes: 5 additions & 1 deletion scripts/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@ try {

console.log(`\nCompiling native addon. Jobs: ${JOBS}, Build type: ${BUILD_TYPE}.`);
console.log(`Running command: ${cmd}\n`);
execSync(cmd, { stdio: 'inherit', cwd: PACKAGE_ROOT });
const buildEnv = { ...process.env };
if (process.platform === 'darwin') {
buildEnv.MACOSX_DEPLOYMENT_TARGET ||= '11.0';
}
execSync(cmd, { stdio: 'inherit', cwd: PACKAGE_ROOT, env: buildEnv });
const artifacts = verifyBuildArtifacts(PACKAGE_ROOT, BUILD_TYPE);
console.log(`✅ Native addon compiled at: ${artifacts.binaryPath}`);
} catch (error) {
Expand Down
Loading
Loading