Link libraries to linux biinary file in c++ - c++

I'm compiling a c++ program using g++ and i am using two libraries called libsdl2-dev and libsdl2-image-dev
I installed both these libraries in my ubuntu machine with the commands
apt install libsdl2-dev libsdl2-image-dev and when I compile the program everything works fine. Then I copied these libraries from /usr/lib/x86_64-linux-gnu/ to my working dir with the binary file to be able to give this folder to someone else.
The problem comes when the user that hasn't installed these libraries tries to open my program by writing ./main (the binary file). Since he hasn't installed these libraries he would get an error like "can't open shared object: no such file or directory".
This happens because the binary file looks for these libraries in /usr/lib etc...
What i need
I need that my binary file looks for these libraries in the same folder,and not in /usr/lib/x86 etc.., from what I read I have to do something like rpath
The IDE used is Sublime Text and the syntax used to compile all my files is this:
g++ -c src/*.cpp -std=c++14 -m64 -g -Wall -I include && g++ *.o -o bin/debug/main -lSDL2main -lSDL2 -lSDL2_image && ./bin/debug/main`
Structure of folders
I got the project dir with and inside that i got 4 more directories, each one called: bin (with the debug subdirectory, where we got the final compile), include (with hpp files), res (with all textures), and src with all cpp files to compile, the other files are project files and .o files
I'm using Ubuntu 20.04-2 LTS and the same is for the other user's PC
Thanks in advance for any help!

That's because the dynamic linker loading runtime dependencies looks for them in some specified locations, which are "by default" your system library directories (where those libraries got installed by apt).
The other user should ideally install those libraries too (which could be done "automatically" if you build a .deb package with proper dependencies)
Otherwise you would have to change the runpath of your program by adding -Wl,-rpath='$ORIGIN', which makes the dynamic linker look for dependencies just where the binary is located.
$ORIGIN here is a special variable meaning "this executable" which is what you wanted to achieve.
see rpath
and A description of RPATH $ORIGIN

I found a way to resolve!
I used the program patchelf to add an rpath to my directory (linked to the binary file) now everything works

use ldd ./bin/debug/main to check the library
export LD_LIBRARY_PATH =$LD_LIBRARY_PATH:"your library path"
run the program,if this is not work. use patchelf to change the rpath to you r library

Related

How to link libraries with g++ compiler?

I'm trying to link a game library for my game project in C++. I am using the g++ compiler and Atom Code Editor. Also on a Windows machine.
To link the library it needs to link those things:
Include path
Library path
Additional dependencies
The main.cpp file is at ProjectRoot/src/main.cpp and the library is at ProjectRoot/deps/lib_name
Inside the library there is and include folder, with the .h file for including, and a lib folder, with the .lib file. It's a static linking library.
So far, I've tried the following commands:
g++ -o ExecutableName.exe -I /deps/lib_name/include -L /deps/lib_name/lib src/main.cpp
Well, that didn't work though... It said that there was no such file or directory as library_name.h...
I need to know if I'm doing anything wrong and also how to specify the additional dependencies.
Every thing is correct . You just forgot to link the libraries . Do it as follows -
g++ -o ExecutableName.exe -I /deps/lib_name/include -L /deps/lib_name/lib src/main -l[library name] -l[library name]

What steps does gcc(or g++) take in searching for the location of libaries?

When using the -l flag in a c++ makefile, I couldn't find information on what steps gcc takes in searching for that library.
For clarity of what I'm asking, I'll make up an example answer (this is completely made up):
First searches the -L flag directory
Next searches the /lib directory
Something something etc
Some extra info:
The reason I'm stuck in this is because I currently have a program that uses libconfig in the makefile like so:
g++ $(CFLAGS) -o libvldsk_config.so $(SRCDIR)/config.cpp -Wall -shared -fPIC -I$(SRCDIR) -I$(COMMON_SRCDIR) -lconfig
but this was made assuming that libconfig is installed via a package manager. I installed via source because the linux version was too old to have it in a package manager. And so I'm trying to modify my program that uses libconfig to search for the libconfig .so file in the system's /lib directory, and if it doesn't exist search for it in the current project directory.

Executing cross-compiled C++ program using Boost on Raspberry Pi

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.

Copy and pasting .so file doesn't work with linker

I compiled and built the casablanca c++ rest library in my home directory where my absolute path to the necessary .so file was /home/dev/casablanca/Release/build.release/Binaries/libcpprest.so. What I wanted to do was to simply cp and past that .so file to /usr/lib/.. path to default lib search ../ so that I could easily link it with the following command:
g++ index.cpp -I/home/dev/casablanca/Release/include -lcpprest -std=c++11
which compiled fine, but when I ran ./a.out I got the typical runtime error:
couldn't load shared library: libcpprest.so
even after adding the default path of libcpprest.so to LD_LIBRARY_PATH.
However everything worked just fine if I linked the directory where the binary was originally created at:
// ./a.out runs just fine
g++ index.cpp -I/home/dev/casablanca/Release/include \
-L/home/dev/casablanca/Release/build.release/Binaries -lcpprest -std=c++11
I'm guessing that the reason why I can't simply move the .so object where I want to add it is somehow the compiler keeps references to it somehow. How can I install this binary in a different path?
I did compile casablanca on my linux debian ( https://git01.codeplex.com/casablanca ) with procedure https://casablanca.codeplex.com/wikipage?title=Setup%20and%20Build%20on%20Linux&referringTitle=Documentation
after compilation i get a libcpprest.so with that (objdump) :
SONAME libcpprest.so.2.2
so you might want to copy libcpprest.so.2.2 to /usr/lib/libcpprest.so.2.2
or use ldconfig tool to do so.
looking into Release/build.release/Binaries you will find :
libcpprest.so -> libcpprest.so.2.2
libcpprest.so.2.2
then libcpprest.so is just a link, real library is libcpprest.so.2.2
The section you are referring to is tuned by the rpath switch:
g++ -Wl,-rpath,/path/to/lib ...

Linux mingw32 sfml cross compile for windows - missing dll files

I am compiling my C++ project in the following way:
/usr/bin/i686-w64-mingw32-g++ -g -std=c++0x -Wall -I /home/bluszcz/dev/win64/SFML-2.1/include -L /home/bluszcz/dev/win64/SFML-2.1/lib -static-libgcc -static-libstdc++ -static -O4 -c src/game.cpp -o src/game.a -lsfml-graphics -lsfml-window -lsfml-system -lsfml-audio
However, when I try to run my exe file I am getting an error about missing DLL files:
bluszcz#zendo ~/dev/win32/builds/magicwizard $ wine mw.exe
err:module:import_dll Library libgcc_s_dw2-1.dll (which is needed by L"Z:\\home\\bluszcz\\dev\\win32\\builds\\magicwizard\\sfml-system-2.dll") not found
err:module:import_dll Library libgcc_s_sjlj-1.dll (which is needed by L"Z:\\home\\bluszcz\\dev\\win32\\builds\\magicwizard\\libstdc++-6.dll") not found
err:module:import_dll Library libwinpthread-1.dll (which is needed by L"Z:\\home\\bluszcz\\dev\\win32\\builds\\magicwizard\\libstdc++-6.dll") not found
err:module:import_dll Library libstdc++-6.dll (which is needed by L"Z:\\home\\bluszcz\\dev\\win32\\builds\\magicwizard\\sfml-system-2.dll") not found
err:module:import_dll Library sfml-system-2.dll (which is needed by L"Z:\\home\\bluszcz\\dev\\win32\\builds\\magicwizard\\sfml-audio-2.dll") not found
err:module:import_dll Library libgcc_s_dw2-1.dll (which is needed by L"Z:\\home\\bluszcz\\dev\\win32\\builds\\magicwizard\\sfml-audio-2.dll") not found
err:module:import_dll Library libgcc_s_sjlj-1.dll (which is needed by L"Z:\\home\\bluszcz\\dev\\win32\\builds\\magicwizard\\libstdc++-6.dll") not found
err:module:import_dll Library libwinpthread-1.dll (which is needed by L"Z:\\home\\bluszcz\\dev\\win32\\builds\\magicwizard\\libstdc++-6.dll") not found
err:module:import_dll Library libstdc++-6.dll (which is needed by L"Z:\\home\\bluszcz\\dev\\win32\\builds\\magicwizard\\sfml-audio-2.dll") not found
I have compiled using static options - so why it asks for libgcc_s_dw2-1.dll for example?
Also, I copied some files there, but the application still doesn't see them.
bluszcz#zendo ~/dev/win32/builds/magicwizard $ ls *dll
libsndfile-1.dll sfml-audio-2.dll sfml-graphics-d-2.dll sfml-system-2.dll sfml-window-d-2.dll
libstdc++-6.dll sfml-audio-d-2.dll sfml-network-2.dll sfml-system-d-2.dll
openal32.dll sfml-graphics-2.dll sfml-network-d-2.dll sfml-window-2.dll
bluszcz#zendo ~/dev/win32/builds/magicwizard $
And some files, like libgcc_s_dw2-1.dll, don't exist on my file system at all...
To summarize:
Why does my application not see the missing files?
How to compile in static way with mingw32?
How to get the missing files?
I use this version of sfml library to compile it: http://www.sfml-dev.org/download/sfml/2.1/SFML-2.1-windows-gcc-4.7-mingw-32bits.zip
The missing dll's can simply be added to your WINEPATH before running your program with wine, i.e.
export WINEPATH="/usr/x86_64-w64-mingw32/lib;/usr/lib/gcc/x86_64-w64-mingw32/7.3-posix"
!Note, your paths might be slightly different depending on the mingw version you are using.
Answering only the last of the three question:
About the standards libraries, it worked for me to copy them from the mingw folder:
cp /usr/lib/gcc/i686-w64-mingw32/5.3-win32/libstdc++-6.dll ./
However, when I copied from the wrong directory according to my build (e.g. /usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/libstdc++-6.dll) I still had the same error while the file with the exact same name was here.
On my Fedora 26 after installing mingw64-gcc and mingw64-gcc-g++:
[leo#pc]$ locate libgcc_s_seh-1.dll
/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libgcc_s_seh-1.dll
[leo#pc]$ locate libstdc++-6.dll
/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libstdc++-6.dll
[leo#pc]$
If I copy dll's and run wine with generated a.out.exe it works.
Probably your application isn't seeing the files because it's configured like that, and you don't need to add tags like -static to the command.
For compiling static libraries, you must add -s, like -lsfml-window-s -lsfml-system-s
libgcc_s_dw2-1.dll is just inside bin folder, on latest MinGW releases.
If there are missing dlls, there's probably a version incompatibility.