共享库或dylib中未定义符号是什么意思?

23
我有一个适用于Linux的Makefile,现在要进行移植到Darwin平台。这个Makefile需要将一堆.o文件链接在一起形成一个.so共享对象。我认为(可能错了),在Darwin中最好的替代品是dylib。所以我将-shared标志改为-dynamiclib。
现在,我要将代码链接到dylib中,这些代码依赖于很多外部库。尝试构建dylib时,会出现未定义引用的错误。但是Linux Makefile在创建.so文件的构建步骤中没有指定任何-lwhatever或-L/path/whatever选项。这是为什么呢?这是因为当你创建一个ELF .so文件时,默认情况下会保留外部引用不变,并且当加载共享库时,它会递归地加载被加载的共享库所依赖的共享库。如果共享库依赖于.a或.o文件,那么你必须将它们静态链接到共享库中,否则无法在运行时链接。如何才能在运行时加载具有未定义引用的库,除非引用也指向可动态加载的库?
总之,如果我指定
-undefined suppress -flat_namespace

在创建共享库时,它不要求我添加那些-l和-L选项。但我仍然不明白最终这是如何工作的。

2个回答

16

这个讨论串 也涉及到了这个问题。我认为关键点在于为了获得类似于Linux的链接行为,你需要指定"-undefined dynamic_lookup"标志。默认情况下,Darwin链接器会在动态库中存在未定义引用时抛出错误。你还可以使用-U选项来设置每个符号的行为。具体信息请参阅'man ld'。


1
使用 libtool
libtool -dynamic -multiply_defined suppress -install_name `basename ../../../../rlp/lib/universal-darwin9-gcc40/libbtutils.dylib` -o ../../../../rlp/lib/universal-darwin9-gcc40/libbtutils.dylib   ../../../../rlp/lib/universal-darwin9-gcc40/libbtd.a ../../../../rlp/lib/universal-darwin9-gcc40/libbttrie.a ../../../../rlp/lib/universal-darwin9-gcc40/libbtkey.a ../../../../rlp/lib/universal-darwin9-gcc40/libbtunit.a ../../../../rlp/lib/universal-darwin9-gcc40/libbtutilities.a ../../../../rlp/lib/universal-darwin9-gcc40/libbtopts.a ../../../../rlp/lib/universal-darwin9-gcc40/libbtxcode.a ../../../../rlp/lib/universal-darwin9-gcc40/libbtprops.a ../../../../rlp/lib/universal-darwin9-gcc40/libbtxml.a ../../../../rlp/lib/universal-darwin9-gcc40/libbttake3.a ../../../../rlp/lib/universal-darwin9-gcc40/libbttake5.a ../../../../rlp/lib/universal-darwin9-gcc40/libbtac.a  -lstdc++.6 -lgcc_s.10.4 ../../../../build_system/lib/universal-darwin9-gcc40/libgcc.a -lSystem -lSystemStubs`

1
谢谢,我认为那会起作用,但我也对背后发生的事情很感兴趣。 - eeeeaaii
MacOS并不完全像Linux。毕竟,它最初是NextOS。链接器有点古怪。在libtool中加上-v参数,它会告诉你它正在做什么。 - bmargulies

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接