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
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,15 @@ $(BUILD_DIR): $(prefix)
$(TARGET_LOADABLE): sqlite-vec.c sqlite-vec.h $(prefix)
$(CC) \
-fPIC -shared \
-fvisibility=hidden \
-Wall -Wextra \
-Ivendor/ \
-O3 \
$(CFLAGS) \
$< -o $@

$(TARGET_STATIC): sqlite-vec.c sqlite-vec.h $(prefix) $(OBJS_DIR)
$(CC) -Ivendor/ $(CFLAGS) -DSQLITE_CORE -DSQLITE_VEC_STATIC \
$(CC) -Ivendor/ -fvisibility=hidden $(CFLAGS) -DSQLITE_CORE -DSQLITE_VEC_STATIC \
-O3 -c $< -o $(OBJS_DIR)/vec.o
$(AR) rcs $@ $(OBJS_DIR)/vec.o

Expand Down Expand Up @@ -130,14 +131,15 @@ $(LIBS_DIR)/shell.a: $(OBJS_DIR)/shell.o $(LIBS_DIR)
$(AR) rcs $@ $<

$(OBJS_DIR)/sqlite-vec.o: sqlite-vec.c $(OBJS_DIR)
$(CC) -c -g3 -Ivendor/ -I./ $(CFLAGS) $< -o $@
$(CC) -c -g3 -fvisibility=hidden -Ivendor/ -I./ $(CFLAGS) $< -o $@

$(LIBS_DIR)/sqlite-vec.a: $(OBJS_DIR)/sqlite-vec.o $(LIBS_DIR)
$(AR) rcs $@ $<


$(TARGET_CLI): sqlite-vec.h $(LIBS_DIR)/sqlite-vec.a $(LIBS_DIR)/shell.a $(LIBS_DIR)/sqlite3.a examples/sqlite3-cli/core_init.c $(prefix)
$(CC) -g3 \
-fvisibility=hidden \
-Ivendor/ -I./ \
-DSQLITE_CORE \
-DSQLITE_VEC_STATIC \
Expand Down
6 changes: 4 additions & 2 deletions site/compiling.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ There will now be `sqlite-vec.c` and `sqlite-vec.h` available in your current di

```bash
# Linux
gcc -g -fPIC -shared sqlite-vec.c -o vec0.so
gcc -g -fPIC -fvisibility=hidden -shared sqlite-vec.c -o vec0.so

# MacOS
gcc -g -fPIC -dynamiclib sqlite-vec.c -o vec0.dylib
gcc -g -fPIC -fvisibility=hidden -dynamiclib sqlite-vec.c -o vec0.dylib

# Windows, MSVC compiler
cl sqlite-vec.c -link -dll -out:sqlite-vec.dll
Expand All @@ -49,6 +49,8 @@ cl sqlite-vec.c -link -dll -out:sqlite-vec.dll
gcc -g -shared sqlite-vec.c -o vec0.dll
```

`-fvisibility=hidden` keeps the library from exporting any symbol but its entry point, `sqlite3_vec_init`. SQLite loads extensions with `RTLD_GLOBAL`, so an exported internal function can otherwise be called in place of a same-named function of another library in the process, another build of `sqlite-vec` included.

Different platforms, compiler, or architectures may require different compilation flags.

## Compile-time options
Expand Down
10 changes: 8 additions & 2 deletions sqlite-vec.h.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@
#include "sqlite3.h"
#endif

// The Makefile compiles with -fvisibility=hidden, so the entry point is the
// one symbol a shared library built from sqlite-vec exports.
#ifdef SQLITE_VEC_STATIC
#define SQLITE_VEC_API
#if defined(__GNUC__) && !defined(_WIN32)
#define SQLITE_VEC_API __attribute__((visibility("default")))
#else
#define SQLITE_VEC_API
#endif
#else
#ifdef _WIN32
#define SQLITE_VEC_API __declspec(dllexport)
#else
#define SQLITE_VEC_API
#define SQLITE_VEC_API __attribute__((visibility("default")))
#endif
#endif

Expand Down
14 changes: 14 additions & 0 deletions tests/test-loadable.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# ruff: noqa: E731

import ctypes
import os
import re
import sys
from typing import List
import sqlite3
import unittest
Expand Down Expand Up @@ -153,6 +156,17 @@ def test_modules():
assert modules == MODULES


def test_exports_only_entry_point():
# SQLite opens an extension with RTLD_GLOBAL, so calls inside one library
# can bind to another library's exported function of the same name, as they
# do between two builds of sqlite-vec loaded into one process.
suffix = {"darwin": ".dylib", "win32": ".dll"}.get(sys.platform, ".so")
lib = ctypes.CDLL(os.path.abspath(EXT_PATH + suffix))
assert hasattr(lib, "sqlite3_vec_init")
for name in ["sqlite3_api", "bitmap_new", "vec0Filter_fullscan"]:
assert not hasattr(lib, name), name


def test_vec_version():
vec_version = lambda *args: db.execute("select vec_version()", args).fetchone()[0]
assert vec_version()[0] == "v"
Expand Down