I made a little c++ program with this library: http://libtins.github.io
I compile with: g++ -o arp arp.cpp -ltins
It runs fine (Ubuntu 14.04 64 bit), however if i send the executable to a friend, he gets this error when running:
error while loading shared libraries: libtins.so.3.4: cannot open shared object file: No such file or directory
I've looked up on stackoverflow and found something about statically linking and dynamically linking, also tried some g++ arguments but no success.
Is it even possible, to create a binary that "contains" the shared object itself?
Thanks
You can use -static to link the libraries statically.
g++ -o arp arp.cc -ltins -static
To build libtins statically, you could refer to the following section in its README:
Static/shared build
Note that by default, only the shared object is compiled. If you would
like to generate a static library file, run:
cmake ../ -DLIBTINS_BUILD_SHARED=0
Related
I have some c++ code in msys2 that I am trying to link dynamically to show how a dynamic link library works.
In linux, showing the call is no problem. stepping in gdb, we can watch the call go through the jump vector, eventually landing in the desired function.
But in msys2, they wanted to eliminated dlls and all the libraries I can find are .dll.a, I think they are really static libraries.
I build a trivial little function like this:
#include <cstdint>
extern "C" {
uint64_t f(uint64_t a, uint64_t b) {
return a + b;
}
}
compiling in the makefile with:
g++ -g -fPIC -c lib1.cc
g++ -g -shared lib1.o -o libtest1.so
When I run the file utility, it says that:
libtest1.so: PE32+ executable (DLL) (console) x86-64, for MS Windows
When I compile the code using it:
g++ -g main.cc -ltest1 -o prog
The error is -ltest1 no such file or directory.
MinGW uses the .dll extension for shared libraries, not .so.
lib??.dll.a is an import library, a shim that will load the corresponding lib??.dll at runtime.
At some point in time, you couldn't link .dlls directly, and had to link .dll.as instead. The modern MinGW can link .dlls directly, so you shouldn't need to use import libraries anymore.
-ltest1 no such file or directory
Wouldn't you get the same error on Linux? You have to specify the library search path with -L. -ltest1 needs either libtest1.a or libtest1.dll.a or libtest1.dll (perhaps some other variants are checked too).
The reason your linker cannot find the library is because your current working directory is not in the search path for libraries. Add -L. to your linking command.
It is untrue that MSYS2 "wanted to eliminate DLLs". Just run ls /mingw64/bin/*.dll and you will see plenty of DLLs (assuming you have some MINGW64 packages installed). The .dll.a files used for linking are called import libraries.
I have built a GCC cross toolchain for the RPi and can cross-compile C++ source and successfully run it after copying the executable to the RPi.
Next I built the Boost libraries targeting ARM, using the cross toolchain. I can successfully build and link C++ source to those Boost libraries using the cross toolchain on my PC.
I then copied the program, dynamically linked to Boost, to the RPi and copied all built libraries into /usr/local/lib on the Pi. However, executing fails:
$ ./my_program
./my_program: error while loading shared libraries: libboost_system.so.1.60.0: cannot open shared object file: No such file or directory
Again, this library, libboost_system.so.1.60.0, exists in /usr/local/lib.
I also tried
export LD_LIBRARY_PATH='/usr/local/lib'
but that doesn't change anything. What am I doing wrong?
EDIT:
I build all source files like this (rpi-g++ is a symlink to my cross-compiler):
rpi-g++ -c -std=c++1y -Wall -Wextra -pedantic -O2 -I /path/to/cross/boost/include *.cpp
rpi-g++ -o myprog *.o -L /path/to/cross/boost/lib/ -lboost_system -pthread
EDIT 2:
When linked with
rpi-g++ -o myprog *.o -L /path/to/cross/boost/lib/ -rdynamic -lboost_system -pthread
the problem remains the same. I have checked and verified everything suggested by Technaton as well. Strangely, ldd insists that the created executable is "not a dynamic executable" (checked that on my PC and on the RPi), which doesn't make sense to me.
There are several things you can check. I've posted a complete check list here, but judging from your linker command line, number 5 is probably the culprit.
Check that your library and your program are correctly build for the target architecture. You can verify that by using file ./myprog and file libboost_system.so.1.60.0.
Make sure that you have copied the actual shared object, and not a link to it.
Ensure that the shared object file's permissions are sane (0755).
Run ldconfig -v and check that your shared object file is picked up. Normally, /usr/local/lib is in the standard library search path, and LD_LIBRARY_PATH is not required.
Make sure that your program is actually dynamically linked by running ldd ./myprog. Judging from your linker command line, that is the problem: You're missing -rdynamic.
Check the paths returned from ldd: If you have linked with rpath, the library search path might be screwed up. Try again without -rpath.
I'm trying to static link OpenSSL into my program.
It works fine when linking into the executable. I need to use OpenSSL in a shared library (so, or dll) that I dynamically load later on when the process executes.
Trying to statically link OpenSSL into the shared library causes errors due to OpenSSL not being compiled with -fPIC. Is it possible to do this without recompiling openssl?
Also, is there a better way to do this?
I'm trying to static link OpenSSL into my program.
In this case, its as simple as:
gcc prog.c /usr/local/lib/libssl.a /usr/local/lib/libcrypto.a -o prog.exe -ldl
It works fine when linking into the executable.
Devil's advocate... Does it work fine with Position Independent Code (PIE)? PIE on a program is the equivalent to PIC on a shared object (some hand waiving).
gcc -fPIE prog.c /usr/local/lib/libssl.a /usr/local/lib/libcrypto.a -o prog.exe -ldl
According to the GCC folks, you can compile with fPIC, and then build a shared object with -fPIC or a relocatable executable with -fPIE. That is, its OK to use -fPIC for both.
Trying to statically link OpenSSL into the shared library causes errors due to OpenSSL not being compiled with -fPIC.
That's easy enough to fix. You simply specify shared in configure:
./config shared no-ssl2 no-ssl3 no-comp --openssldir=/usr/local/ssl
make
sudo make install
I think you can also (notice the lack of shared):
export CFLAGS="-fPIC"
./config no-ssl2 no-ssl3 no-comp --openssldir=/usr/local/ssl
make
sudo make install
not being compiled with -fPIC. Is it possible to do this without recompiling openssl?
NO, you have to compile with PIC to ensure GCC generates relocatable code.
Also, is there a better way to do this?
Usually you just configure with shared. That triggers -fPIC, which gets you relocatable code.
There's other things you can do, but they are more intrusive. For example, you can modify Configure line (like linux-x86_64), and add -fPIC in the second field. The fields are separated by colons, and the second field is $cflags used by the OpenSSL build system.
You can see an example of modifying Configure at Build OpenSSL with RPATH?
How do you statically link matio, a library for reading mat-files, mainly used by matlab and octave into an executable?
If the file main.cpp holds matio functionality the compiler call
g++ -o main main.cpp -Imatio/include matio/lib/libmatio.a
fails with a bunch of error messages like: undefined reference to `inflateEnd'. This can be resolved by also adding zlib to the compiler call:
g++ -o main main.cpp -Imatio/include matio/lib/libmatio.a -lz
Now the error messages differ with something like undefined reference to `__intel_sse2_strlen'. So it appears that the zlib library is necessary for the comilation.
I now have the following questions:
What do you need to do to statically link the matio library in an executable?
Why do I need to add the zlib library even though I configured and compiled matio with ./configure --without-libz?
To build matio without zlib you apparently need to invoke configure with
./configure --with-zlib=no
(Checked this from configure.ac and config/matio_zlib.m4.)
In case you want to build matio with icc, Intel's developer pages tell that __intel_sse2_strlen is defined in libirc.a on Linux and libirc.lib on Windows.
To compile matio with the gcc do
./configure --with-zlib=no CC=gcc
afterwards, the matio library is statically linkable with the call posted in the question
I'm trying to statically link libtcod to my C++ project without success. I get many linking errors, including:
./tuto: error while loading shared libraries: libtcodxx.so.1: cannot open shared object file: No such file or directory
Has anyone had similar problems with that library?
There are dynamic libs provided in current libtcod (1.6.0) distribution.
You can link libtcod dynamically, but you need to create symbolic links:
cd /var/lib/libtcod
ln -s libtcod.so libtcod.so.1
ln -s libtcodxx.so libtcodxx.so.1
Compile with following command:
g++ src/*.cpp -o tuto -I/var/lib/libtcod/include -L/var/lib/libtcod -ltcod -ltcodxx -Wl,-rpath=/var/lib/libtcod -Wall
Which flags do you use while linking to the library? Did you used -static flag, do you specified -ltcod? If not, add -static -ltcod to the end of command line.
Or you can force tell gcc to link with static builded library:
gcc %YOUR_OTHER_FLAGS_ANDFILES% -l:libtcod.a -L%PATH_TO_TCOD_STATIC_BUILDED_FILE%