-Wl,--no-as-needed
工作,以及应该做什么,而不是有一个更强大的方法。
简而言之:
-lHSrts-ghcXXX.so
取决于
libHSbaseXXX.so
,
libHSinteger-gmpXXX.so
和
libHSghc-primXXX.so
必须在链接过程中提供给链接器。
这里提出的解决方案依赖于大量的手工工作,并且不具有很强的可扩展性。但是我不太了解
cabal
告诉你如何使这自动化,但我希望你能迈出最后一步。
或者你可以用
-WL,——无需
-解决方案,因为你知道幕后发生了什么。
让我们从单步执行版本的链接过程开始,而不调用
foo
以某种简化的方式(
here
是来自EliBendersky的一篇很好的文章,即使是关于静态链接的):
-
链接器维护一个符号表,必须找到所有符号的定义/机器代码。让我们简化并假设,开始时它只有一个符号
main
在表中,此符号的定义未知。
-
符号的定义
主要的
找到它的对象文件
test.o
. 但是,函数
主要的
使用函数
hs_init
和
hs_exit
. 因此我们发现了
主要的
但是如果我们不知道
和
高速出口
. 所以现在我们必须寻找它们的定义。
-
在下一步中,链接器将查看
foo.so
但是
所以
没有定义任何我们感兴趣的符号(
富
未使用!)链接器只是跳过
所以
永远不会回头。
-
链接器查看
-lhsrts-ghcxx.so.
. 在那里它找到了
初始化
和
高速出口
. 因此,可以使用共享库的全部内容,但它需要定义这些符号,例如
base_GHCziTopHandler_flushStdHandles_closure
. 这意味着链接器开始寻找这些符号的定义。
-
但是,命令行中没有更多的库,因此链接器没有任何可查看的内容,并且链接失败/不成功,因为缺少某些符号的定义。
哪种情况不同?
福
是否使用?2号之后。不仅如此
初始化
和
高速出口
被通缉,但也
富
,在
所以
. 所以
所以
必须包括在内。
因为图书馆的方式
所以
已生成,包含以下信息:
>>> readelf -d dist/build/foo.so/foo.so | grep NEEDED
0x0000000000000001 (NEEDED) Shared library: [libHSrts-ghc7.10.3.so]
0x0000000000000001 (NEEDED) Shared library: [libHSbase-4.8.2.0-HQfYBxpPvuw8OunzQu6JGM-ghc7.10.3.so]
0x0000000000000001 (NEEDED) Shared library: [libHSinteger-gmp-1.0.0.0-2aU3IZNMF9a7mQ0OzsZ0dS-ghc7.10.3.so]
0x0000000000000001 (NEEDED) Shared library: [libHSghc-prim-0.4.0.0-8TmvWUcS1U1IKHT0levwg3-ghc7.10.3.so]
0x0000000000000001 (NEEDED) Shared library: [libgmp.so.10]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
>>> readelf -d dist/build/foo.so/foo.so | grep RPATH
0x000000000000000f (RPATH) Library rpath: [
/usr/lib/ghc/base_HQfYBxpPvuw8OunzQu6JGM:
/usr/lib/ghc/rts:
/usr/lib/ghc/ghcpr_8TmvWUcS1U1IKHT0levwg3:
/usr/lib/ghc/integ_2aU3IZNMF9a7mQ0OzsZ0dS]
从这些信息中,链接器知道需要哪些共享库(
NEEDED
-标记)以及它们在您的系统中的位置(
RPATH
您可以通过添加
g++ ...
-Wl,--trace-symbol=base_GHCziTopHandler_flushStdHandles_closure \
-Wl,--verbose \
-o test
到悬挂机构步骤。
如果我们强制执行
所以
通过
-WL,——无需
如@yuras所建议。
这种分析的结果是什么?
我们应该在命令行上提供所需的库(在
-lhsrts-ghcxx.so.
)而且不依赖于通过其他共享库每次添加它们。显然,有些神秘的名称只对我的安装有效:
g++ ...
-L/usr/lib/ghc/base_HQfYBxpPvuw8OunzQu6JGM -lHSbase-4.8.2.0-HQfYBxpPvuw8OunzQu6JGM-ghc7.10.3 \
-L/usr/lib/ghc/integ_2aU3IZNMF9a7mQ0OzsZ0dS -lHSinteger-gmp-1.0.0.0-2aU3IZNMF9a7mQ0OzsZ0dS-ghc7.10.3 \
-L/usr/lib/ghc/ghcpr_8TmvWUcS1U1IKHT0levwg3 -lHSghc-prim-0.4.0.0-8TmvWUcS1U1IKHT0levwg3-ghc7.10.3 \
...
-o test
现在它生成,但在运行时不加载(毕竟
rpath
只设置在
所以
但是
所以
未使用)。为了修复它,我们可以扩展
LD_LIBRARY_PATH
或添加
-rpath
链接命令行:
g++ ...
-L... -lHSbase-... -Wl,-rpath,/usr/lib/ghc/base_HQfYBxpPvuw8OunzQu6JGM \
-L... -lHSinteger-gmp-... -Wl,-rpath,/usr/lib/ghc/integ_2aU3IZNMF9a7mQ0OzsZ0dS \
-L... -lHSghc-prim-... -Wl,-rpath,/usr/lib/ghc/ghcpr_8TmvWUcS1U1IKHT0levwg3 \
...
-o test
必须有一个实用程序来自动获取路径和库名称(cabal在构建时似乎会这样做)
所以
但我不知道该怎么做,因为我对哈斯克尔/卡巴没有经验。