制作共享库,linux需要的参数更少

时间:2014-03-12 20:35:57

标签: linux macos gcc shared-libraries

我有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
  • 由于执行格式,ELF与Mach-O的变化,这些差异是否有人可以详细阐述?
  • 为什么在linux的情况下需要确切的顺序顺序?

更新

查看引用的库:

的Mac

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)

的Linux

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这样的东西上。

3 个答案:

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

共享库(如liba.so)可以链接(在Linux上)与另一个库(libx.so)。试试ldd liba.so了解一下。另请参阅thisthat

阅读Drepper's paper: How to write Shared Libraries;注意VDSO ...