How to link libgomp statically when linking other libraries dynamically? - c++

I am trying to build an image processing program written in C++ that depends on the following libraries using MinGW + MSYS (with GCC4.8.1) that I downloaded from www.mingw.org/ on a Windows 8 64bit computer
LibJPEG
BLAS and LAPACK
Armadillo
OpenMP
I have successfully compiled all the source code files (with -fopenmp flag of course), then I linked with the following statement:
g++ -o ./build/rspfitter {a list of .o files}
-L{paths to libraries} -ljpeg -lopenblas -lgomp -lpthread
The executable was correctly produced. However, it asks for the following dlls:
libgomp-1.dll
libpthread-2.dll
pthreadGC2.dll
I think it might a better idea to link libgomp and libpthread statically, so that I can minimize the number of dlls I need to deploy my program with (the above three dlls are not the only ones the program depends on). So I tried to link only libgomp and libpthread statically with the following command:
g++ -o ./build/rspfitter {a list of .o files}
-L{paths to libraries} -ljpeg -lopenblas -Wl,-static -lgomp -lpthread
But this time it fails with the following error message:
d:/mingw/bin/../lib/gcc/mingw32/4.8.1\libgomp.a(env.o):(.text.startup+0xbfe):
undefined reference to `_imp__pthread_attr_init'
d:/mingw/bin/../lib/gcc/mingw32/4.8.1\libgomp.a(env.o):(.text.startup+0xc13):
undefined reference to `_imp__pthread_attr_setdetachstate'
d:/mingw/bin/../lib/gcc/mingw32/4.8.1\libgomp.a(env.o):(.text.startup+0x3c):
undefined reference to `_imp__pthread_attr_setstacksize'
d:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe:
d:/mingw/bin/../lib/gcc/mingw32/4.8.1\libgomp.a(env.o): bad reloc
address 0x0 in section `.ctors'
d:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe:
final link failed: Invalid operation
Then I tried to execute the exact same compiling and linking commands using the MinGW + GCC 4.8.1 environment that was installed together with CodeLite. It fails again with different error messages:
./tmp/hshfitcmdline.o:hshfitcmdline.cpp:(.text.unlikely+0x105):
undefined reference to `_Unwind_Resume'
./tmp/hshfitcmdline.o:hshfitcmdline.cpp:(.text$_ZN9NormalMapD1Ev[__ZN9NormalMapD1Ev]+0xb4):
undefined reference to `_Unwind_Resume'
d:/mingw-4.8.1/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe:
./tmp/hshfitcmdline.o: bad reloc address 0xb4 in section
`.text$_ZN9NormalMapD1Ev[__ZN9NormalMapD1Ev]'
d:/mingw-4.8.1/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe:
final link failed: Invalid operation collect2.exe: error: ld returned
1 exit status make: *** [build/rspfitter] Error 1
I confirmed that the file "libgomp.a"/"libgomp.dll.a" was present on the [MinGW dir]/lib/gcc/mingw32/4.8.1/ for both installations of MinGW. However, they are of different sizes! In installation downloaded from MinGW.org, 'libgomp.a' is of 86kb, and "libgomp.dll.a" is of 87kb; In the CodeLite installation, however, the sizes are 74kB and 148Kb respectively.
Now I am wondering:
What could be the cause of the error messages given by the two MinGW systems? Could it be that the statically libraries that I downloaded from MinGW are corrputed? But dynamically linking was perfectly fine on both systems.
How on earth can I correctly link libgomp statically?
Thanks

To link libgomp statically you can do
ln -s `g++ --print-file-name=libgomp.a` && \
g++ foo.o -static-libgcc -static-libstdc++ -L. -o foo -fopenmp -ljpeg -lopenblas
However your executable will still depend on a pthread dll. The reason you are getting the error is that libc is still linking dynamically. To fix this you have to link libc statically as well
ln -s `g++ --print-file-name=libpthread.a` && \
ln -s `g++ --print-file-name=libc.a` && \
g++ foo.o -static-libgcc -static-libstdc++ -L. -o foo -fopenmp -ljpeg -lopenblas
However, if openblas or jpeg libraries depend on libc then there will likely still be undefined references.

Related

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 ?

Boost link error occurs even though I'm including the library

I'm trying to build a boost-dependent project on TravisCI. When it runs the g++ command:
g++ -Wall -L/usr/lib -fopenmp -lboost_system -lboost_filesystem -o bin/test obj/data_parser.o obj/hmm.o obj/test.o
It gets this linking error:
data_parser.cpp:(.text+0x136a): undefined reference to `boost::system::generic_category()'
But not only am I including -lboost_system in the g++ command, I also know that /usr/lib/libboost_system.so exists.
This is on an Ubuntu/Linaro 4.6.3-1ubuntu5 system with g++ 4.6.3. I installed the boost libraries with:
sudo apt-get install libboost-dev libboost-filesystem1.46-dev libboost-iostreams1.46-dev libboost-system1.46-dev
Why won't this link correctly?
Put the libraries after the object files in the linker command.
The objects and libraries are linked in order; and library code is only linked if it's needed to resolve a reference in the currently linked objects. By putting them first, there are no unresolved references when they are processed, so no code is linked from them.

C++: linker cannot find -lcrypto, but the library is in the path

I am compiling a C++ application using GNU g++. The project takes advantage of OpenSSL libraries.
Background
On my machine (a 64 bit CentOS quad core) I compile and link my files.
g++ -g -c -L/usr/local/lib/ -L/usr/lib64/
-I/usr/local/include/ -I/usr/local/ssl/include/
-lcrypto mysrc1.cpp mysrc2.cpp mysrc3.cpp
g++ -L/usr/local/lib/ -L/usr/lib64/ -lcrypto
*.o -o ./myapp.out
My application uses function MD5 which is contained in libcrypto.so. As you can see I specify to g++ the dirs where to search using the -L, -I options and which libraries to look for with the -l<lib-name> option. There are some trivial paths like /usr/local/lib which can be omitted of course, but I specified them because the makefile is parametric.
The problem
My problem is that I can successfully compile my stuff (first command), but linking fails (second command):
/usr/bin/ld: cannot find -lcrypto
collect2: ld returned 1 exit status
make: * [cppsims_par] Error 1
But I did check folders and everything... libcrypto.so is inside /usr/lib64/. What is going on?
It may help if you try strace to find why it failed the file lookup
strace -f -e trace=file g++ -L/usr/local/lib/ -L/usr/lib64/ -lcrypto
*.o -o ./myapp.out
I did find the problem and it is related to this question: ld cannot find an existing library
Actually I had no symlink libcrypto.so and the compiler was not able to find the library...
I had related issue, and resolved it after inspecting the trace.
I had
-L<my/path/to/lib> -llib_some_library
when it should have been
-L<my/path/to/lib> -lsome_library

How to tell ld where to find libc

So I created a static library with some basic assistance functions in C++ today. I built it with Clang 3.2 (SVN snapshot). However when I try to run a test program that links to it (prog.cpp), I get the following error:
~/Projects/CPP/AssisterLib> g++ prog.cpp -o program -static -L. -lassister
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/bin/ld: cannot find -lm
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/bin/ld: cannot find -lc
collect2: ld returned 1 exit status
I get the same error with G++ and Clang++. Apparently it can't find libc.a and libm.a, which are both in /usr/lib64 (provided by glibc-devel in OpenSUSE). Adding -L/usr/lib64 does nothing for the error.
Why can't ld find those libraries? Is there a flag that I'm missing?
The problem is likely the use of -static. I would conclude you do not have static version of the libm and libc installed. You can try removing -static to confirm.
The -static flag signals to the compiler that you want your executable to be entirely statically linked, and so it fails if not all the libraries have static versions available.

linux cross compiling and dynamic libraries / linking

i'm trying to develop for the BeagleBoard.
Therefore i installed the CodeSourcery Sourcery_G++_Lite Toolchain.
I want to use the opencv library. So I downloaded the sources to my Ubuntu devolepment system, compiled with gcc as shared library and installed the library.
When i build a helloworld-application for the x86-Architecture, everything is fine.
Now, i want to compile the same application with the other toolchain for the ARM-Architecture.
I get these warnings/erros while compiling/linking:
john#ubuntu:~/Downloads/BeagleTest$ arm-none-linux-gnueabi-g++ -c ImageProcessing.cpp -o ImageProcessing.o -I/usr/local/include
cc1plus: warning: include location "/usr/local/include" is unsafe for cross-compilation
john#ubuntu:~/Downloads/BeagleTest$ arm-none-linux-gnueabi-g++ -c Main.cpp -o Main.o -I/usr/local/include
cc1plus: warning: include location "/usr/local/include" is unsafe for cross-compilation
john#ubuntu:~/Downloads/BeagleTest$ arm-none-linux-gnueabi-g++ -oApplication -L/usr/local/lib Main.o ImageProcessing.o -lopencv_core
/usr/local/CodeSourcery/Sourcery_G++_Lite/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.1/../../../../arm-none-linux-gnueabi/bin/ld: warning: library search path "/usr/local/lib" is unsafe for cross-compilation
/usr/local/CodeSourcery/Sourcery_G++_Lite/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.1/../../../../arm-none-linux-gnueabi/bin/ld: skipping incompatible /usr/local/lib/libopencv_core.so when searching for -lopencv_core
/usr/local/CodeSourcery/Sourcery_G++_Lite/bin/../lib/gcc/arm-none-linux-gnueabi/4.2.1/../../../../arm-none-linux-gnueabi/bin/ld: cannot find -lopencv_core
collect2: ld returned 1 exit status
Obviously, im using the same include-directories and library-pathes like im using for the x86-Architecture. This does not work. But what do i have to do? Do i have to cross compile the opencv-library?
Libraries have to be cross compiled and you have to make sure the correct library is found when linking. If that shouldn't work automatically you may want to take a look at the --sysroot command line switch of gcc.
Yes. Libraries are specific to an architecture.