0

I have c++ file a.cpp, which uses references to libx.so. a.cpp is made a shared library itself, liba.so by doing:

g++ -shared -fpic  a.cpp -o liba.so

This works fine under linux, yet in OSX, I'd need to readd the reference to x.so:

g++ -shared -fpic  a.cpp -o liba.so -L. -lx

or else:

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

However in Linux if I wish to use liba.so, I also have to add libx.so on the command line, whereas in OSX I can get by, by merely including liba.so.

Linux

g++ main.cpp -L. -la -lx

vs

OSX

g++ main.cpp -L. -la
  • Are these differences due to changes in executbale format, ELF vs Mach-O - could someone elaborate?
  • Why is the exact order of dependents needed in the case of linux?

Update

Looking at the libraries referenced:

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)

So it shows nicely that linking for liba is deferred until it is actually used in something like a main.

hbogert
  • 4,198
  • 5
  • 24
  • 38
  • nevermind the last question, it's been answered here: http://stackoverflow.com/questions/45135/linker-order-gcc – hbogert Mar 12 '14 at 20:51

3 Answers3

2

It has to do with two-level namespaces, see: http://archive.today/DeFLp

To mimic the "Linux-way" on OSX one would:

use -flat_namespace:

g++ -shared  -flat_namespace  -undefined warning -o liba.so a.o

and then use -flat_namespace in the main executable:

gcc main.cpp   -flat_namespace -o main  -L.  -la -lx

We can now also verify liba and libx are needed in main, instead of liba depending on 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)

And for 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)    

Sidenotes

Note that

gcc main.cpp   -flat_namespace -o main  -L.  -la #omission of libx

results in:

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

as in Linux, however also mind that omitting -flat_namespace and -lx does not give any warning until runtime:

$ 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 
hbogert
  • 4,198
  • 5
  • 24
  • 38
0

For the first part, I don't know. libx.so is needed in both cases, so it presumably is included by default (g++ -v ... will tell the exact low-level commands used, that should answer that).

For the second part, the linker (invoked by g++, again -v gives blow-by-blow) processes the files exactly in the order in which they are given. As your liba needs symbols from libx, they must be processed in that order (the list of symbols to be satisfied is built up, and uses/defines are matched up as new libraries are seen; no "let's go back and recheck" ever).

vonbrand
  • 11,412
  • 8
  • 32
  • 52
0

A shared library (like your liba.so) can be linked (on Linux) with another library (libx.so for you). Try ldd liba.so to find out. See also this and that.

Read Drepper's paper: How to write Shared Libraries; be aware of VDSO...

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Now I understand, by omitting (in my case) libx while compiling liba, the end executable has to figure it out, whereas: `g++ -shared -fpic a.cpp -o liba.so -L. -lx` under linux would tie libx to liba. this however does not explain why it does not work under OSX – hbogert Mar 13 '14 at 07:38