Mixing static and dynamic libraries in fedora - c++

There are already some answers how to mix dynamic and static linking of binaries.
Like in the anwers I read so far I compile like this:
gcc main.cpp -static-libstdc++ -static-libgcc -Wl,-Bstatic -lm -lstdc++ -lpthread -lrt -lc -Wl,-Bdynamic -lmyshared_lib -L. libx.a liby.a
But then I get an error:
/usr/lib/gcc/i686-redhat-linux/4.7.2/../../../libpthread.a(libpthread.o): In function `sem_open':
(.text+0x6407): warning: the use of `mktemp' is dangerous, better use `mkstemp'
/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib/gcc/i686-redhat-linux/4.7.2/../../../libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
collect2: error: ld returned 1 exit status
The third-party lib is itself dependend on libc.so.6, so I guess this is now in conflict with my static linked libc.
If I compile with the -fPIE and -pie parameters like below - the application segfaults immediately:
gcc main.cpp -fPIE -static-libstdc++ -static-libgcc -Wl,-Bstatic -lm -lstdc++ -lpthread -lrt -lc -Wl,-Bdynamic -lmyshared_lib -L. libx.a liby.a -Wl,-pie
Does it even work to compile nearly completely static and just link one shared object additionally?
I try to do this because I want to get one specific 32bit binary to run on a x64 system using a 32bit third party shared object...

Related

Why would I need to list -ldl before a library that calls dlopen/dlclose/dlerror when linking

I am building an executable (foo.exe let's call it) on RHEL with gcc 6.2. It links against a few third-party libraries, libzzdesign.so, libyydesign.so. Yydesign uses dlopen/dlclose/dlerror. I would expect this command-line to work:
g++ -Wall -fcheck-new -fno-strict-aliasing -msse2 -fno-omit-frame-pointer -pthread -O3 -Wl,--export-dynamic -o foo.exe foo.o -L/path/to/zzdesign -Wl,-rpath=/path/to/zzdesign -lzzdesign -L/path/to/yydesign -Wl,-rpath=/path/to/yydesign -lyydesign -ldl
(I'm listing all the options used in case it matters)
It produces the errors,
/path/to/yydesign/libyydesign.so: undefined reference to 'dlclose'
/path/to/yydesign/libyydesign.so: undefined reference to 'dlerror'
If I change the command line to put -ldl before -lyydesign:
g++ -Wall -fcheck-new -fno-strict-aliasing -msse2 -fno-omit-frame-pointer -pthread -O3 -Wl,--export-dynamic -o foo.exe foo.o -L/path/to/zzdesign -Wl,-rpath=/path/to/zzdesign -lzzdesign -L/path/to/yydesign -Wl,-rpath=/path/to/yydesign -ldl -lyydesign
... it works without error.
This is the opposite of everything I thought I knew about order of libraries on the command line when linking.
Why does -ldl have to come before -lyydesign?
Other than dumb luck to stumble across this solution, how could I troubleshoot the original error to understand what's going on?
And since changing the build system to move -ldl first in all the places it's needed is kind of a pain, is there a way I can avoid having to put -ldl first?
Order of libs for LD does matter. Lib yydesign use dlclose and dlerror that's why lib dl need to be passed before yydesign.

Linking problem with an Shared Object in 32-bits

I am trying to migrate and old version of an software and I modernized the code with CLang-Tidy assistance and I am having an strange linking problem that is saying this:
/usr/bin/ld: /usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/32/crtbeginT.o:
direct GOT relocation R_386_GOT32X against
`_ITM_deregisterTMCloneTable' without base register can not be used
when making a shared object
I tried to isolate the problem by commenting some .cpp files in CMakeLists.txt but I still can't determine what is wrong.
Here is my CMakeLists.txt section
add_library(client SHARED
network/client/mistery.cpp
network/client/mclient.cpp
network/client/ellect.cpp
network/client/proctcppacket.cpp
network/client/ping.cpp
network/client/signals.cpp
network/client/remotecontrol.cpp
network/client/data.cpp
network/client/sensor.cpp
network/client/events.cpp
network/client/test.cpp
network/client/misteryThread.cpp
network/client/libNetwork.cpp
)
target_link_libraries(client -lssl -lcrypto -ggdb -lxml2 -lz -ldl -pthread -lstdc++ -static)
set_target_properties(client PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
My shared object must be 32-bits mode.
I noticed that I must compile and link without the -static option in the target_link_libraries. Since I am build a shared object I cannot use this option.
Therefore, the correct implementation of the target_link_libraries is:
target_link_libraries(client -lssl -lcrypto -ggdb -lxml2 -lz -ldl -pthread -lstdc++)

Static compilation fails: dynamic STT_GNU_IFUNC symbol `tan' .. can not be used when making an executable

I'm trying to compile expect statically on my PC, but I seem to run into some strange compiling errors.
I was able to compile tcl statically like this:
./configure --disable-load --disable-shared
Then add to the makefile CFLAGS variable -static keyword. Now after compiling I seem to have a static tcl, and a library:
-rw-rw-r-- 1 jlumme jlumme 3284332 loka 2 11:27 libtcl8.6.a
After this, I configure expect:
./configure --with-tclconfig=${TCL_DIR}/unix --disable-shared --disable-load
And then compile (first dynamic):
$ gcc -pipe -O2 -fomit-frame-pointer -Wall -Wl,--export-dynamic -o expect exp_main_exp.o -L/home/jlumme/Downloads/compile/expect5.45 -lexpect5.45 -L/home/jlumme/Downloads/compile/tcl8.6.4/unix -ltcl8.6 -lieee -lm -lpthread -lz
The result looks ok:
$ file expect
expect: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=a613c260944117f43bcaebc43c51c421dce273a7, not stripped
But now if I want to attempt a static compilation, I get errors that I dont understand:
gcc -pipe -O2 -fomit-frame-pointer -Wall -Wl,--export-dynamic -o expect exp_main_exp.o -L/home/jlumme/Downloads/compile/expect5.45 -lexpect5.45 -L/home/jlumme/Downloads/compile/tcl8.6.4/unix -ltcl8.6 -lieee -lm -lpthread -lz -static
/home/jlumme/Downloads/compile/tcl8.6.4/unix/libtcl8.6.a(tclUnixCompat.o): In function `TclpGetGrGid':
tclUnixCompat.c:(.text+0x41c): warning: Using 'getgrgid_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/home/jlumme/Downloads/compile/tcl8.6.4/unix/libtcl8.6.a(tclUnixCompat.o): In function `TclpGetGrNam':
tclUnixCompat.c:(.text+0x31c): warning: Using 'getgrnam_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
<HANDFUL OF WARNINGS REMOVED>
/usr/bin/ld: dynamic STT_GNU_IFUNC symbol `tan' with pointer equality in `/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/libm.a(s_tan.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
collect2: error: ld returned 1 exit status
I dont really understand what this final linking problem is, can someone help ?

Link error with my own C++ library

This is my first time trying to make a simple library. I worked in Ubuntu 12.04 with g++ 4.6.3. Here is the problem:
[[mylib.cpp]]
#include<sqlite3.h>
void Mylib::blahblah() {...}
void Mylib::evenmoreblah() {...}
...
[[mylib.h]]
#include <...>
class Mylib {
...
};
Then I made the lib by:
gcc -c -Wall -fpic mylib.cpp
gcc -shared -o libmylib.so mylib.o
I used the library in a single test.cpp which contains only the main(). I put libmylib.so in ./libdir, and compiled by using:
g++ -g test.cpp -o test -lpthread -L/usr/local/lib -lsqlite3 -L./libdir -lmylib
The error I got:
./libdir/libmylib.so: undefined reference to `sqlite3_close'
./libdir/libmylib.so: undefined reference to `sqlite3_exec'
./libdir/libmylib.so: undefined reference to `sqlite3_free'
./libdir/libmylib.so: undefined reference to `sqlite3_open'
You could link -lsqlite3 into your shared library with
gcc -shared mylib.o -o libmylib.so -lsqlite3
If you do that, you don't need to explicitly link -lsqlite3 to your program, but that won't harm.
and the order of linking arguments for your program is important:
g++ -Wall -g test.cpp -o mytest \
-L./libdir -lmylib -L/usr/local/lib -lsqlite3 -lpthread
it should go from higher-level libraries to lower-level (i.e. system) ones. And don't forget -Wall to get almost all warnings from the compiler, which is very useful.
Read the Program Library HowTo.
PS. Don't call your program test which is a shell builtin (and the standard /usr/bin/test). Use some other name.
If your library make references to sqlite3, you should link sqlite after linking your library :
g++ -g test.cpp -o test -lpthread -L/usr/local/lib -L./libdir -lmylib -lsqlite3
Otherwise ld won't find anything useful in libsqlite3 before linking your library and won't be able to find the requested symbols after that.
Since your library uses sqlite3, you need to add that AFTER your own library in the linker command. I think you could add it to the linking of your shared library too, but not certain.
The linker resolves libraries and their references in the order you list them, so the order is important.

GCC linker error while compiling a static library

I want to create a static library of all my files so that i could give my mylib.a file to others to execute on their system. I use opencv library in my code. I used the following command to compile my code.
g++ index.cpp -o display1 -Wl,-Bdynamic pkg-config --cflags --libs opencv -lglut -lGL -lGLU -Wl,-Bstatic mylib.a
But it is giving the following error.
/usr/bin/ld: cannot find -lgcc_s
collect2: ld returned 1 exit status
I believe the Kerrek SB is right in the comment. The command should be
g++ index.cpp -o display1 mylib.a $(pkg-config --cflags --libs opencv) -lglut -lGL -lGLU
Explanation:
The -Wl,-Bdynamic and -Wl,-Bstatic flags are useless. The linker automatically picks static or dynamic library depending on what it finds. If you give it path to a library (as you do with mylib.a) it can't choose and will link the library you provided. If you give it an -lX flag, it will look for libX.so or libX.a and link whichever it finds, but most Linux installations won't have static variants of system libraries, so there is nothing to choose from either.
It's worse, the -Wl,-Bdynamic and -Wl,-Bstatic are wrong. -Wl,-Bstatic prohibits linking of shared libraries. That has the side-effect of selecting static libgcc, which implicitly comes last on the linker command line. And you don't seem to have that installed. Most Linux systems don't.
Each object must be listed on the command-line before the libraries it refers to. I would expect mylib.a contains functions that need opencv or opengl, so it must be listed before those -l flags.