Undefined symbol in static lib linked into dynamic library - c++

here is my issue:
At runtime my program which load shared library fail to load one, it says:
libCommunicationModule.so: undefined symbol __builtin_delete
the context:
compiler: gcc 3.4
Linux Debian 4.0 (old stuff ....)
I have a static library: libtgi_cppd.a , I don't have the source of this library.
This lib is linked into the shared library libCommunicationModule.so with these options
-Wl,-whole-archive -ltgi_cppd
I enabled -y option on __builtin_delete to check:
libtgi_cppd.a(ClientAPI_cpp.o): reference to __builtin_delete
libtgi_cppd.a(ClientInterface.o): reference to __builtin_delete
libtgi_cppd.a(ClientAPI_cpp.o): reference to __builtin_delete
I try to add to link command -lstdc++ -lgcc before and after -whole-archive, no change.
$ nm libCommunicationModule.so | grep __builtin
result is always like this:
U __builtin_delete
U __builtin_new
U __builtin_vec_new
What can I do to solve this issue?
Thank you
Full command as requiered:
g++ -Wl,-y -Wl,__builtin_delete -Wl,--trace -Wl,-rpath,/usr/local/qt/lib -shared
-Wl,-soname,libCommunicationModule-x11-Debug.so.6 -Wl,-rpath,/home/sncf/AGC_IHM/AGC/Tms/Gui/Components/CommunicationModule/x11/Debug
-o libCommunicationModule-x11-Debug.so.6.0.1 x11/Debug/Obj/CommunicationModule-Build.o x11/Debug/Obj/CommunicationModuleFilesAutoGen.o x11/Debug/Obj/CommunicationModuleParamsAutoGen.o
x11/Debug/Obj/CommunicationModule.o
x11/Debug/Obj/CommunicationModuleAutoGen.o
x11/Debug/Obj/CommDebugDlg.o
x11/Debug/Obj/moc_CommunicationModule.o x11/Debug/Obj/moc_CommDebugDlg.o
-L/usr/local/qt/lib
-L/usr/X11R6/lib -lBuildInformations-x11-Debug
-lBagsLib-x11-Debug -lConfigParamsLib-x11-Debug
-lIniLib-x11-Debug -lModuleHandling-x11-Debug
-lGenericRuntimeInfoLib-x11-Debug
-lDebugLib-x11-Debug -lTCNLib-x11-Debug
-lGUITools-x11-Debug -lQtEventsLib-x11-Debug
-lPackUnpack-x11-Debug -L/home/sncf/AGC_IHM/AGC/Tms/Gui/ProjectLib/x11
-L/home/sncf/AGC_IHM/AGC/Tms/Gui/Components/AGCTCNClientAPI/2004.09.21/posix_linux_i586/lib
-lqt-mt -lXext -lX11 -lm -lpthread -Wl,-whole-archive -ltgi_cppd -lstdc++ -lgcc

You linked against a library which was compiled/linked by another compiler/linker version. What you need is to link against a library which was compiled and linked by the same compiler/linker as used by yourself, or you have to make sure, that the libraries are at least binary compatible.

Execute command ldd and it will list out all shared libraries using by your program.
Check the environment variable LIBPATH /LD_PATH in your execution environment. And make sure all those libraries are present in that path
Make sure all library files have sufficient permission

Related

The correct way to use the GNU linker

I am trying to use a couple of libraries, libglfw3-dev and libglew-dev, on an ubuntu environment but have been unable to get the linker to perform its intended purpose. I would normally use a makefile but for the purpose of debugging I have just used g++ on the CLI.
g++ -I-Iinclude -I/usr/include/GL -I/usr/include/GLFW -L/usr/lib/x86_64-linux-gnu/
I understand that I need to specify the libraries themselves with the -l flag but get an error of the form
/usr/bin/ld: cannot find -llibglfw
Here is some information about the locations of the packages (omitting irrelevancies)
root#Jake-Faptop:/usr/include/GLFW# dpkg -L libglfw3-dev
/usr/include/GLFW/glfw3.h
/usr/include/GLFW/glfw3native.h
/usr/lib/x86_64-linux-gnu/libglfw.so
root#Jake-Faptop:/usr/include/GLFW# dpkg -L libglew-dev
/usr/include/GL/glew.h
/usr/include/GL/glxew.h
/usr/include/GL/wglew.h
/usr/lib/x86_64-linux-gnu/libGLEW.so
The names of the shared libraries have been a matter of great confusion to me as it turns out they are named /usr/lib/x86_64-linux-gnu/libGLEW.so.2.1.0 and /usr/lib/x86_64-linux-gnu/libglfw.so.3.3
---EDIT---
In light of the advice given to omit prefixes and suffixes on the library names I am still getting linker errors on the following input
g++ -Iinclude -I/usr/include/GL -I/usr/include/GLFW -L/usr/lib/x86_64-linux-gnu/ -lGLEW -lglfw src/main.cpp -o build/main
->
/usr/bin/ld: main.cpp:(.text+0x3b): undefined reference to glfwTerminate'
/usr/bin/ld: main.cpp:(.text+0x54): undefined reference to `glfwWindowHint'
/usr/bin/ld: main.cpp:(.text+0x63): undefined reference to `glfwWindowHint'
/usr/bin/ld: main.cpp:(.text+0x72): undefined reference to glfwWindowHint'
Confused.com...
Remove lib at the beginning of the names. E.g. the library's name is
libGLEW.so.2.1.0
Link it with
-lGLEW
This will link to libxGLEW.so which usually is a symlink to a versioned library like libGLEW.so.2.1.0.
-llibrary
-l library
Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.)
The -l option is passed directly to the linker by GCC. Refer to your linker documentation for exact details. The general description below applies to the GNU linker.
The linker searches a standard list of directories for the library. The directories searched include several standard system directories plus any that you specify with -L.
Static libraries are archives of object files, and have file names like liblibrary.a. Some targets also support shared libraries, which typically have names like liblibrary.so. If both static and shared libraries are found, the linker gives preference to linking with the shared library unless the -static option is used.
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded.
https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html

g++ not find .so files

I am trying to generate a c++ library using the g++ compiler. My library has another C library as dependency and I have compiled it in order to obtain the .so files.
I have the following structure:
src:
include/linux:
libcustom.a
libcustom.la
libcustom.so
libcustom.so.0
libcustom.so.0.0.0
Now, when I have all the .o files of my cpp classes, and I want to link the library, I execute the following command:
g++ -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o mylibrary.so File1.o File2.o File3.o -L./include/linux -lc++ -lutil -lm -lcustom -Wl,-rpath='$ORIGIN/include/linux' -L/usr/lib/R/lib -lR
But it throws me the error:
libcustom.so.0: cannot open shared object file: No such file or directory
I am executing the command from the src directory.
I know it could be fixed editing the LD_LIBRARY_PATH, but the idea it is someone can use my library without the need of configuring anything, so I am trying to do that with the c++'s -rpath flag.
Any idea how can I fix it, or the reason for the error?
The error message you got seems to come from the run-time loader ld.so instead of the linker ld (I know the names are confusing). You have to distinguish between finding so's at link-time and at run-time. The -L flag you give at link-time has nothing to do with localizing the library at run-time.
Your rpath=./include/linux value is not correct, because dot is not recognized by the ld as relative path. Relative searching path should be given like
-Wl,-rpath='$ORIGIN/include/linux'
where the $ORIGIN represents the folder where your executable (not mylibrary.so) locates. Make sure to use single quote and not double quote because the string $ORIGIN should be passed to the linker literally and hard coded into the executable file.
More details goes
how to link to shared lib from shared lib with relative path
ld: Using -rpath,$ORIGIN inside a shared library (recursive)

Static and Dynamic/Shared Linking with MinGW

I want to start with a simple linking usage to explain my problem. Lets assume that there is a library z which could be compiled to shared library libz.dll(D:/libs/z/shared/libz.dll) or to static library libz.a (D:/libs/z/static/libz.a).
Let I want to link against it, then I do this:
gcc -o main.exe main.o -LD:/libs/z/static -lz
According to this documentation, gcc would search for libz.a, which is
archive files whose members are object files
I also can do the following:
gcc -o main.exe main.o -LD:/libs/z/shared -lz
It is not mentioned in the documentation above that -l flag will search for lib<name>.so.
What will happen if I libz.a and libz.dll will be in the same directory? How the library will be linked with a program? Why I need the flags -Wl,-Bstatic and -Wl,-Bdynamic if -l searches both for shared and static libraries?
Why some developers provide .a files with .dll files for the same modules, if I compile a shared library distribution?
For example, Qt provides .dll files in bin directory with .a files in lib directory. Is it the same library, but built like shared and static, respectively? Or .a files are some kind of dummy libraries which provide linking with shared libraries, where there are real library implementations?
Another example is OpenGL library on Windows. Why every compiler must provide the static OpenGL lib like libopengl32.a in MingW?
What are files with .dll.a and .la extensions used for?
P.S. There are a lot of questions here, but I think each one depends on the previous one and there is no need to split them into several questions.
Please, have a look at ld and WIN32 (cygwin/mingw). Especially, the direct linking to a dll section for more information on the behavior of -l flag on Windows ports of LD. Extract:
For instance, when ld is called with the argument -lxxx it will attempt to find, in the first directory of its search path,
libxxx.dll.a
xxx.dll.a
libxxx.a
cygxxx.dll (*)
libxxx.dll
xxx.dll
before moving on to the next directory in the search path.
(*) Actually, this is not cygxxx.dll but in fact is <prefix>xxx.dll, where <prefix> is set by the ld option -dll-search-prefix=<prefix>. In the case of cygwin, the standard gcc spec file includes -dll-search-prefix=cyg, so in effect we actually search for cygxxx.dll.
NOTE: If you have ever built Boost with MinGW, you probably recall that the naming of Boost libraries exactly obeys the pattern described in the link above.
In the past there were issues in MinGW with direct linking to *.dll, so it was advised to create a static library lib*.a with exported symbols from *.dll and link against it instead. The link to this MinGW wiki page is now dead, so I assume that it should be fine to link directly against *.dll now. Furthermore, I did it myself several times with the latest MinGW-w64 distribution, and had no issues, yet.
You need link flags -Wl,-Bstatic and -Wl,-Bdynamic because sometimes you want to force static linking, for example, when the dynamic library with the same name is also present in a search path:
gcc object1.o object2.o -lMyLib2 -Wl,-Bstatic -lMyLib1 -Wl,-Bdynamic -o output
The above snippet guarantees that the default linking priority of -l flag is overridden for MyLib1, i.e. even if MyLib1.dll is present in the search path, LD will choose libMyLib1.a to link against. Notice that for MyLib2 LD will again prefer the dynamic version.
NOTE: If MyLib2 depends on MyLib1, then MyLib1 is dynamically linked too, regardless of -Wl,-Bstatic (i.e. it is ignored in this case). To prevent this you would have to link MyLib2 statically too.

How to compile cpp source to full static binary and except for: libc, libpthread, libdl, libstdc++, and libm

I want to compile a binary linux to full static, But I always fail with this configuration:
CFLAGS="--static" CPPFLAGS="-I/home/alan/arm/arm-none-linux-gnueabi/libc/usr/include" LDFLAGS="-L/home/alan/arm/arm-none-linux-gnueabi/libc//usr/lib" LIBS="-lcrypt -ldl -lpthread -lm -lc -lstdc++" CC=arm-none-linux-gnueabi-gcc AR=arm-none-linux-gnueabi-ar CXX=arm-none-linux-gnueabi-g++ ./configure --host=arm-none-linux-gnueabi target=arm-none-linux-gnueabi --prefix=/home/alan/armbin/test --without-pcre --without-zlib --without-bzip2 --without-openssl --disable-ipv6 --enable-static
But I always get warning dlopen, gethostbyname, etc. If I not except libc, libm, etc to shared. I get warning approximately as below:
warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
Thank you very much.
Use -pthread instead of -lpthread.
Source.
Your link command should look like this:
g++ objectFiles $(CFLAGS) -o executable -Wl,-Bstatic -L/path/to/static/lib1/ -ls1 -L/path/to/static/lib2 -ls2 -Wl,-Bdynamic
You only have to explicitly call the static libraries libs1.a, libs2.a . The shared system libraries you are referring to (libc.so, libpthreads.so, libm.so, libdl.so, libstdc++.so etc.) should be found implicitly by your linker and are affected by -Wl, -Bdynamic. You don't have to pass them explicitly. Try and do a
"ldd executable" to see the dynamic dependencies.

how to do static linking of libwinpthread-1.dll in mingw?

I use mingw from here: http://sourceforge.net/projects/mingwbuilds/files/host-windows/releases/4.7.2/32-bit/threads-posix/sjlj/x32-4.7.2-release-posix-sjlj-rev2.7z/download
And I've sucessfully managed to link statically libstdc++-6.dll and libgcc_s_sjlj-1.dll by using -static-libgcc -static-libstdc++ parameters, but I cannot find a command for doing the same with libwinpthread-1.dll.
If your toolchain includes the static winpthreads, adding the option
-static
Will pull in static versions of all libraries it can.
Alternatively, you can remove libwinpthread.dll.a and the DLL itself from the toolchain directories. This might mess up programs linking with libstdc++ and libgcc DLLs though, so be careful.
A third option is to use -Wl,-Bdynamic and -Wl,-Bstatic to select which version you want linked in (which is what -static internally does when ld is called). An example:
gcc -o someexec someobject.o -Wl,-Bdynamic -lsomelibIwantshared -Wl,-Bstatic -lsomelibIwantstatic
If you run your link command with -v added, you should see these options appearing in the ld/collect2 invocation when you use -static-libgcc and -static-libstdc++.
Try this:
-static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic
Notice the -lstdc++ before -lpthread. It worked for me.
Make sure to add this to the very end of your g++ command line.
You should probably check command line options documentation for GCC.
These's no '-static-something' command, only standard libraries (libgcc and libstdc++) can be set to static linking with one command. For other libraries, you first switch to static linking with "-static" and then list the libraries to include with separate commands, ie "-lpthread".
To statically link winpthread even if threading isn't used in the program, pass the -Bstatic and --whole-archive parameters to the linker:
g++ -o hello.exe hello.cpp -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive
Note the following:
The "whole archive" option should be disabled immediately afterwards.
You don't need to do this hack if your program actually uses symbols from the library (i.e. you use <thread> from C++11), in which case the library won't get dropped when you statically link it.
This hack is intended for MinGW-w64, to fix the libwinpthread-1.dll dependencies.
For anyone working in CMake, this solution is readily implemented in your CMakeLists.txt file as follows...
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static")
Apparently, CMake does some weird stuff with how the -Wl compiler flags are handled, making the -Wl,-Bstatic -lstdc++ -lwinpthread -Wl,-Bdynamic solution not work, with only two other options seemingly left: the bad compiler flag -static and the ugly compiler flag -Wl,--whole-archive.
Meanwhile, the good option that actually works in CMake, yet seems rather undocumented, is to directly use the linker flags. Hence, in CMake, this seems to be the best way to statically link to all the mingw-w64 C++ dependencies:
target_link_libraries (MyVeryAwesomeApp -static gcc stdc++ winpthread -dynamic)
It should be noted that even if there isn't a library explicitly following -dynamic, it should still be applied in order to ensure that the standard, implicitly linked libraries get linked correctly.
I circumvented this problem by using win32 variant of the mingw toolchain instead of the posix variant. With the win32 variant, -static-libgcc -static-libstdc++ is sufficient for an independent build.
If you are using toolchains from MSys2 (tested with gcc version 12) ,the only way to use winpthread statically is standard -static (forces all library to be static) or simply delete/rename the libwinpthread.dll.a && libpthread.dll.a imp libs.
Other methods like "Bstatic", "-l:libwinpthread.a" will no longer work (due to dependency hell, especially in CMake). The one with whole archive still works but it overrides the program properties.
You may also want static link libgcc and libstdc++ if the dependency comes from them.
Just link with -l:libwinpthread.a
Just add -static to your CFLAGS.
For example: ./configure CFLAGS="-static".
This will link all static libraries to your executable file.