Linking problem with an Shared Object in 32-bits - c++

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++)

Related

MSYS2 and libcurl, which libs to link?

I am having some big headaches linking statically libcurl in MSYS2 mingw.
I installed libcurl and all the listed dependencies from here
https://packages.msys2.org/package/mingw-w64-x86_64-curl
Since I am using CodeBlocks as IDE I need to supply a whole list of libs in form of lib#?.a, please keep in mind that I know nothing of Linux world and gcc tools and command line, otherwise I wouldn't be using an IDE!
Also I am not skilled enough to compile lib packages. I just need to write some portable code to do a https post request in cpp, so I need libcurl.
Can you tell me a complete list of all the needed libs to link against ? I tried all my best but I keep getting an infinity of unresolved symbols
UPDATE
After having checked what the package config for libcurl says, I have installed all the missing libs and used the following command line:
g++.exe -o MyProg.exe obj\Release\main.o -static-libstdc++ -static-libgcc -static -m64 -lcurl -lnghttp2 -lidn2 -lssh2 -lpsl -ladvapi32 -lcrypt32 -lssl -lcrypto -lssl -lcrypto -lgdi32 -lwldap32 -lzstd -lbrotlidec -lz -lws2_32 -s
Despite that I am still getting tons of undefined references:
d:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: d:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/lib/../lib\libcurl.a(gsasl.o):(.text+0x14): undefined reference to `gsasl_init'
[plus many other 'gsasl...' referrences]
d:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: d:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../lib\libbrotlidec.a(decode.c.o):(.text+0x2d28): undefined reference to `BrotliTransformDictionaryWord'
[plus many other 'brotli...' references]
pkg-config will tell you the necessary flags. Install it from the package mingw-w64-x86_64-pkg-config.
Run it as pkg-config --libs --static libcurl.
Copy the output into "linker flags -> other". For me the output is -L/mingw64/lib -lcurl -lnghttp2 -lidn2 -lssh2 -lpsl -ladvapi32 -lcrypt32 -lssl -lcrypto -lssl -lcrypto -lgdi32 -lwldap32 -lzstd -lbrotlidec -lz -lws2_32. Don't forget to add the --static flag, if you're not already doing so.

Create shared .so library that has all it's dependencies statically linked

I am trying to build my .so library with all dependencies (mostly boost) statically linked. Currently, I can build statically linked static library and dynamically linked shared library:
I would like to add other dependencies to .so library so that it has 20MB and does not require user to install anything. Note that this is just a temporary solution before we upgrade to new Boost 1.55 on production servers.
I define libraries like this in Makefile ($ARCH can be either 32 or 64):
## Multi-arch library locations
LIB32=/usr/lib/i386-linux-gnu/
LIB64=/usr/lib/x86_64-linux-gnu/
LIBDIR:=$(LIB$(ARCH))
##Library directory
LIB=-L $(LIBDIR)
## DYNAMIC
LIBS=-lboost_serialization -lboost_thread -lboost_date_time -lboost_signals -lboost_iostreams -lboost_system -llog4cplus -lcrypto -lssl -lm
## STATIC
SLIBS=$(LIBDIR)libboost_serialization.a $(LIBDIR)libboost_thread.a $(LIBDIR)libboost_date_time.a $(LIBDIR)libboost_signals.a $(LIBDIR)libboost_iostreams.a $(LIBDIR)libboost_system.a $(LIBDIR)liblog4cplus.a
Shared lib with dynamic linking:
This is my shared lib GCC command:
Makefile:
$(CXX) $(CFLAGS) $(INCLUDE) $(LIB) $(LIBS) -shared -Wl,-soname,$(SHARED_LIB_VERSION) -o $(NEW_LIB_DIR)${SHARED_LIB_VERSION} $(OBJ_CPP_DYN) $(OBJ_C_DYN)
Changes into:
g++ -m64 -Wl,--trace -D NDEBUG -I /usr/include/ -I /usr/local/include -L /usr/lib/x86_64-linux-gnu/ -shared -lboost_serialization -lboost_thread -lboost_date_time -lboost_signals -lboost_iostreams -lboost_system -llog4cplus -lcrypto -lssl -lm -Wl,-soname,libLIBNAMEx64.so -o ../Release/libLIBNAMELIBNAMEx64.so ... and much more .o files ...
Linker says:
-lboost_serialization (/usr/lib/x86_64-linux-gnu//libboost_serialization.so)
-lboost_thread (/usr/lib/x86_64-linux-gnu//libboost_thread.so)
-lboost_date_time (/usr/lib/x86_64-linux-gnu//libboost_date_time.so)
-lboost_signals (/usr/lib/x86_64-linux-gnu//libboost_signals.so)
-lboost_iostreams (/usr/lib/x86_64-linux-gnu//libboost_iostreams.so)
-lboost_system (/usr/lib/x86_64-linux-gnu//libboost_system.so)
-llog4cplus (/usr/lib/x86_64-linux-gnu//liblog4cplus.so)
-lcrypto (/usr/lib/x86_64-linux-gnu//libcrypto.so)
-lssl (/usr/lib/x86_64-linux-gnu//libssl.so)
And it works.
Shared lib with static linking:
I thought I can just replace -shared with -static:
g++ -m64 -Wl,--trace -D NDEBUG -I /usr/include/ -I /usr/local/include -L /usr/lib/x86_64-linux-gnu/ -static -lboost_serialization -lboost_thread -lboost_date_time -lboost_signals -lboost_iostreams -lboost_system -llog4cplus -lcrypto -lssl -lm -Wl,-soname,libLIBNAMEx64_static_link.so -o ../Release/libLIBNAMEx64_static_link.so ... and much more .o files ...
But I get undefined reference errors everywhere.
So where do I configure how are dependencies linked with my binary? How can I achieve my goal?
More things I tried (edit)
-Wl,--library:
I also tried passing libraries directly to linker in a very assertive manner:
-Wl,--library=:/usr/lib/x86_64-linux-gnu/libboost_serialization.a
And without : (which prevents searching for .a):
-Wl,--library=/usr/lib/x86_64-linux-gnu/libboost_serialization.a
But I get the error:
/usr/bin/ld: cannot find -l/usr/lib/x86_64-linux-gnu/libboost_serialization.a
Of course, the file exists at that path.
Pass just library names:
Of course, here it's not even interpreted as linking command:
g++: error: libboost_serialization.a: No such file or directory
Interesting is that if I pass full path instead (/usr/lib/x86_64-linux-gnu/libboost_iostreams.a), GCC doubles it:
g++: error: /usr/lib/x86_64-linux-gnu//usr/lib/x86_64-linux-gnu/libboost_signals.a: No such file or directory
Use command man ld, I got this information:
-static
Do not link against shared libraries. It affects library searching for -l options which follow it. This option also implies --unresolved-symbols=report-all. This option can be used with -shared. Doing so means that a shared library is being created but that all of the library's external references must be resolved by pulling in entries from static libraries.
This option is exactly what you want: create a shared library with all dependencies (mostly boost) statically linked.
-l parameter is used to specify the library name, so you should use boost_serialization instead of /path/libboost_serialization.a:
-larchive
If you specify -lcommon, then ld will search its path-list for occurrences of "libcommon.a" for every common specified.
You can use -L parameter many times to specify the library paths when ld try to search static libraries:
-Lsearchdir
For example:
-L/usr/lib/x86_64-linux-gnu/
You could try -Wl,--whole-archive ${your library} -Wl,--no-whole-archive.

Mixing static and dynamic libraries in fedora

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...

g++ linking static and non-static libraries at the same time

I have a makefile project in which I include a few different libraries. One of them is the boost library which I statically link in order to make my program portable. This is how my makefile command looks like:
g++ -O0 -g test.cpp testObject.o -pthread -I/home/user/devel/lmx-sdk-4.7.1/include/ -L/home/user/devel/lmx-sdk-4.7.1/linux_x64 -llmxclient -lrt -ldl -lboost_filesystem -lboost_system -static -static-libgcc -o $#
I have also linked lmx-sdk library to my project in order to use the licensing functionality; however, it seems to be that lmx-sdk doesn't seem to like static link as it gives an error "Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking".
How can I make it possible to link some libraries statically and the other ones dynamically ?
Thanks in advance
P.S. I have checked some of similar topics and tried a few methods which didn't work out for me.
Using -Wl,-Bdynamic and -Wl,-Bstatic instead of just using -Bdynamic and -Bstatic solved the problem.
The full link line looks like this now:
g++ -O0 -g test.cpp testObject.o -pthread -Bdynamic -I/home/user/devel/lmx-sdk-4.7.1/include/ -L/home/user/devel/lmx-sdk-4.7.1/linux_x64 -llmxclient -lrt -ldl -Wl,-Bstatic -lboost_filesystem -lboost_system -o $#
You can use -Bstatic to statically link what comes after it, then -Bdynamic to do the opposite. As many times as you need on the command line.

Static linking failed although the name exists

I'm trying to link to a static library, libcovis.a. Everything looks fine but I still have
undefined reference to `CoViG_PublicDemo::MoInS::reset()'
I checked that the name exists in the library
$nm libcovis.a | grep reset
...
_ZN16CoViG_PublicDemo5MoInS5resetEv
...
I'm using linking arguments -L/path/to/libcovis.a -lcovis
What am I doing wrong ?
Edit:
The error might be something else, if do
gcc main.cpp -I/usr/include/opencv -I/usr/include/cairo -I../../Source -o slam -rdynamic -lGLU -lGL -lSM -lICE -lX11 -lXext -lglut -lXi -lxml2 -lboost_filesystem-mt -llapack -lblas -lcv -lcxcore -lcvaux -lhighgui -lcairo ../../Source/libcovis.a ../../Source/contrib/gnuplot_i/libcovis_contrib_gnuplot_i.a -lgl2ps
It works !
But when I'm in KDevelop using cmake, I doesn't work anymore. I use
CMAKE_EXE_LINKER_FLAGS:STRING=-rdynamic -lGLU -lGL -lSM -lICE -lX11 -lXext -lglut -lXi -lxml2 -lboost_filesystem-mt -llapack -lblas -lcv -lcxcore -lcvaux -lhighgui -lcairo /usr/local/src/CoViS-0.0.0-1/Source/libcovis.a /usr/local/src/CoViS-0.0.0-1/Source/contrib/gnuplot_i/libcovis_contrib_gnuplot_i.a -lgl2ps
CMAKE_CXX_FLAGS:STRING=-I/usr/local/src/CoViS-0.0.0-1/Source -I/usr/include/opencv -I/usr/include/cairo
The only difference I can see is that the paths are absolute and not relative, but if he couldn't find the libs, he would say it...
There are two different issues there, the first of which is the simplest, you have used the wrong compiler options. The -L option tells the linker to also look in the directory when looking for a library. The -l tells it to link the specific library. To link you would then use:
g++ -o test test.o -L/path/to -lcovis
or
g++ -o test test.o -l/path/to/libcovis.a
To force static linking if the same library is present as a dynamic library in the same directory.
The second potential issue is that the order of static libraries in the linker command line does matter, so that might also be an issue if there is a dependency on different static libs.
g++ -o test tests.o -ldependent -lprovider
The linker will process the libraries in order as they are in the command line, and from each static lib it will only pull those symbols that are required (with as much information as the linker has at that time). In the command line above, the linker will extract from dependent the symbols it needs for test.o, and that might in turn add new undefined symbols to the program (the dependencies of dependent). When it processes provider it will fill in those symbols. If the order was reversed in the command line, the symbols that are required by dependent but not by test.o would not be added to the executable, as the linker does not know that those symbols will be needed when processing provider.
Should the arguments be like -L/path/to/ -lcovis?
Besides, object files should be placed before libs, for example
g++ obj1.o obj2.o -L/path/to/ -lcovis.
If you see the link succeeding in one context but not another, I suspect the problem may be caused by the order in which the link operation is executed as the linker will discard symbols in a library if they're not needed at the point in which the library is referenced.
Here is a link explaining: http://www.network-theory.co.uk/docs/gccintro/gccintro_18.html
I've run into similar situations in the past the linking order was found to be the cause of the problem.