MacOS 上 SQLite-Vec 扩展加载报 dlopen 错?这 2 处改完就能跑
【免费下载链接】sqlite-vecA vector search SQLite extension that runs anywhere!项目地址: https://gitcode.com/GitHub_Trending/sq/sqlite-vec
$ python3 demo.py sqlite3.OperationalError: dlopen(/path/to/dist/vec0.dylib, 0x0002): invalid dylib $ sqlite3 sqlite> .load ./vec0.dylib Parse error near line 2: unable to open library "./vec0.dylib" (14)dlopen failed和SQLITE_CANTOPEN,是 macOS 上折腾 SQLite-Vec 扩展加载时最常见的两张脸。别急,这两个坑都不在代码里,一个出在架构,一个出在路径。跟着下面的步骤走,10 分钟内能把扩展跑起来。
make 一把,拿到 dist/vec0.dylib
先说结论:编译产物叫dist/vec0.dylib,不是很多教程里写的sqlite-vec.dylib。找错文件名是路径坑的源头之一。
克隆仓库
把仓库克隆到本地:
git clone https://gitcode.com/GitHub_Trending/sq/sqlite-vec cd sqlite-vec # 预期输出: Cloning into 'sqlite-vec'... 之后无报错,目录切换成功拉取 SQLite amalgamation,再编译
编译前要先跑一遍 vendor 脚本,把 SQLite 官方的 amalgamation 源码下到vendor/目录,编译扩展时会用到里面的sqlite3ext.h,这步跳过后面 make 会直接失败:
./scripts/vendor.sh然后make loadable只编译可动态加载的库。Makefile 会自己认出你的机器架构,自动补 SIMD 加速参数:Intel 的 Mac 走 AVX,M 芯片走 NEON,所以"在谁机器上编,就是谁的架构":
make loadable # 预期输出: 最后一行类似 dist/vec0.dylib,无 error 即成功编译完用file验一下产物,架构和机器对得上才算数:
file dist/vec0.dylib # 预期输出: Mach-O 64-bit dynamically linked shared library arm64 #(M 芯片是 arm64,Intel 是 x86_64)把 dist 目录写进 shell,一次配置长期有效
DYLD_LIBRARY_PATH相当于 macOS 版LD_LIBRARY_PATH,作用是指明动态库去哪里找。注意它和.load的相对路径是两套独立机制:.load ./xxx相对的是你敲命令时所在的目录,不是扩展库住哪儿。所以建议.load用绝对路径,别依赖当前目录。
打开 shell 配置文件(zsh 用户是~/.zshrc,bash 用户是~/.bash_profile),把 dist 目录追加进去:
echo 'export DYLD_LIBRARY_PATH="$PWD/dist:$DYLD_LIBRARY_PATH"' >> ~/.zshrc保存后让配置立即生效并确认:
source ~/.zshrc echo $DYLD_LIBRARY_PATH # 预期输出: /path/to/sqlite-vec/dist: 开头包含 dist 目录的完整路径sqlite3 里敲一句,版本回来就对了
打开sqlite3命令行,加载扩展并查版本,vec_version()返回版本号就代表扩展真正跑起来了:
sqlite3 # 预期输出: 进入 sqlite> 交互提示符 sqlite> .load /path/to/sqlite-vec/dist/vec0.dylib sqlite> select vec_version(); # 预期输出: v0.1.10-alpha.4(版本号随版本变化)⚠️ 如果.load时直接报SQLITE_CANTOPEN,是路径的事,回上一节再核对一次;报dlopen相关错误则是架构不匹配,跳下面"翻车"部分处理。
除了命令行,Python 里也能加载。macOS 的 Pythonsqlite3模块默认禁用扩展加载,必须先调enable_load_extension,这是和 Linux 上手感差最大的地方:
import sqlite3 conn = sqlite3.connect(":memory:") conn.enable_load_extension(True) conn.execute('SELECT load_extension("/path/to/sqlite-vec/dist/vec0.dylib")') conn.execute("SELECT vec_version()") # 预期输出: 无异常,vec_version() 返回版本号翻车就这两处,各一刀
架构对不上,file 一下就有答案
症状:M 芯片上加载报invalid dylib或dlopen ... failed。原因:dylib 的编译架构和运行机器对不上,最常见的是 x86 编译的库跑在 Apple Silicon 上。
先核对产物架构:
file dist/vec0.dylib uname -m # 预期输出: 两行架构一致,比如都是 arm64不一致的话,在当前机器上直接重编即可,make 会自动选对指令集:
make loadableCANTOPEN 十有八九是路径
症状:.load报unable to open library(错误码 14,即SQLITE_CANTOPEN)。原因:.load用的相对路径跟当前工作目录不匹配,或者文件压根不在那个位置。
先确认产物在不在:
ls -l dist/vec0.dylib # 预期输出: -rwxr-xr-x ... dist/vec0.dylib在,就把.load换成文件的绝对路径再试一次;不,回编译那节重跑make loadable。
Python 报 not authorized 的开关
症状:Python 里执行load_extension抛OperationalError: ... not authorized。原因:macOS 的sqlite3模块默认把扩展加载关了。
注意顺序,先开权限再加载:
conn.enable_load_extension(True) conn.execute('SELECT load_extension("/path/to/sqlite-vec/dist/vec0.dylib")')记住这三条,下次不会再踩
- 编译产物在
dist/vec0.dylib,file输出必须和uname -m对得上,这是第一条命。 .load的相对路径跟着"你敲命令的目录"走,DYLD_LIBRARY_PATH管的是全局查找,两者互不相通,别混着调试。- Python 场景里
enable_load_extension(True)是硬前提,漏了必报not authorized,和路径无关。
更多加载方式可以参考仓库里的 site/getting-started/installation.md,Python 集成的细节在 site/using/python.md。
【免费下载链接】sqlite-vecA vector search SQLite extension that runs anywhere!项目地址: https://gitcode.com/GitHub_Trending/sq/sqlite-vec
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考