macOS下如何在Cgo中指定dylib相对路径
解决Go调用C dylib运行时找不到库的问题
核心问题
你的二进制文件中记录的库依赖路径是/usr/local/lib/libMyLibrary.dylib,但实际库存放在Go源码目录,运行时dyld会默认去系统路径查找,导致找不到依赖。
方案1:通过Cgo链接参数直接修正依赖路径
修改你的Cgo配置为以下内容:
// #cgo CFLAGS: -I${SRCDIR} // #cgo LDFLAGS: -L${SRCDIR} -lMyLibrary -Wl,-rpath,@executable_path -Wl,-change_install_name,/usr/local/lib/libMyLibrary.dylib,@executable_path/libMyLibrary.dylib import "C"
各参数作用:
-L${SRCDIR}:指定链接器在Go源码目录查找libMyLibrary.dylib-Wl,-rpath,@executable_path:告诉dyld运行时优先在可执行文件所在目录搜索依赖库-Wl,-change_install_name,old,new:直接修改二进制文件中记录的库引用路径,把原来的/usr/local/lib/libMyLibrary.dylib替换为同目录路径@executable_path/libMyLibrary.dylib
编译完成后,将libMyLibrary.dylib复制到生成的二进制文件同目录,即可直接运行。
方案2:用Go embed嵌入库,无需手动复制
如果不想手动复制库,可以用Go 1.16+的embed包将dylib嵌入二进制,运行时自动提取到同目录,完全不需要额外构建步骤:
package main import ( _ "embed" "os" "path/filepath" ) //go:embed libMyLibrary.dylib var libBytes []byte func init() { // 获取当前可执行文件路径 exePath, err := os.Executable() if err != nil { panic(err) } exeDir := filepath.Dir(exePath) libPath := filepath.Join(exeDir, "libMyLibrary.dylib") // 如果库文件不存在,从嵌入的内容写入 if _, err := os.Stat(libPath); os.IsNotExist(err) { if err := os.WriteFile(libPath, libBytes, 0755); err != nil { panic(err) } } } // #cgo CFLAGS: -I${SRCDIR} // #cgo LDFLAGS: -L${SRCDIR} -lMyLibrary -Wl,-rpath,@executable_path import "C" func main() { // 调用你的C库函数 C.your_c_function() }
这种方式编译后,二进制会自动携带dylib,首次运行时会把库提取到同目录,后续运行直接使用。
验证
编译后运行二进制,dyld将直接从同目录加载libMyLibrary.dylib,不会再出现找不到库的错误。
内容的提问来源于stack exchange,提问作者Benedikt M.
相关产品推荐
相关产品推荐

