在制作共享对象时,不能使用Haskell Stack静态二进制重定位R_X86_64_32与`__TMC_END__'

时间:2017-01-01 21:15:42

标签: haskell gcc ghc haskell-stack

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

2 个答案:

答案 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