I'm trying to generate a mex function usigin external libraries. I'm using Ubuntu 18 and Matlab R2021a.
In particular I want to compile my file.cpp that uses my cpp library called model.
What I did is
mex -I<path_library_include> -L<path_library_so_file> -lmodel.so -lboost_system -lstdc++ file.cpp -v
where in -I i put the path where is the include of the library in -L the path in which the libmodel.so is located, then I added 2 more libraries and at the end the source file that I want to compile.
In this way I can compile my source but when I try to execute the mex function I get:
libmodel.so: cannot open shared object file: No such file or directory
I also tested the library outside matlab and works fine, this is the command that I use to compile the library outside Matlab
gcc -Wall -I<path_library_include> -L<path_library_so_file> main.cpp -lmodel -lboost_system -lstdc++ -o main
What could be the problem with Matlab?
Thanks to 273K that gave me the right direction.
The problem was that the LD_LIBRARY_PATH was not configured well in fact running /sbin/ldconfig -v my library was not present. So to add the shared library i created a new file as root in /etc/ld.so.conf.d/ called mylib.conf it is not important the name just the extension. Then I run
sudo ldconfig
after that the library was present in fact running
/sbin/ldconfig -v | grep model
where model is the name of my library. it is possible to see the output.
Related
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
Update: issue is solved. The library was Made for Armv7a CPUs but it was "soft float" Not "hard float". It seems like my machine is HF and Not SF compatible
My program depends on an externally build .so library called libMyLib.so. When I compile the program like this:
$ g++ -std=c++11 main.cpp -o run -pthread
it reports that there are a lot of undefined references, obviously because i didn't include libMyLib.so when compiling. So the compiler knows what he needs to compile the program. When i compile the program like this:
$ g++ -std=c++11 main.cpp -o run -pthread -lMyLib
it doesn't report any errors and creates the file "run". Notice that libMyLib.so is already in /usr/local/lib and it looks like it is linked when compiling since the references are defined now and the "run" file is created. But as i run the file, this happens:
$ ./run
./run: error while loading shared libraries: libMyLib.so: cannot open shared object file: No such file or directory
I've checked with ldd and it shows me this:
$ ldd run
...
libMyLib.so => not found
...
So ldd doesn't find the library on execution, but it finds it while compiling. I'm quite new to Linux and linking libraries so i don't know what to do.
Also, running ldd on the .so file returns this:
$ ldd /usr/local/lib/libMyLib.so
not a dynamic executable
I've already checked an this message may occur when running a .so file on the wrong platform. But i've checked, the library is compiled for arm (I'm running on a raspberry pi -> arm):
$ objdump -f /usr/local/lib/libMyLib.so | grep ^architecture
architecture: arm, flags 0x00000150:
I also update the linker:
$ sudo ldconfig -v
...
/usr/local/lib:
libwiringPi.so -> libwiringPi.so.2.44
libwiringPiDev.so -> libwiringPiDev.so.2.44
libMyLib.so -> libMyLib.so.1
...
I really have no clue why this might still happen. Can anyone help me?
/usr/local/lib is one of the directories that the linker searches by default
for libraries specified with the -l option, so your linkage succeeds.
At runtime however, the program loader by default searches for the linked
libraries in:-
/lib, /usr/lib and among the libraries whose names and locations have been cached in the ldconfig cache, /etc/ld.so.cache.
The directories listed in the value of the environment variable LD_LIBRARY_PATH,
in the current shell.
The ldconfig cache is only updated when ldconfig is run. See man ldconfig.
The loader fails to find libMyLib.so at runtime because you have not
run ldconfig since you placed that library in /usr/local/lib and
neither have you correctly added /usr/local/lib to the LD_LIBRARY_PATH
in the same shell in which you try to run the program.
It is inconvenient and otherwise undesirable to require a special setting of
LD_LIBRARY_PATH to enable a program to run.
To enable the loader to find your library, run ldconfig as root. This
will succeed provided that /usr/local/lib is listed in /etc/ld.so.conf,
or in one of the files included by /etc/ld.so.conf. If it's not, then
you can explicitly cache the shared libraries from /usr/local/lib by running
ldconfig /usr/local/lib, as root.
First check LD_LIBRARY_PATH variable is having the path to your library directory
$ echo $LD_LIBRARY_PATH
If not there then update the library path.
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/library
Use strace to debug.
strace -f ./run
It would be helpful if you could provide some guidance on how to compile c++ source code files in an Ubuntu environment, using the MATLAB Engine with g++.
I assume that you want to know the procedure for compiling the c++ code (which calls MATLAB engine) using g++ from Linux Terminal. To do so, follow the steps below:
Include following paths in PATH variable:
a) Location of MATLAB i.e. $matlabroot/bin
b) $matlabroot/sys/os
You can do this by using the command
'setenv PATH $matlabroot/bin:$matlabroot/sys/os:$PATH ' .
In the command prompt, navigate to the directory where the cpp code is located using cd command. For instance, if you are compiling engdemo.cpp, you need to navigate to $matlabroot/extern/examples/eng_mat/engdemo.cpp
You need to call the compiler with required include files and libraries. For this you can use -I and -L switches for that. Note that the order is important. So you need to use the command as below:
g++ engdemo.cpp -I "$matlabroot/extern/include" -L "$matlabroot/bin/glnxa64" -leng -lmat -lmex -lut -o engdemo.o
The above command will generate an object file engdemo.o. To execute this, use the command ./engdemo.o
You can refer to the document at http://www.umiacs.umd.edu/~jsp/Downloads/MatlabEngine/MatlabEngine.pdf for more help regarding C++ and MATLAB.
The compilation process in C/C++ is divided in two phases:
First, the compilation where source code is transformed into machines code with multiples object files (.o or .obj).
Then, the link to transform object files into a single executable file (.dll or .exe).
C/C++ programs that run matlab engine need three things:
1> A compiler that is compatible with matlab engine.
2> Reference to API header files('.h' for c or '.hpp' for c++) for compilation.
3> Reference to the libraries('.lib' for windows,'.so' for linux) for external symbol link.
You can see comptatible linux based system compiler here.
The GCC C/C++ 4.9.x is compatible so you can use g++.
As this pdf suggested, the API header files should be there $matlabroot/extern/include and the .so files should be in $matlabroot/
bin/glnax64 where $matlabroot is your matlab install folder
Set up Environment variables
Open your temnial with ctrl + alt + T and type :
setenv PATH $matlabroot/bin:$matlabroot/sys/os:$PATH
You can then go to the folder where source file is located, let's say $matlabroot/extern/examples/eng_mat/ with the following command :
cd $matlabroot/extern/examples/eng_mat/
You need to do the compilation with :
g++ -c engDemo.cpp -I '$matlabroot/extern/include' -leng -lmat -lmex -lut
After that, a file named engDemo.o should be created.
The -leng -lmat -lmex -lut options are probably needed among other things because of the usage of the matlab interpreter that should be located in $matlabroot/bin
And the external symbol link with :
g++ -o engDemo -L '$matlabroot/bin/glnax64'
Be careful as this path sugested that you are on a x64 architecture machine, if you are not,the path might be slightly different.
Then you can execute your file just by doing ./engDemo
I can't install the matlab engine on the laptot I am using so I'm unable to test the instruction I gave you but It should be done this way.
Hope it helps !!
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 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 ...