CGo嵌入sqlite3.c编译时ld报dlopen等符号未定义错误
CGo编译最简SQLite接口链接错误解决
问题背景
CGo初学者不依赖mattn/go-sqlite第三方包,尝试自行构建最简SQLite接口,在Linux环境执行go build编译测试程序时持续抛出链接错误:
/usr/bin/ld: $WORK/b001/_x003.o: in function `unixDlError': ./sqlite3.c:42036: undefined reference to `dlerror' /usr/bin/ld: $WORK/b001/_x003.o: in function `unixDlClose': ./sqlite3.c:42067: undefined reference to `dlclose' /usr/bin/ld: $WORK/b001/_x003.o: in function `unixDlSym': ./sqlite3.c:42063: undefined reference to `dlsym' /usr/bin/ld: $WORK/b001/_x003.o: in function `unixDlOpen': ./sqlite3.c:42022: undefined reference to `dlopen' collect2: error: ld returned 1 exit status
项目目录结构:
- go.mod
- main.go
- sqlite3.c
- sqlite3.h
当前main.go内容:
//go:build cgo // +build cgo package main /* #cgo CFLAGS: -DSQLITE_OMIT_LOAD_EXTENSION #cgo CFLAGS: -DSQLITE_THREADSAFE=1 #include "sqlite.h" */ import "C" func main() { }
使用Go版本为1.18.1,已添加SQLITE_OMIT_LOAD_EXTENSION编译宏仍报上述错误。
问题原因
报错里的dlopen/dlsym/dlclose/dlerror是Linux系统动态链接库libdl提供的接口,SQLite默认的扩展加载能力依赖这组接口。当前配置不生效有两个核心问题:
- 头文件引用错误:目录中存放的是
sqlite3.h,代码里写的是#include "sqlite.h",会导致宏定义无法正确作用到sqlite3.c的编译流程,SQLITE_OMIT_LOAD_EXTENSION没有实际生效,相关动态加载的代码没有被编译期裁剪。 - 未正确处理链接依赖:如果保留扩展加载能力,需要显式链接
libdl库;如果要彻底禁用扩展加载,需要确保编译宏在编译sqlite3.c时正确生效。
解决方案
二选一即可:
方案1:彻底禁用扩展加载(无需额外链接库)
修正头文件引用,确保编译宏正确传递,修改后的main.go内容如下:
//go:build cgo // +build cgo package main /* #cgo CFLAGS: -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_THREADSAFE=1 #include "sqlite3.h" */ import "C" func main() {}
同目录下的sqlite3.c会被cgo自动识别纳入编译,宏定义生效后会裁掉所有动态加载扩展相关的代码,不再依赖dl库的接口,可直接编译通过。
方案2:保留扩展加载能力
如果后续需要使用SQLite的运行时扩展加载功能,去掉SQLITE_OMIT_LOAD_EXTENSION宏,添加LDFLAGS配置显式链接dl库即可,修改后的main.go内容如下:
//go:build cgo // +build cgo package main /* #cgo CFLAGS: -DSQLITE_THREADSAFE=1 #cgo LDFLAGS: -ldl #include "sqlite3.h" */ import "C" func main() {}
内容的提问来源于stack exchange,提问作者JuanCarols
相关产品推荐
相关产品推荐

