无法从MacOS交叉编译Golang库到Linux。

huangapple go评论92阅读模式
英文:

Unable to cross compile Golang library from MacOS for Linux

问题

阅读文章后,我尝试了以下命令:

env GOOS=linux GOARCH=amd64 go build -buildmode=c-shared -o hello.so testlib.go

但是出现了错误:

go: no Go source files

然后我通过执行以下命令启用了CGO:

env GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -buildmode=c-shared -o hello.so testlib.go

然后出现了一系列错误:

# runtime/cgo
linux_syscall.c:67:13: error: implicit declaration of function 'setresgid' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
linux_syscall.c:67:13: note: did you mean 'setregid'?
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/unistd.h:593:6: note: 'setregid' declared here
linux_syscall.c:73:13: error: implicit declaration of function 'setresuid' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
linux_syscall.c:73:13: note: did you mean 'setreuid'?
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/unistd.h:595:6: note: 'setreuid' declared here

以下是版本信息:

Go版本:go version go1.19.4 darwin/amd64

GCC版本:

Apple clang version 12.0.0 (clang-1200.0.32.29)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
英文:

After reading articles I tried this:

env GOOS=linux GOARCH=amd64 go build -buildmode=c-shared -o hello.so testlib.go

It gave an error:

go: no Go source files

Then I enabled CGO by doing this:

env GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -buildmode=c-shared -o hello.so testlib.go

and it gave a set of errors:

env GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -buildmode=c-shared -o hello.so testlib.go
# runtime/cgo
linux_syscall.c:67:13: error: implicit declaration of function 'setresgid' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
linux_syscall.c:67:13: note: did you mean 'setregid'?
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/unistd.h:593:6: note: 'setregid' declared here
linux_syscall.c:73:13: error: implicit declaration of function 'setresuid' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
linux_syscall.c:73:13: note: did you mean 'setreuid'?
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/unistd.h:595:6: note: 'setreuid' declared here

Below are the versions:

Go: go version go1.19.4 darwin/amd64

GCC:

=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 12.0.0 (clang-1200.0.32.29)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

答案1

得分: 2

Go的移植政策提到:
>所有Linux的一流端口都是针对只使用glibc的系统。使用其他C库的Linux系统不受完全支持,也不被视为一流。

这就排除了基于glibc替代品musl的交叉编译器解决方案用于构建GO共享库。

如果你尝试了(如答案的第一个版本中所示,请参见编辑历史记录),当你使用filenm命令进行检查时,一切看起来都很好。但是,如果你尝试在C程序中使用.so库,会出现以下崩溃:

error relocating ./libhello.so: free: initial-exec TLS resolves to dynamic definition in ./libhello.so

更多信息请参见:https://github.com/golang/go/issues/54805。

然后你需要一个基于gcc的交叉编译器-在macOS上不能使用clang进行此操作。最简单的方法是使用带有适当镜像的Docker,它将工作量减少到一个命令行:

docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp golang:1.19 env GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -buildmode=c-shared -o libhello.so testlib.go

参见https://index.docker.io/_/golang

对你的问题进行了一个小调整,将-o hello.so改为-o libhello.so,以便在基于libc的Linux上使用gcc进行简单的测试。

顺便说一下,可以这样做:

cd testdir
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd`
gcc -Wall -Wextra -L. test.c -lhello -o test
./test

或者,如果你不想在编译时静态绑定.so文件/在运行时动态加载它,而是只想在运行时直接动态加载和绑定Go函数符号,测试看起来会更简单:

gcc -Wall -Wextra test2.c -o test2
./test2
英文:

Go's porting policy mentions:
>All Linux first class ports are for systems using glibc only. Linux systems using other C libraries are not fully supported and are not treated as first class.

This then excludes cross-compiler solutions based on the glibc alternative musl for building GO shared libraries.

If you try it anyway (as in the first version of the answer, see edit history), it looks good at first sight when you check it with the file and nm command. But if you try to use the .so lib with a C program, there is the following crash:

error relocating ./libhello.so: free: initial-exec TLS resolves to dynamic definition in ./libhello.so

More info here: https://github.com/golang/go/issues/54805.

You then need a gcc based cross compiler - clang on macOS cannot be used for this. The easiest way to do this is to use Docker with an appropriate image, it reduces the effort to a single command line:

docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp golang:1.19 env GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -buildmode=c-shared -o libhello.so testlib.go

see https://index.docker.io/_/golang

One minor adjustment was to change the -o hello.so in your question to -o libhello.so to simply test with -lhello using gcc on a libc-based Linux.

By the way, this can then be done in this way:

cd testdir
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd`
gcc -Wall -Wextra -L. test.c -lhello -o test
./test

Or if you don't want to bind the .so file statically at compile time / load it dynamically at runtime as shown above, but only want to load and bind the Go function symbols directly dynamically at runtime, the test would look even simpler:

gcc -Wall -Wextra test2.c -o test2
./test2

huangapple
  • 本文由 发表于 2023年1月2日 02:23:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/74976549.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定