当在我的 stack.yaml
中使用以下内容(尝试)通过 Stack 编译静态二进制文件时:
ghc-options:
"*": -static -optc-static -optl-static -optl-pthread -fPIC
我收到此错误:
usr/bin/ld: /usr/lib/gcc/x86_64-amazon-linux/4.8.3/crtbeginT.o: relocation R_X86_64_32 against `__TMC_END__' can not be used when making a shared object; recompile with -fPIC
/usr/lib/gcc/x86_64-amazon-linux/4.8.3/crtbeginT.o: could not read symbols: Bad value
collect2: error: ld returned 1 exit status
`gcc' failed in phase `Linker'. (Exit code: 1)
我使用启用了 docker 的堆栈和自定义的 Amazon Linux 镜像来构建与 AWS Lambda 一起使用的静态二进制文件。
我之前没有静态二进制编译的经验,所以我对这个链接器错误有点困惑。请问有什么想法吗?
这是使用 -v 的 gcc 参数:
/usr/bin/gcc -fno-stack-protector -DTABLES_NEXT_TO_CODE '-Wl,--hash-size=31' -Wl,--reduce-memory-overheads -Wl,--no-as-needed -Wl,-rpath<snipped LOADS> -lHSghc<SNIPPED LOADS> -lpq -lz -lrt -lutil -ldl -lgmp
最佳答案
关于问题的根本原因,@Reid Barton 是正确的。这里真正的问题是堆栈默认构建共享二进制文件。通过传递选项 -static
或 ghc-options: -optl-static
我们仅分别寻址 ghc 层和 ld 层。
stack
|_ cabal
|_ ghc
|_ gcc
|_ ld (linker)
解决问题的正确方法是告诉 cabal 我们需要一个静态二进制文件,因为它会引导构建。
Reddit 上的 sausade 提供了有关如何执行此操作的答案:您只需将以下内容添加到 .cabal 文件的可执行部分中即可:
directive:
`ld-options: -static`
这将暗示 cabal 我们需要一个静态二进制文件,因此它不会将 -shared
传递给 ghc。
因此,一旦您在 cabal 文件中添加了此指令,您只需运行:
堆栈安装 --ghc-options="-fPIC"
瞧!
P.S:如果您的系统上没有静态库(例如 Archlinux),ld
将回退到动态链接
之前的回答:
这是海湾合作委员会的一个老问题,没有人愿意解决。 https://bugs.launchpad.net/ubuntu/+source/gcc-4.4/+bug/640734
对于您最初的问题,这里有两个有用的链接来向您展示如何做到这一点:
关于在创建共享对象时,不能使用针对 `__TMC_END__' 的 Haskell 堆栈静态二进制重定位 R_X86_64_32,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41419102/