Linking libgsl and libgslcblas failing - gcc

I am attempting to create a shared library that provides an easier interface for calling FFT and IFFT functions from GSL in C.
My C file.
fft.c
Building the object file.
gcc -c -Wall -Wextra -O2 -fPIC fft.c -o fft.o
Object file builds perfectly.
Then the link command.
gcc -L/usr/local/lib -Wl,-rpath=/usr/local/lib -shared -o libfft.so fft.o -lgsl -lgslcblas
No errors...
However, running the following command
ldd libfft.so
prints the following output.
linux-vdso.so.1 found
libgsl.so => /usr/local/lib/libgsl.so <--- CORRECT
libc.so.6 => found
libm.so.6 => found
/lib64/ld-linux-x86-64.so.2
libgslcblas.so => not found <--- This is confusing me...
For some reason the libgsl.so is found in the correct location on my computer, but the libgslcblas.so is saying not found.
Both libraries are in that directory.
Thank you so much for any answers.
EDIT (09/07/2022)
After looking into the recommendation by
https://stackoverflow.com/users/2581418/vitsoft
the Dynamic section of the shared library was only showing libgsl.so as being (NEEDED). Then I thought maybe the actual libgsl.so I have is dependent upon libgslcblas.so.
Running the ldd command on libgsl.so, shows that it relies on libgslcblas.so, and it is not found. So, I may have built GSL incorrectly from source?..
This was exactly the problem, make sure to follow the directions of GSL when they tell you how to build their source code!

Related

How to link OpenSSL engine with a third party dynamic library

I have a custom shared object file as an OpenSSL engine and it is working fine with pthread. I was trying to use a third-party thread library instead of pthread. However, upon linking and running the engine, I'm getting a Segmentation fault. I just could not figure out why. I have a hunch that my linking with the newly built dynamic library is not correct,
Following is what I did
Makefile to create a dynamic library
CC = GCC
CFLAGS = -Wall -fPIC -g -O3 -MD
LDFLAGS = -shared
OBJ = uthread.o
all: libuthread.so
libuthread.so: $(OBJ)
$(LD) -shared -o $(#) $(OBJ)
clean:
rm -f *.o *.d libuthread.so
-include *.d
%.o: %.c
$(CC) $(CFLAGS) -o $# -c $<
Copy libuthread.so library to /lib/x86_64-linux-gnu/
My Makefile to compile my OpenSSL engine
gcc -g -fPIC -c -fomit-frame-pointer testengine.c
gcc -g -shared -o libtestengine.so rsa-engine.o rsa/rsa.o rsa/bignum.o
rsa/aes.o -Wl,-Bstatic -Wl,-Bdynamic -lcrypto -luthread
mv libtestengine.so rsaEngine.so
After compilation, $ldd rsaEngine.so shows the following,
linux-vdso.so.1 => (0x00007ffded367000)
libcrypto.so.1.1 => /opt/openssl/lib/libcrypto.so.1.1 (0x00007f895c5fa000)
libuthread.so => /lib/x86_64-linux-gnu/libuthread.so (0x00007f895c3f4000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f895c02a000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f895be26000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f895bc09000)
/lib64/ld-linux-x86-64.so.2 (0x00007f895cd56000)
I use gdb to find out what causes the segmentation fault, and I find out that uthread_join(), is failing at some point. Can someone please tell me what I'm, doing wrong?
N.B: I checked the library with a simple program and the library works fine.
I just could not figure out why.
There could be a number of reasons:
A threading bug in your code (which happens not to cause a crash with system libpthread library, but causes a crash with uthread.o, whatever it is),
A bug in uthread.o which is exposed by your test, but not by the simple program you tried,
A bug somewhere else.
There is no way for us to tell with the info provided.
Your first step should be to run the program under debugger and figure out where it crashes, and then why.
I have a hunch that my linking with the newly built dynamic library is not correct
I have a hunch that your hunch is wrong. There doesn't seem to be anything wrong with your linking.

gcc build links but shared library does not appear with ldd

I've a program that I must build. The program depends on libA, and libA depends on libB. Both libs are in the same folder but ldd libA.so does not include libB.so so I must add it while linking it.
This is my gcc command:
gcc -L/path/to/libraries/lib -lA -lB -I/path/to/libraries/include main.cpp
The program builds and links, but it does not start. It gives me following error:
./a.out: symbol lookup error: /path/to/libraries/lib/libA.so: undefined symbol: symbol_used_in_libA_but_defined_in_libB
With ldd I can see that libB.so is not included in my binary:
linux-vdso.so.1 => (0x00007fffaecd9000)
libA.so => /path/to/libraries/lib/libA.so (0x00007effc02a4000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007effbfebb000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007effbfca5000)
/lib64/ld-linux-x86-64.so.2 (0x00007effc05cb000)
I have these conditions:
/path/to/libraries is inside LD_LIBRARY_PATH
running ldconfig is ok and ldconfig -p find both libA.so and libB.so
If in gcc command I change -lB with -lBB it gives me a linker error, so I think that gcc find correctly libB.so even if it does not link it inside the executable.
What I'm doing wrong? What I can do in order to link the executable to both libraries?
Most Linux distributions (I assume you are using Linux based on the output of ldd) seem to configure gcc as to pass --as-needed to ld by default (e.g., see here for Debian). This means the final library/executable will only depend on a library (i.e., have a DT_NEEDED tag for that library) if some symbol of that library is actually used by the library/executable.
In your case, main.cpp does not use any functions of libB so the linker does not add libB as a dependency of the final executable. You can work around it by passing the --no-as-needed flag to the linker. E.g.,
gcc -Wl,--no-as-needed ...
Of course, the proper fix is to relink libA and make sure it lists libB as a dependency.

CMake: correctly linking system library using gcc

I have a static libary mylib that depends on the math library.
If I first link mylib with math and then to my executable it works:
add_executable(myapp main.c)
target_link_libraries(mylib m)
target_link_libraries(myapp mylib)
But if I do the linking directly with the executable it fails when using gcc (with clang it works!)
add_executable(myapp main.c)
target_link_libraries(myapp m mylib)
Why does this make any difference?
I thought that it is anyway not possible to link libraries together?
When using cmake's target_link_libraries it does not mean you will link anything. It rather will create a dependency between a target and a library of type/action link.
I guess that the actually build line of the first example will result in something like that:
gcc -o myapp myapp.o -lmylib -lm
and the second one
gcc -o myapp myapp.o -lm -lmylib
. If mylib has references to m the second example (might) not link.
Try to run make VERBOSE=1 and study the command-line of the link-process to really understand what's happening. The linker of clang is maybe intelligent and waits for all calls to be linked before actually dropping a library during the link-process.
When using target_link_libraries it matters in which order you specify linked libraries.
This does not work when using gcc (at least in v4.6.3):
target_link_libraries(myapp m mylib)
while this works:
target_link_libraries(myapp mylib m)
So all libraries mylib depends on have to come after mylib.
If you track down the actual linker invocation with make VERBOSE=1 you will find this for the broken example:
gcc main.c.o -o luatest -rdynamic -lm mylib.a
and this for the working one:
gcc main.c.o -o luatest -rdynamic mylib.a -lm
Invoking clang with the exact same parameters works in both cases!
So #PatrickB seems to be right:
The linker of clang is maybe intelligent and waits for all calls to be
linked before actually dropping a library during the link-process.

Linking with dynamic library with dependencies

Consider the following scenario:
Shared Library libA.so ,with no dependencies.
Shared Library libB.so, with libA.so as its dependency.
I want to compile a binary file that links with the libB.
Should I link the binary with libB only or with libA either?
Is there any way to link only with the direct dependencies, letting the resolution of unresolved symbols from the dependencies for runtime?
I'm worried about the fact that the library libB implementation may change in the future, introducing other dependencies (libC, libD, libE for instance). Am I going to have problems with that?
In other words:
libA files: a.cpp a.h
libB files: b.cpp b.h
main program files: main.cpp
Of course, b.cpp includes a.h and main.cpp includes b.h.
Compilation commands:
g++ -fPIC a.cpp -c
g++ -shared -o libA.so a.o
g++ -fPIC b.cpp -c -I.
g++ -shared -o libB.so b.o -L. -lA
Which of the bellow options should I use?
g++ main.cpp -o main -I. -L. -lB
or
g++ main.cpp -o main -I. -L. -lB -lA
I couldn't use the first option. The linker complains about the unresolved symbols from the library libA. But it sound a little strange to me.
Thanks very much.
-- Updated comments:
When I link the binary, the linker will try to resolve all symbols from the main and the libB. However, libB has undefined symbols from the libA. That's why the linker complains about that.
That's why I need to link with the libA too.
However I found a way to ignore unresolved symbols from shared libraries.
Looks like I should use the following command line to do that:
g++ main.cpp -o main -I. -L. -lB -Wl,-unresolved-symbols=ignore-in-shared-libs
Looks like it is still possible to use the -rpath option.
However I need to understand it a little better.
Does anyone knows any possible pitfalls when using the -Wl,-unresolved-symbols=ignore-in-shared-libs option?
-- Updated comments 2:
-rpath should not be used for this purpose. It is useful to force a library to be found in a given directory. The -unresolved-symbol approach looks much better.
Thanks again.
It looks like you are most of the way there already. Well done with your investigation. Let's see if I can help clear up the 'why' behind it.
Here's what the linker is doing. When you link your executable ('main' above) it has some symbols (functions and other things) that are unresolved. It will look down the list of libraries that follow, trying to resolve unresolved symbols. Along the way, it finds that some of the symbols are provided by libB.so, so it notes that they are now resolved by this library.
However, it also discovers that some of those symbols use other symbols that are not yet resolved in your executable, so it now needs to resolve those as well. Without linking against libA.so, your application would be incomplete. Once it links against libA.so, all symbols are resolved and linking is complete.
As you saw, the use of -unresolved-symbols-in-shared-libs, doesn't fix the problem. It just defers it so that those symbols are resolved at run time. That's what -rpath is for: to specify the libraries to be searched at run time. If those symbols can't be resolved then, your app will fail to start.
It's not an easy thing to figure out library dependencies because a symbol could be provided by more than one library and be satisfied by linking against any one of them.
There is another description of this process here: Why does the order in which libraries are linked sometimes cause errors in GCC?
For dynamic linking only with direct dependencies you can use -Wl,--as-needed with adding the libs after -Wl,--as-needed:
gcc main.c -o main -I. -L. -Wl,--as-needed -lB -lA
For checking the direct dependencies you should use readelf instead of ldd because ldd also shows the indirect dependencies.
$ readelf -d main | grep library
0x0000000000000001 (NEEDED) Shared library: [libB.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
ldd also shows the indirect dependencies:
$ LD_LIBRARY_PATH=. ldd ./main
linux-vdso.so.1 (0x00007fff13717000)
libB.so => ./libB.so (0x00007fb6738ed000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb6734ea000)
libA.so => ./libA.so (0x00007fb6732e8000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb673af0000)
If you use cmake, you can add the following lines to include only direct dependencies:
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_SHARED_LINKER_FLAGS}")
Another option is to use libtool
If you change the g++ call to libtool --mode=compile g++ to compile the source code and then libtool --mode=link g++ to create the application off of libB, then libA will be linked automatically.
This is an interesting post - I was banging my head with this as well, but I think you miss a point here..
The idea is as follows, right ?
main.cpp =(depends)=> libB.so =(depends)=> libA.so
Let's further consider that ..
In a.cpp (and only there) you define a class / variable, let's call it "symA"
In b.cpp (and only there) you define a class / variable, let's call it "symB".
symB uses symA
main.cpp uses symB
Now, libB.so and libA.so have been compiled as you described above. After that, your first option should work, i.e.:
g++ main.cpp -o main -I. -L. -lB
I guess that your problem originates from the fact that
in main.cpp you also refer to symA
Am I correct?
If you use a symbol in your code, then that symbol must be found in an .so file
The whole idea of inter-referencing shared libraries (i.e. creating APIs), is that the symbols in the deeper layers are hidden (think of peeling onions) and not used.
.. i.e. don't refer to symA in your main.cpp, but only to symB instead (and let symB to refer symA only).

Compiling a dynamically linked library

I'm currently trying to compile a dynamically linked library (for a plugin system) using Windows and MinGW.
I compile each objects using this command line :
mingw-g++ -fPIC test.cpp
And the library using this line:
mingw-g++ -rdynamic -shared -Wl,-soname,test.so.1 -o test.so test.o
It doesn't work at all (using GCC with Linux, a similar line works though) : fPIC and rdynamic are ignored for some reason.
And while trying to make the library, it fails because the compiler try to link it with objects that are supposed to be resolved as I dynamically link it with the main binary.
So how do you compile this using MinGW?
Thanks :) !
-fPIC and -rdynamic are ignored because they are unused for Windows.
Also, .so is not the correct output extension for libraries on Windows.
To make a shared library for/on windows with GCC:
mingw-g++ -c file.cpp -o file.o
mingw-g++ -shared -Wl,--out-implib,libfile.a -o file.dll file.o
No more, no less.
And, documentation is always lovely to have: http://www.mingw.org/wiki/sampleDLL

Resources