Skip to content
Open
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
1 change: 1 addition & 0 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ KeepEmptyLinesAtTheStartOfBlocks: false
PointerAlignment: Left
ReferenceAlignment: Left
ReflowComments: true
NamespaceMacros: ['SVS_DECLARE_NAMESPACE_VERSION']
---
68 changes: 58 additions & 10 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,12 +1,60 @@
Checks: "-*,
bugprone*,
-bugprone-easily-swappable-parameters,
-bugprone-macro-parentheses,
clang-analyzer*,
readability*,
-readability-magic-numbers,
-readability-identifier-length"
Checks: '
-*,
bugprone-argument-comment,
bugprone-sizeof-*,
bugprone-use-after-move,
clang-diagnostic-*,
-clang-diagnostic-nrvo,
-clang-diagnostic-missing-designated-field-initializers,
cppcoreguidelines-pro-type-member-init,
cppcoreguidelines-special-member-functions,
google-build-using-namespace,
misc-definitions-in-headers,
modernize-use-emplace,
modernize-use-using,
performance-faster-string-find,
performance-for-range-copy,
performance-implicit-conversion-in-loop,
performance-inefficient-algorithm,
performance-inefficient-string-concatenation,
performance-inefficient-vector-operation,
performance-move-const-arg,
performance-move-constructor-init,
performance-no-automatic-move,
performance-no-int-to-ptr,
performance-noexcept-move-constructor,
performance-trivially-destructible,
performance-type-promotion-in-math-fn,
performance-unnecessary-copy-initialization,
performance-unnecessary-value-param,
readability-operators-representation,
readability-redundant-string-init,
readability-braces-around-statements,
'

WarningsAsErrors: '
bugprone-use-after-move,
'

CheckOptions:
- key: readability-implicit-bool-conversion.AllowIntegerConditions
value: '1'
- key: bugprone-easily-swappable-parameters.MinimumLength
value: 4
- key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor
value: true
- key: cppcoreguidelines-special-member-functions.AllowImplicitlyDeletedCopyOrMove
value: 1
- key: modernize-use-using.IgnoreExternC
value: true
- key: performance-move-const-arg.CheckTriviallyCopyableMove
value: false
- key: performance-unnecessary-value-param.AllowedTypes
value: '[Pp]ointer$;[Pp]tr$;[Rr]ef(erence)?$'
- key: performance-unnecessary-copy-initialization.AllowedTypes
value: '[Pp]ointer$;[Pp]tr$;[Rr]ef(erence)?$'
- key: readability-operators-representation.BinaryOperators
value: '&&;&=;&;|;~;!;!=;||;|=;^;^='
- key: readability-redundant-string-init.StringNames
value: '::std::basic_string'
- key: readability-named-parameter.InsertPlainNamesInForwardDecls
value: true
...
7 changes: 7 additions & 0 deletions .github/scripts/build-cpp-runtime-bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ set -e # Exit on error
# Source environment setup (for compiler)
source /etc/bashrc || true

# Temporary: pip-install clang-tidy 17 to test whether the system clang-tidy
# version is the cause of the template crash. Pin setuptools <81 because the
# wheel's wrapper imports pkg_resources, which setuptools 81 removed.
# Remove once resolved.
pip install 'setuptools<81' clang-tidy==17.0.1

# Source MKL environment (required for IVF)
if [ -f /opt/intel/oneapi/setvars.sh ]; then
source /opt/intel/oneapi/setvars.sh --include-intel-llvm 2>/dev/null || true
Expand All @@ -41,6 +47,7 @@ CMAKE_ARGS=(
"-DCMAKE_INSTALL_LIBDIR=lib"
"-DSVS_RUNTIME_ENABLE_LVQ_LEANVEC=${ENABLE_LVQ_LEANVEC:-ON}"
"-DSVS_RUNTIME_ENABLE_IVF=ON"
"-DSVS_EXPERIMENTAL_CLANG_TIDY=ON"
)

if [ -n "$SVS_URL" ]; then
Expand Down
30 changes: 30 additions & 0 deletions bindings/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,23 @@ target_compile_options(${TARGET_NAME} PRIVATE
-fvisibility=hidden
)

# Optional clang-tidy integration. Reuses the top-level repo's
# cmake/clang-tidy.cmake module so the runtime build runs the same
# .clang-tidy config as the rest of the library.
option(SVS_EXPERIMENTAL_CLANG_TIDY
"Run the clang-tidy static analyzer on the cpp runtime bindings."
OFF
)
if(SVS_EXPERIMENTAL_CLANG_TIDY)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../cmake")
include(clang-tidy)
if(CLANG_TIDY_COMMAND)
set_target_properties(${TARGET_NAME}
PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}"
)
endif()
endif()

if(UNIX AND NOT APPLE)
# Don't export 3rd-party symbols from the lib
target_link_options(${TARGET_NAME} PRIVATE "SHELL:-Wl,--exclude-libs,ALL")
Expand Down Expand Up @@ -142,6 +159,19 @@ if (SVS_RUNTIME_ENABLE_LVQ_LEANVEC)
FetchContent_MakeAvailable(svs)
list(APPEND CMAKE_PREFIX_PATH "${svs_SOURCE_DIR}")
find_package(svs REQUIRED)

# Strip svs::svs_compile_options gcc-only flags for clang-tidy
if(SVS_EXPERIMENTAL_CLANG_TIDY AND TARGET svs::svs_compile_options)
get_target_property(_svs_co_opts svs::svs_compile_options INTERFACE_COMPILE_OPTIONS)
if(_svs_co_opts)
list(FILTER _svs_co_opts EXCLUDE REGEX "^-fconcepts-diagnostics-depth")
list(FILTER _svs_co_opts EXCLUDE REGEX "^-ftemplate-backtrace-limit")
set_property(TARGET svs::svs_compile_options
PROPERTY INTERFACE_COMPILE_OPTIONS "${_svs_co_opts}"
)
endif()
endif()

target_link_libraries(${TARGET_NAME} PRIVATE
svs::svs
svs::svs_compile_options
Expand Down
6 changes: 2 additions & 4 deletions bindings/cpp/include/svs/runtime/api_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@

namespace svs {
namespace runtime {
namespace v0 {

SVS_DECLARE_NAMESPACE_VERSION(0) {
class OptionalBool {
enum class Value : int8_t { Undef = -1, True = 1, False = 0 };
Value value_;
Expand Down Expand Up @@ -206,7 +205,6 @@ struct SVS_RUNTIME_API_INTERFACE ResultsAllocator {
return this->allocate(result_counts);
}
};

} // namespace v0
} // SVS_DECLARE_NAMESPACE_VERSION(0)
} // namespace runtime
} // namespace svs
6 changes: 2 additions & 4 deletions bindings/cpp/include/svs/runtime/dynamic_ivf_index.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@

namespace svs {
namespace runtime {
namespace v0 {

SVS_DECLARE_NAMESPACE_VERSION(0) {
/// @brief Abstract interface for dynamic IVF indices (supports add/delete).
struct SVS_RUNTIME_API DynamicIVFIndex : public IVFIndex {
/// @brief Utility function to check storage kind support.
Expand Down Expand Up @@ -160,7 +159,6 @@ struct SVS_RUNTIME_API DynamicIVFIndexLeanVec : public DynamicIVFIndex {
size_t intra_query_threads = 1
) noexcept;
};

} // namespace v0
} // SVS_DECLARE_NAMESPACE_VERSION(0)
} // namespace runtime
} // namespace svs
9 changes: 2 additions & 7 deletions bindings/cpp/include/svs/runtime/dynamic_vamana_index.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,14 @@

namespace svs {
namespace runtime {
namespace v0 {

SVS_DECLARE_NAMESPACE_VERSION(0) {
// Abstract interface for Dynamic Vamana-based indexes.
struct SVS_RUNTIME_API DynamicVamanaIndex : public VamanaIndex {
virtual Status add(size_t n, const size_t* labels, const float* x) noexcept = 0;
virtual Status
remove_selected(size_t* num_removed, const IDFilter& selector) noexcept = 0;
virtual Status remove(size_t n, const size_t* labels) noexcept = 0;

virtual Status reset() noexcept = 0;

// Utility function to check storage kind support
static Status check_storage_kind(StorageKind storage_kind) noexcept;

Expand Down Expand Up @@ -65,7 +62,6 @@ struct SVS_RUNTIME_API DynamicVamanaIndex : public VamanaIndex {

static Status destroy(DynamicVamanaIndex* index) noexcept;

virtual Status save(std::ostream& out) const noexcept = 0;
static Status load(
DynamicVamanaIndex** index,
std::istream& in,
Expand Down Expand Up @@ -131,7 +127,6 @@ struct SVS_RUNTIME_API DynamicVamanaIndexLeanVec : public DynamicVamanaIndex {
const VamanaIndex::DynamicIndexParams& dynamic_index_params
) noexcept;
};

} // namespace v0
} // SVS_DECLARE_NAMESPACE_VERSION(0)
} // namespace runtime
} // namespace svs
6 changes: 2 additions & 4 deletions bindings/cpp/include/svs/runtime/flat_index.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@

namespace svs {
namespace runtime {
namespace v0 {

SVS_DECLARE_NAMESPACE_VERSION(0) {
// Abstract interface for Flat indices.
struct SVS_RUNTIME_API FlatIndex {
// Utility function to check storage kind support
Expand Down Expand Up @@ -55,7 +54,6 @@ struct SVS_RUNTIME_API FlatIndex {
static Status
map_to_memory(FlatIndex** index, void* data, size_t size, MetricType metric) noexcept;
};

} // namespace v0
} // SVS_DECLARE_NAMESPACE_VERSION(0)
} // namespace runtime
} // namespace svs
6 changes: 2 additions & 4 deletions bindings/cpp/include/svs/runtime/ivf_index.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@

namespace svs {
namespace runtime {
namespace v0 {

SVS_DECLARE_NAMESPACE_VERSION(0) {
// Abstract interface for IVF (Inverted File) indices.
struct SVS_RUNTIME_API IVFIndex {
virtual ~IVFIndex();
Expand Down Expand Up @@ -170,7 +169,6 @@ struct SVS_RUNTIME_API IVFIndexLeanVec : public IVFIndex {
size_t intra_query_threads = 1
) noexcept;
};

} // namespace v0
} // SVS_DECLARE_NAMESPACE_VERSION(0)
} // namespace runtime
} // namespace svs
6 changes: 2 additions & 4 deletions bindings/cpp/include/svs/runtime/training.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@

namespace svs {
namespace runtime {
namespace v0 {

SVS_DECLARE_NAMESPACE_VERSION(0) {
struct SVS_RUNTIME_API LeanVecTrainingData {
virtual ~LeanVecTrainingData();

Expand Down Expand Up @@ -70,7 +69,6 @@ struct SVS_RUNTIME_API LeanVecTrainingData {
virtual Status save(std::ostream& out) const noexcept = 0;
static Status load(LeanVecTrainingData** training_data, std::istream& in) noexcept;
};

} // namespace v0
} // SVS_DECLARE_NAMESPACE_VERSION(0)
} // namespace runtime
} // namespace svs
6 changes: 2 additions & 4 deletions bindings/cpp/include/svs/runtime/vamana_index.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@

namespace svs {
namespace runtime {
namespace v0 {

SVS_DECLARE_NAMESPACE_VERSION(0) {
namespace detail {
struct VamanaBuildParameters {
size_t graph_max_degree = Unspecify<size_t>();
Expand Down Expand Up @@ -144,7 +143,6 @@ struct SVS_RUNTIME_API VamanaIndexLeanVec : public VamanaIndex {
const VamanaIndex::SearchParams& default_search_params = {}
) noexcept;
};

} // namespace v0
} // SVS_DECLARE_NAMESPACE_VERSION(0)
} // namespace runtime
} // namespace svs
36 changes: 20 additions & 16 deletions bindings/cpp/include/svs/runtime/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
///
/// This header defines the SVS Runtime API versioning scheme:
/// 1. Versioned namespaces (e.g., v0, v1) for API stability
/// 2. Using declarations to bring current version to parent namespace
/// 2. Inline namespace to expose the current API version at svs::runtime::*
/// 3. Clean integration points for external libraries
///
/// Usage:
Expand Down Expand Up @@ -59,21 +59,21 @@
#define SVS_RUNTIME_API_VERSION SVS_RUNTIME_VERSION_MAJOR
#endif

#define SVS_API_VERSION_NS_IMPL(version) v##version
#define SVS_API_VERSION_NS(version) SVS_API_VERSION_NS_IMPL(version)
#define SVS_RUNTIME_API_VERSION_NAMESPACE SVS_API_VERSION_NS(SVS_RUNTIME_API_VERSION)

#if (SVS_RUNTIME_API_VERSION == 0)
/// Use v0 API
/// Current API version namespace
#define SVS_RUNTIME_CURRENT_API_NAMESPACE v0
namespace svs {
namespace runtime {
/// Current API version namespace (v0)
/// All public runtime APIs live here and are accessible as svs::runtime::FunctionName
/// due to inline namespace
inline namespace v0 {
// Public runtime APIs will be defined in their respective headers
// IMPORTANT: include this header before other runtime headers to ensure proper versioning
}
} // namespace runtime
} // namespace svs
#define SVS_DECLARE_NAMESPACE_VERSION_0 inline namespace SVS_API_VERSION_NS(0)

// Forward declaration for the current version namespace as inline namespace
// This enforces compilation warnings/errors if the v0 namespace is not inlined below
namespace svs::runtime {
inline namespace v0 {}
} // namespace svs::runtime
#else
#error "Unsupported SVS Runtime major version"
#endif
Expand All @@ -86,11 +86,15 @@ inline namespace v0 {
#define SVS_RUNTIME_CREATE_API_ALIAS(alias_name, version_ns) \
namespace alias_name = svs::runtime::version_ns

/// Helper macro to declare versioned namespaces for API definitions
#define SVS_DECLARE_NAMESPACE_VERSION_IMPL(version) SVS_DECLARE_NAMESPACE_VERSION_##version
#define SVS_DECLARE_NAMESPACE_VERSION(version) SVS_DECLARE_NAMESPACE_VERSION_IMPL(version)

///
/// @brief Version information structure for runtime queries
///
namespace svs::runtime::v0 {

namespace svs::runtime {
SVS_DECLARE_NAMESPACE_VERSION(0) {
struct VersionInfo {
static constexpr int major = SVS_RUNTIME_VERSION_MAJOR;
static constexpr int minor = SVS_RUNTIME_VERSION_MINOR;
Expand All @@ -109,5 +113,5 @@ struct VersionInfo {
return major == requested_major;
}
};

} // namespace svs::runtime::v0
} // SVS_DECLARE_NAMESPACE_VERSION(0)
} // namespace svs::runtime
2 changes: 1 addition & 1 deletion bindings/cpp/src/dynamic_vamana_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ struct DynamicVamanaIndexManagerBase : public DynamicVamanaIndex {
});
}

size_t blocksize_bytes() const noexcept { return impl_->blocksize_bytes(); }
size_t blocksize_bytes() const noexcept override { return impl_->blocksize_bytes(); }

Status
remove_selected(size_t* num_removed, const IDFilter& selector) noexcept override {
Expand Down
2 changes: 2 additions & 0 deletions bindings/cpp/src/dynamic_vamana_index_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class DynamicVamanaIndexImpl {
}
}

virtual ~DynamicVamanaIndexImpl() = default;

size_t size() const { return impl_ ? impl_->size() : 0; }

size_t blocksize_bytes() const { return 1u << dynamic_index_params_.blocksize_exp; }
Expand Down
2 changes: 2 additions & 0 deletions bindings/cpp/src/vamana_index_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ class VamanaIndexImpl {
}
}

virtual ~VamanaIndexImpl() = default;

size_t size() const { return impl_ ? get_impl()->size() : 0; }

size_t dimensions() const { return dim_; }
Expand Down
Loading
Loading