在macOS上使用CGO运行"go test"时如何处理DYLD_LIBRARY_PATH问题(Golang相关)
在macOS上使用CGO运行"go test"时如何处理DYLD_LIBRARY_PATH问题(Golang相关) 我一直尝试让我们公司一个使用CGO并在Linux上构建的项目能在macOS上构建。为此,我创建了一个简单的CGO Hello World测试项目。
我可以让我的测试项目构建并运行可执行文件,并且它能够很好地遵循我为DYLD_LIBRARY_PATH设置的环境变量(因为macOS系统完整性保护允许DYLD_LIBRARY_PATH被非系统可执行文件继承——即存在于非系统位置的可执行文件)。
然而,当我运行“go test”时,它无法在DYLD_LIBRARY_PATH中找到我的原生库。我尝试设置环境变量CGO_LDFLAGS,这改变了我得到的输出,但它最终仍然抱怨找不到原生库。
以下是未设置CGO_LDFLAGS时的输出:
% go test
# localhost/cgo2.test
/Users/barry/dev/go/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: library not found for -lhello
clang: error: linker command failed with exit code 1 (use -v to see invocation)
FAIL localhost/cgo2 [build failed]
以下是设置后的输出:
% echo "CGO_LDFLAGS = $CGO_LDFLAGS"; go test
CGO_LDFLAGS = -L/Users/barry/testdir/
dyld[68952]: Library not loaded: libhello.so
Referenced from: <0F30CBC8-09BB-38FF-A929-66A67266A540> /private/var/folders/fl/yvgrj4p53w7blwlr0zwtf_5h0000gn/T/go-build1534663025/b001/cgo2.test
Reason: tried: 'libhello.so' (no such file), '/System/Volumes/Preboot/Cryptexes/OSlibhello.so' (no such file), 'libhello.so' (no such file), '/usr/local/lib/libhello.so' (no such file), '/usr/lib/libhello.so' (no such file, not in dyld cache), '/Users/barry/testdir/chello/libhello.so' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/barry/testdir/chello/libhello.so' (no such file), '/Users/barry/testdir/chello/libhello.so' (no such file), '/usr/local/lib/libhello.so' (no such file), '/usr/lib/libhello.so' (no such file, not in dyld cache)
signal: abort trap
FAIL localhost/cgo2 0.104s
我的经验推测是,“go test”正在使用默认的系统shell生成一个子进程,而该shell不会继承DYLD_LIBRARY_PATH。
有没有其他人在macOS上构建/测试使用CGO的Go语言应用程序,并找到了如何让它链接到非标准位置的动态库的方法?
我真的非常不愿意将我所有的原生库开发构建都放在/usr/local/lib中才能让它工作。
注意: 我确保将Go可执行文件安装在我的主目录中,而不是/usr/local/,以确保macOS不会将“go”视为系统可执行文件。
更多关于在macOS上使用CGO运行"go test"时如何处理DYLD_LIBRARY_PATH问题(Golang相关)的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我解决了这个问题… TMPDIR 并不是答案。答案是使用 go test -exec [我的脚本] 来执行测试,通过一个可以首先设置 DYLD_LIBRARY_PATH 的脚本。这与我之前处理 Java/Junit/Maven 时不得不采用的解决方案类似,它们也会 fork 一个进程来运行测试。
归根结底,CGO_LDFLAGS 能帮你完成链接,而 go test 的 -exec xprog 选项则允许你创建一个脚本来绕过系统完整性保护并设置你的 DYLD_LIBRARY_PATH。
更多关于在macOS上使用CGO运行"go test"时如何处理DYLD_LIBRARY_PATH问题(Golang相关)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在 macOS 上使用 CGO 运行 go test 时,可以通过以下方式解决 DYLD_LIBRARY_PATH 问题:
- 使用编译标签传递链接器参数:
// #cgo LDFLAGS: -L${SRCDIR}/../lib -lhello -Wl,-rpath,${SRCDIR}/../lib
import "C"
- 在测试时设置环境变量:
DYLD_LIBRARY_PATH=/path/to/libs go test
- 使用测试包装脚本:
#!/bin/bash
export DYLD_LIBRARY_PATH="/Users/barry/testdir:$DYLD_LIBRARY_PATH"
go test "$@"
- 在测试文件中通过 exec.Command 设置环境:
func TestMain(m *testing.M) {
os.Setenv("DYLD_LIBRARY_PATH", "/Users/barry/testdir")
os.Exit(m.Run())
}
- 使用 ldflags 指定运行时搜索路径:
CGO_LDFLAGS="-L/Users/barry/testdir -Wl,-rpath,/Users/barry/testdir" go test
- 创建符号链接到标准路径:
ln -s /Users/barry/testdir/libhello.so /usr/local/lib/libhello.so
- 使用绝对路径链接库:
// #cgo LDFLAGS: /Users/barry/testdir/libhello.so
import "C"
示例测试文件配置:
package main
// #cgo CFLAGS: -I${SRCDIR}/../include
// #cgo LDFLAGS: -L${SRCDIR}/../lib -lhello -Wl,-rpath,${SRCDIR}/../lib
// #include "hello.h"
import "C"
import "testing"
func TestHello(t *testing.T) {
C.say_hello()
}
构建命令示例:
CGO_ENABLED=1 \
CGO_LDFLAGS="-L/Users/barry/testdir -Wl,-rpath,/Users/barry/testdir" \
go test -v
这些方法可以确保 go test 在 macOS 上正确找到动态库,避免 DYLD_LIBRARY_PATH 继承问题。

