Mixing static libraries and shared libraries - linux

I have a project where I have one static library libhelper.a and another with my actual shared object library, libtestlib.so. My goal is to link libhelper.a into libtestlib.so. Is that possible on Linux/BSD? When I tried and created a test program I got the following errors:
./prog1:/usr/local/lib/libtestlib.so.1.0: undefined symbol ''
My guess is that this is occurring because libhelper.a was not compiled with -fPIC while libtestlib.so was. What is the proper way to build programs that use shared libraries that also have dependancies on static libraries?
Thanks!

My goal is to link libhelper.a into libtestlib.so. Is that possible on Linux?
Sure. This should do:
gcc -shared -fPIC -o libtestlib.so $(OBJS) \
-Wl,--whole-archive -lhelper -Wl,--no-whole-archive
libhelper.a was not compiled with -fPIC
It's best to rebuild libhelper.a with -fPIC. If that's not possible, above command will still work on Linux/ix86, but not on e.g. Linux/x86_64.
What is the proper way to build programs that use shared libraries that also have dependancies on static libraries?
If you include libhelper.a into libtestlib.so as above, then simple:
gcc main.c -ltestlib
is all you need. If you insist on linking with libhelper.a, then you must tell the end-user that he must link with e.g.
gcc main.c -ltestlib -lhelper
There is no way to specify that libtestlib.so depends on libhelper.a.

Related

Linking static and dynamic libraries on LINUX

I am trying to build an executable from different libraries using the below statement
g++ -fPIC -O -DUSING_PCH -D_REENTRANT -I"/app1/home1/quickfast/boost_1_61_0/include/boost-1_61" -I"/app1/home1/quickfast/boost_1_61_0/." -I"../../src" -I"../src/Examples" -I"/app1/home1/quickfast/boost_1_61_0/include" -L"." -L"/app1/home1/quickfast/boost_1_61_0/stage/lib" -L/app1/home1/quickfast/quickfast-master/lib -l"QuickFAST" -l"boost_thread-gcc44-mt-1_61" -l"boost_system-gcc44-mt-1_61" -l"boost_filesystem-gcc44-mt-1_61" -l"boost_unit_test_framework-gcc44-mt-1_61" -static -ldl -lpthread -o "../../bin/testSequences"
The above compilation statement includes lot of libraries, which are availabe as dynamic libaries(.so file) as well as static libraries (.a file). For example library boost_system-gcc44-mt-1_61 is present in the system as libboost_system-gcc44-mt-1_61.so as well as libboost_system-gcc44-mt-1_61.a . What I want is that while compilation only dynamic libraries (.so files) are picked up and static libraries are ignored. Can someone please guide.
You are telling it to pick up static libraries by using the -static link option. If you remove it, it'll probably work as you expect.

Do permanent linking to other shared libraries

currently I'm creating a shared library "libmylib.so" using libtool with statements like this:
libtool --mode=compile g++ -Wall -fPIC -shared $(CFLAGS) $(LFLAGS) $(LSTATIC)
libtool --mode=link g++ -shared -export-symbols-regex beam_ -rpath /usr/lib -lotherlib
The library created with this depends on an other (non-static) library "libotherlib.so", that's why I'm using the statement "-lotherlib".
Now when I build an executable that links against libmylib.so something strange happens: I have to link against libotherlib.so again, means I have to add a statement "-lotherlib" for this executable too.
So it seems former linking of libotherlib.so when building libmylib.so does not to be persistent. But how can I change this? How can I build libmylib.so so that it implicitely knows about its dependency to shared library libotherlib.so?
Thanks!
The answer seems to be the same like for this question: Link a static library to a shared one during build?
Big difference: when shared objects are specified for linking instead of static ones they are not included but the generated shared library remembers its dependnecy to these so's.

Link a static library to a shared one during build?

I have a problem building a shared library with GCC/Linux. Currently this shared library is created with GCC/libtool option "-shared" and everything is fine.
Now there are two additional, static libraries (.a-files) that have to be added to this shared one since they provide some functionality that is required by the shared one. Adding these static libraries with option "-l" does not help, afterwards they are not part of the .so file.
So how can I force GCC/libtool to really add the code of these static libraries to the shared library?
Thanks!
You need --whole-archive linker option in this case to command the linker to include whole static libs' content into the shared lib.
g++ -shared sample.o -o libSample.so -Wl,-whole-archive -lmylib1.a -lmylib2.a -Wl,-no-whole-archive
From man ld:
For each archive mentioned on the command line after the --whole-archive option, include every object file in the archive in the link, rather than searching the archive for the required object files. This is normally used to turn an archive file into a shared library, forcing every object to be included in the resulting shared library. This option may be used more than once.
Two notes when using this option from gcc: First, gcc doesn't know about this option, so you have to use -Wl,-whole-archive. Second, don't forget to use -Wl,-no-whole-archive after your list of archives, because gcc will add its own list of archives to your link and you may not want this flag to affect those as well.
You only need the --whole-archive parameter to force the linker to include the library, but it should be able to infer its own needs from unmatched symbols.
Ensure that any static libraries on the command-line come after their dependent object-files e.g.:
g++ -Wl,-E -g -pipe -O2 -pipe -fPIC myobjectfile.o mystaticlibrary.a -shared -o mylib.so

How to link static libs (archives) to an empty dynamic lib with GCC4

I'm using GCC on Linux to create a shared library. The library itself has no code but links to a couple of static libraries (archives) also built using GCC.
I need to export the static libs' symbols through my shared library. What happens is that the resulting shared lib is too small and it actually does not contain any of the symbols provided by the static libs mentioned above.
I also tried with a map of exported symbols but that did not help at all.
You need the linker's --whole-archive option to pull in all of the static archives:
gcc -shared -o libwhatever.so -Wl,--whole-archive -lstatic -Wl,--no-whole-archive
The -Wl is needed because --whole-archive is a linker option.
In order to do this, the code in libstatic.a will need to have been properly compiled for use in a shared object (i.e. with -fpic on platforms that require that).

Trying to statically link Boost

I am working in Linux, Eclipse CDT, g++, with Boost library. Having existing program which uses Boost thread, I try to link it statically instead of dynamically. /usr/local/lib directory contains the following files:
libbost_thread.a
libbost_thread.so
libbost_thread.1.41.0
Dynamic linking works:
g++ -o"MyProgram" ./main.o -lboost_thread
Static linking:
g++ -static -o"MyProgram" ./main.o -lboost_thread
produces huge number of messages like:
undefined reference to `pthread_mutex_init'
How can I link statically to the Boost library?
For pthread_mutex_init, you want to compile/link with -pthread option:
g++ -static -pthread -o"MyProgram" ./main.o -lboost_thread
The problem is that functions like pthread_mutex_init are in a separate library. Dynamic libraries can include the metadata for the fact that it needs the separate library (so libboost_thread.so includes the fact that it needs libpthread).
But static libraries don't have that information. So you need to provide the reference to any necessary libraries when you link statically.
As for using -pthread instead of -lpthread, it's slightly preferable because it not only links the necessary library, but provides any other options that should be used (such a -D_REENTRANT to the compiler).
Try adding -lpthread to your invocation.
On Linux a dynamic library may automatically depend on other dynamic libraries so that when you link it, you get the other libraries for free. When linking statically, there is no such system and you have to specify the other libraries manually.

Resources