我有c ++文件a.cpp,它使用对libx.so的引用。 a.cpp通过以下方式成为共享库liba.so:
g++ -shared -fpic a.cpp -o liba.so
这在linux下工作正常,但在OSX中,我需要读取对x.so的引用:
g++ -shared -fpic a.cpp -o liba.so -L. -lx
或者:
Undefined symbols for architecture x86_64:
"foo()", referenced from:
bar() in cctvRwlZ.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
但是在Linux中,如果我想使用liba.so,我还必须在命令行中添加libx.so,而在OSX中,我可以通过仅包含liba.so来实现。
的Linux
g++ main.cpp -L. -la -lx
VS
OSX
g++ main.cpp -L. -la
查看引用的库:
Darwin/liba.so:
Darwin/liba.so (compatibility version 0.0.0, current version 0.0.0)
Darwin/libx.so (compatibility version 0.0.0, current version 0.0.0)
Darwin/main:
Darwin/liba.so (compatibility version 0.0.0, current version 0.0.0)
ldd liba.so
[none, besides default]
ldd a.out
liba.so => /home/gandalf/BTSync/tutorials/cpp/sharedlibosx/liba.so (0x00007fcf89097000)
libx.so => /home/gandalf/BTSync/tutorials/cpp/sharedlibosx/libx.so (0x00007fcf88a9f000)
因此很好地证明了liba的链接是推迟的,直到它实际上用在像main这样的东西上。
答案 0 :(得分:2)
它与两级命名空间有关,请参阅: http://archive.today/DeFLp
要模仿OSX上的“Linux-way”,可以:
使用-flat_namespace:
g++ -shared -flat_namespace -undefined warning -o liba.so a.o
然后在主可执行文件中使用-flat_namespace:
gcc main.cpp -flat_namespace -o main -L. -la -lx
我们现在还可以在main中验证liba 和 libx,而不是liba,具体取决于libx
$ otool -L main
main:
liba.so (compatibility version 0.0.0, current version 0.0.0)
libx.so (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
/opt/local/lib/libgcc/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
对于liba:
otool -L liba.so
liba.so:
liba.so (compatibility version 0.0.0, current version 0.0.0)
/opt/local/lib/libgcc/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.18.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
/opt/local/lib/libgcc/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
请注意
gcc main.cpp -flat_namespace -o main -L. -la #omission of libx
结果:
Undefined symbols for architecture x86_64:
"foo()", referenced from:
import-atom in liba.so
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
就像在Linux中一样,但是也要注意省略-flat_namespace
和 -lx在运行时之前不会发出任何警告:
$ gcc main.cpp -o main -L. -la
$ main
dyld: lazy symbol binding failed: Symbol not found: __Z3foov
Referenced from: liba.so
Expected in: flat namespace
dyld: Symbol not found: __Z3foov
Referenced from: liba.so
Expected in: flat namespace
[1] 19297 trace trap main
答案 1 :(得分:0)
第一部分,我不知道。在这两种情况下都需要libx.so
,因此默认情况下可能会包含g++ -v ...
(g++
会告诉使用的确切低级命令,应该回答这个问题。)
对于第二部分,链接器(由-v
调用,再次liba
给出了逐个打击)文件完全按照给定的顺序处理。由于您的libx
需要来自{{1}}的符号,因此必须按此顺序处理它们(构建要满足的符号列表,并且当看到新库时使用/定义匹配;否则“让我们回去重新检查“永远”。
答案 2 :(得分:0)