I have doubt is it possible if I built lib1.so
using source file common.cpp
and lib2.so
using same source file common.cpp
again. Now I want to build my application APP
using this two library ,
My question are
- is it possible Or it will give me error ?
- If it will successfully built then how naming gets resolved?
F.e. let say
foo
is class incommon.cpp
.foo_v1
is object of foo in lib1.so andfoo_v2
is object of foo in lib2.so. Now during bulid ofAPP
what would happen? Also is it possible to create object of foo inAPP
application ?
Naturally one would suggest you consider building the common functionality shared by
lib1.so
andlib2.so
into a distinct shared library,libcommon.so
.But if you want nevertheless to statically link the common functionality identically1 into both
lib1.so
andlib2.so
, you can link these two shared libraries with your program. The linker will have no problem with that. Here is an illustration:common.h
common.cpp
foo.h
foo.cpp
bar.h
bar.cpp
Now we'll make two shared libraries,
libfoo.so
andlibbar.so
. The source files we need arefoo.cpp
,bar.cpp
andcommon.cpp
. First compile them all to PIC (Position Independent Code object files:And here are the object files we just made:
Now link
libfoo.so
usingfoo.o
andcommon.o
:Then link
libbar.so
usingbar.o
and (again)common.o
We can see that
common::...
symbols are defined and exported bylibfoo.so
:(
T
means defined in the code section,B
means defined in the uinitialized data section). And exactly the same is true aboutlibbar.so
Now we'll make a program linked with these libraries:
main.cpp
It calls
foo
; it callsbar
, and it callscommon::print1
.It runs like:
Which is just fine. You might perhaps have worried that two copies of the static class variable
common::count
would end up in the program - one fromlibfoo.so
and another fromlibbar.so
, and thatfoo
would increment one copy andbar
would increment the other. But that didn't happen.How did the linker resolve the
common::...
symbols? Well to see that we need to find their mangled forms, as the linker sees them:There they all are and we can tell which one is which with
c++filt
:Now we can re-do the linkage of
prog
, this time asking the linker to tell us the names of the input files in which thesecommon::...
symbols were defined or referenced. This diagnostic linkage is a bit of a mouthful, so I'll\
-split it:So the linker tells us that it linked the definition of
common::count
from./libfoo.so
. Likewise the definition ofcommon::print1
. Likewise the definition ofcommon::print2
. It linked all thecommon::...
symbol definitions fromlibfoo.so
.It tells us that the reference(s) to
common::print1
inmain.o
was resolved to the definition inlibfoo.so
. Likewise the reference(s) tocommon::count
inlibbar.so
. Likewise the reference(s) tocommon::print1
andcommon::print2
inlibbar.so
. All thecommon::...
symbol references in the program were resolved to the definitions provided bylibfoo.so
.So there were no multiple definition errors, and there is no uncertainty about which "copies" or "versions" of the
common::...
symbols are used by the program: it just uses the definitions fromlibfoo.so
.Why? Simply because
libfoo.so
was the first library in the linkage that provided definitions for thecommon::...
symbols. If we relinkprog
with the order of-lfoo
and-lbar
reversed:then we get exactly the opposite answers. All the
common::...
symbol references in the program are now resolved to the definitions provided bylibbar.so
. Becauselibbar.so
provided them first. There is still no uncertainty, and it makes no difference to the program, because bothlibfoo.so
andlibbar.so
linked thecommon::...
definitions from the same object file,common.o
.The linker does not try to find multiple definitions of symbols. Once it has found a definition of a symbol S, in an input object file or shared library, it binds references to S to the definition it has found and is done with resolving S. It does not care if a shared library it finds later can provide another definition of S, the same or different, even if that later shared library resolves symbols other than S.
The only way in which you can cause a multiple definition error is by compelling the linker to statically link multiple definitions, i.e. compel it to physically merge into the output binary two object files
obj1.o
andobj2.o
both of which contain a definition S. If you do that, the competing static definitions have exactly the same status, and only one definition can be used by the program, so the linker has to fail you. But it does not need to take any notice of a dynamic symbol definition of S provided by a shared library if it has already resolved S, and it does not do so.[1] Of course, if you compile and link
lib1
andlib2
with different preprocessor, compiler or linkage options, you can sabotage the "common" functionality to an arbitary extent.