在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 args/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
答案 0 :(得分:3)
@Reid Barton是对的,关于问题的根本原因。这里真正的问题是堆栈默认构建共享二进制文件。通过选项-static
或ghc-options:-optl-static
,我们只分别处理ghc层和ld层。
stack
|_ cabal
|_ ghc
|_ gcc
|_ ld (linker)
解决问题的正确方法是告诉cabal我们想要一个静态二进制文件,因为它会引导构建。
关于如何做到这一点的答案是由reddit上的sausade提供的:你只需将以下内容添加到可执行部分的.cabal文件中:
directive:
`ld-options: -static`
这将暗示我们想要一个静态二进制文件,因此它不会将-shared
传递给ghc。
因此,一旦在cabal文件中添加了此指令,就必须运行:
stack install --ghc-options="-fPIC"
和voilà!
P.S:如果你的系统上没有静态库(比如Archlinux)ld
将回退到动态链接
上一个回答:
这是一个古老的gcc问题,无人问津。 https://bugs.launchpad.net/ubuntu/+source/gcc-4.4/+bug/640734
对于您的原始问题,这里有两个有用的链接,向您展示如何操作:
答案 1 :(得分:2)
我在这里猜测一下,但我认为这只是在构建系统的背后隐藏事物的一个例子。
写
是错误的ghc-options:
"*": -static
因为构建动态或静态库的选择会影响构建的其余部分。在这里看起来像Stack或Cabal告诉ghc构建一个动态库,这个标志覆盖了你设置-static
的尝试。结果gcc可能最终得到了选项组合-shared -static
,这导致了Erèbe的回答中提到的错误。 (如果你的标志-static
赢了-dynamic
,那么ghc可能已经成功构建了一个静态库,但是Stack / Cabal可能会对下一步该做什么感到困惑。)
执行此操作的正确方法不是在-static
中使用ghc-options
,而是告诉Stack不要首先构建共享库。我不知道你是如何在Stack中那样做的,但是Cabal标志是--disable-shared
。