g++ link an .a file and its dependencies into a static .so - linux

I have a libSomelib.a that can be linked to an executable by the following command:
g++ -L. -lsomeLib -lpcrecpp -lpcre -lpthread main.cpp -o main
But how could I link a shared object from it, that contains all depentencies?
I want to achieve the following with my new someLib.so:
g++ -L. -lsomeLib main.cpp -o main
I have tried the following:
g++ -shared -L. -lsomeLib -lpcrecpp -lpcre -lpthread -o libSomelib_static.so
This gives me an .so file with no symbols.
PS: I'm completely beginer of compilers.

There are a few issues at play here:
Linkers only use object files from an archive that resolve unresolved symbols. This is why the order of archives in the command line is important. Correct order is object files, followed by static libraries, followed by shared libraries. E.g. g++ -o main -pthread main.cpp -L. -lsomeLib -lpcrecpp -lpcre.
When you build the shared library that archive does not resolve any symbols, hence the linker ignores it completely. See 1.
Object files for a shared library must be compiled as position independent code (-fPIC compiler flag). Archives are normally built without this flag.
Use -pthread flag both when compiling and linking multi-threaded applications, not -lpthread.

Related

Linker is unable to locate curl_global_init

I am compiling a C++ application on Ubuntu 18.04.
The linker is unable to pickup the required functions from the library or it is not locating the right library
I have libcurl.so located at /usr/local/lib
nm -D lists all the functions I need with T prefix. Yet when I compile as follows
g++ -std=c++17 -lcurl tz.o main.o
I get
/usr/bin/ld: tz.o: in function 'date::curl_global()':
tz.cpp:(.text+0x9aef): undefined reference to 'curl_global_init'
I tried installing openssl-dev. No joy. So I uninstalled it.
try
g++ -std=c++17 tz.o main.o -lcurl
instead... g++ is shit in some ways, like argument ordering. (all i did was to make -lcurl the last argument instead of argument #3)

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.

Creating shared objects with mpicc - does not seem to find pthread routines

I am learning to create shared libraries in Linux, subsequently to develop parallelised scientific computing programs. I took the toy example from here for shared library. I modified the Makefile from this question to suit the toy example. My Makefile now is
CC = mpicc
INCDIR = -I ./
CFLAGS = -Wall -rdynamic -g -fPIC $(INCDIR)
LIBADD = -L ./ -lcalc_mean
all: dyn_main.out
dyn_main.out: libcalc_mean.so
$(CC) -o $# main.c $(LIBADD)
libcalc_mean.so: calc_mean.o
$(CC) -shared --export-dynamic -o $# $<
calc_mean.o: calc_mean.c
$(CC) $(CFLAGS) -c $<
clean :
-rm *.o
-rm *.out
-rm *.so
.PHONY:
clean
When I make with CC = gcc in the Makefile, things run fine. I could run the binary even with mpirun.
When I have CC = mpicc in the Makefile, I get the following error.
mpicc -Wall -rdynamic -g -fPIC -I ./ -c calc_mean.c
mpicc -shared --export-dynamic -o libcalc_mean.so calc_mean.o
mpicc -o dyn_main.out main.c -L ./ -lcalc_mean
/home/elan/localinstalls/lib/libmpi.so: undefined reference to `pthread_key_create'
/home/elan/localinstalls/lib/libmpi.so: undefined reference to `pthread_getspecific'
/home/elan/localinstalls/lib/libmpi.so: undefined reference to `pthread_create'
/home/elan/localinstalls/lib/libmpi.so: undefined reference to `pthread_atfork'
/home/elan/localinstalls/lib/libmpi.so: undefined reference to `pthread_setspecific'
/home/elan/localinstalls/lib/libmpi.so: undefined reference to `pthread_join'
collect2: ld returned 1 exit status
make: *** [dyn_main.out] Error 1
I added the path to libpthread.so,.a to LD_LIBRARY_PATH, but no avail. I have a self compiled openmpi-1.5.4. If this were a openmpi dependency, shouldn't it have been resolved when I configured it?
Is this error familiar? I am using Ubuntu 11.04, with gcc 4.5.2. I already built and run some mpi parallel programs successfully. But they are large packages configured with autotools. One of the config.log s display the same error. But even that one runs fine.
References to / examples of creating static/shared libraries with mpi will also be appreciated (though Openmpi discourages fully static libraries.)
Thank you very much,
Elan.
You should be able to just add -lpthread.
Open MPI probably didn't add it because it found that adding -lpthread wasn't necessary (likely due to some other dependency implicitly pulling in the pthread library). But with the linker flags you're using, you might well have changed that implicit dependency, so the pthread library isn't being pulled in automatically anymore.
If adding -lpthread to the command line fixes the issue, then see this FAQ entry for how to update the wrapper compilers (E.g., add your own flags): http://www.open-mpi.org/faq/?category=mpi-apps#override-wrappers-after-v1.0
You can see what options the Open MPI compiler wrapper supplies to the underlying compiler and linker using the -showme option or one of its specific variants:
-showme:compile to just show the compiler flags
-showme:link to just show the linker flags
For example:
$ mpicc -showme
icc -I/opt/MPI/openmpi-1.5.3/linux/intel/include -I/opt/MPI/openmpi-1.5.3/linux/intel/include/openmpi -fexceptions -pthread -I/opt/MPI/openmpi-1.5.3/linux/intel/lib -Wl,-rpath,/opt/MPI/openmpi-1.5.3/linux/intel/lib -I/opt/MPI/openmpi-1.5.3/linux/intel/lib -L/opt/MPI/openmpi-1.5.3/linux/intel/lib -lmpi -ldl -Wl,--export-dynamic -lnsl -lutil

How can I force linking with a static library when a shared library of same name is present

Suppose I have a file main.cpp which uses sin() function which is defined in libmath. Also suppose that we have both libmath.a and libmath.so available in the same directory. Now if I issue the command g++ -o main main.cpp -lmath the default behaviour of Linux is to link to the shared library libmath.so. I want to know is there a way to force the program to link with the static library libmath.a without deleting or moving the shared library?
You'll need to pass the -static to the linker, but only for particular libraries you want. e.g.:
g++ -o main main.cpp -Wl,-Bstatic -lmath -Wl,-Bdynamic
If your linker supports -l:<filename> you may use:
g++ -o main main.cpp -l:libmath.a
Use this function:
g++ -o main main.cpp /path_to/libmath.a

Resources