I have a shared library and I use it to create an executable binary. I can only control the build process of the library and the executable binary and not the source files involved. As expected, the source files in executable binary refer to a lot of functions from the library.
Currently the shared library is built using the objectfiles(.o) directly.
g++ -shared ${OBJECT_FILES} -o ${SHARED_LIBRARY}
I want to publish the object files too by grouping them in a static library (.a file or achive).
To save on space, I delete all the .o files on creation of the archive file. So now, the build command is
g++ -shared ${ACRCHIVE_FILE} -o ${SHARED_LIBRARY}
The library builds fine.
But when I try to build the executable binary by linking to this shared library, the symbols refereed to by the binary are not defined and it fails to link. (undefined reference to Context::Get()
)
By my understanding it should not matter if we create the shared library using .o files directly or an archive consisting of all the .o files, but evidently either it is not possible or I may be missing something.
Shared libraries libfoo.so
should contain PIC code and static libraries libfoo.a
contain ordinary non PIC code. So you cannot create a shared library from a static one.
Shared libraries want Position Independent Code because their segment(s) is mmap(2)-ed at nearly arbitrary and variable addresses - without MAP_FIXED
... See also ASLR.
You could in principle build a static library from PIC object files, but nobody does that in practice.
You might (if you really insist) make an ELF shared object made of non-PIC code, but the result would have very bad performance; the dynamic linker would have a lot of relocations, so most segments would be unshared and the dynamic linking would be very slow.
To compile foo.cc
for a shared library into a PIC object file foo.pic.o
:
g++ -Wall -c -O foo.cc -fPIC -o foo.pic.o
To compile it for a static library int an ordinary non-PIC object file foo.o
:
g++ -Wall -c -O foo.cc -o foo.o
To make a shared library of foo.pic.o
and bar.pic.o
into libfoobar.so
linking in some libdep.so
shared library:
g++ -shared foo.pic.o bar.pic.o -ldep -o libfoobar.so
You often want to add more linking options when making a shared library like above, e.g. -Wl,-rpath,
... or -Wl,-soname,
....
BTW, it is not possible to link an archive libfoobar.a
(even if it is made of PIC files) into a libfoobar.so
because no name is undefined and requires linking some object files from libfoobar.a
(maybe you could try to undefine some symbol symb
with -u symb
but I don't recommend doing that).
To make a static library of foo.o
and bar.o
into libfoobar.a
:
ar cv libfoobar.a foo.o bar.o
Notice that ranlib (creating an index of the archive) is no more necessary since GNU ar
does its job.
Read also ld.so(8), ldd(1), ld(1), ar(1), objdump(1), readelf(1), dlopen(3) (often, you need to link the main program with -rdynamic
if it loads dlopen
-ed plugins at runtime, to enable the plugin to find some symbols in the main program).
NB: I would just build a shared library and not care about static linking at all. Notice that on some systems, PIC has a slight cost (slightly bigger and/or slower code). AFAIK, PIC overhead is less costly on x86-64 than on 32 bits Linux x86 code. On some architectures and ABIs PIC may have negligible overhead (or perhaps even be more efficient than non position independent code).
References: Drepper's paper: How to Write Shared Libraries & Levine's book: Linkers and Loaders & Program Library HowTo
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다