Reputation: 129
How to cross compile a Go program and still retain the dynamic linked to libc?
Context: The compiling host is macOS M1, target is Linux amd64. The default
result is static linked. However I still want to have dynamic linked, esp for libc part to have LD_PRELOAD ability).
Trying to force dynamic linked like this
❯ CGO_ENABLED=1 GOARCH=amd64 GOOS=linux go build -o main cmd/server/main.go
# runtime/cgo
linux_syscall.c:67:13: error: call to undeclared function 'setresgid'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
linux_syscall.c:67:13: note: did you mean 'setregid'?
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/unistd.h:593:6: note: 'setregid' declared here
linux_syscall.c:73:13: error: call to undeclared function 'setresuid'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
linux_syscall.c:73:13: note: did you mean 'setreuid'?
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/unistd.h:595:6: note: 'setreuid' declared here
Any suggestions to solve this? Many thanks
Upvotes: 4
Views: 2591
Reputation: 2720
Try out Zig as your C compiler. I've had issues cross-compiling with CGO_ENABLED=1
for years. I found this article that recommended swapping out Zig and it worked great.
https://zig.news/kristoff/building-sqlite-with-cgo-for-every-os-4cic
env CGO_ENABLED=1 CGO_CFLAGS="-D_LARGEFILE64_SOURCE" CC="zig cc -target x86_64-linux" CXX="zig c++ -target x86_64-linux" GOOS=linux GOARCH=amd64 go build
Upvotes: 0
Reputation: 129
Thanks to @Kalis suggestion. What I missed is the cross compiler.
brew tap SergioBenitez/osxct
brew install x86_64-unknown-linux-gnu
Source: https://github.com/SergioBenitez/homebrew-osxct Another source: https://github.com/messense/homebrew-macos-cross-toolchains (haven't tested yet).
❯ CC=x86_64-unknown-linux-gnu-gcc CGO_ENABLED=1 GOARCH=amd64 GOOS=linux go build main.go
Upvotes: 5
Reputation: 48
According to the documentation : Using cgo with the go command
Specifying GOOS and GOARCH is not enough , you need to specify also CC_FOR_TARGET or CC_FOR_${GOOS}_${GOARCH}. check this :
When cross-compiling, you must specify a C cross-compiler for cgo to use. You can do this by setting the generic CC_FOR_TARGET or the more specific CC_FOR_${GOOS}_${GOARCH} (for example, CC_FOR_linux_arm) environment variable when building the toolchain using make.bash, or you can set the CC environment variable any time you run the go tool.
Upvotes: 2