I am trying to call Matlab functions from C++ code.
With Matlab it comes an example of such code at /extern/examples/eng_mat/engdemo.cpp, however I found no way to build that source code.
Here is the makefile I use:
CFLAGS = -Wall -O3
INCLUDES = -I/opt/Matlab-2009a/extern/include
LIBRARIES = -Wl,-R/opt/Matlab-2009a/bin/glnx86 -L/opt/Matlab-2009a/bin/glnx86 -lmx -lmat -leng
out : engdemo.cpp
g++ $(CFLAGS) $(INCLUDES) -static $^ $(LIBRARIES) -o out
clean :
rm -f out
(Here /opt/Matlab-2009a is my Matlab root.) I am getting a linker error like this:
/usr/bin/ld: cannot find -lmx
collect2: ld returned 1 exit status
make: *** [out] Error 1
And the question is: how can I make g++ to compile engdemo.cpp ?
Note, that the shared library exists:
$ locate libmx.so
/opt/Matlab-2009a/bin/glnx86/libmx.so
/opt/Matlab-2009a/bin/glnx86/libmx.so.csf
and
$ ldd /opt/Matlab-2009a/bin/glnx86/libmx.so
linux-gate.so.1 => (0x004b4000)
libut.so => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/libut.so (0x0078f000)
libmwfl.so => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/libmwfl.so (0x00110000)
libicudata.so.38 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/libicudata.so.38 (0xb7f82000)
libicuuc.so.38 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/libicuuc.so.38 (0x00bee000)
libicui18n.so.38 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/libicui18n.so.38 (0x001f7000)
libicuio.so.38 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/libicuio.so.38 (0x00e1c000)
libz.so.1 => /usr/lib/libz.so.1 (0x0098e000)
libstdc++.so.6 => /opt/Matlab-2009a/bin/glnx86/../../sys/os/glnx86/libstdc++.so.6 (0x00531000)
libm.so.6 => /lib/libm.so.6 (0x00194000)
libgcc_s.so.1 => /opt/Matlab-2009a/bin/glnx86/../../sys/os/glnx86/libgcc_s.so.1 (0x00eaa000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00900000)
libc.so.6 => /lib/libc.so.6 (0x00345000)
librt.so.1 => /lib/librt.so.1 (0x00964000)
libdl.so.2 => /lib/libdl.so.2 (0x0014e000)
libexpat.so.1 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/../../bin/glnx86/libexpat.so.1 (0x00152000)
libboost_thread-gcc42-mt-1_36.so.1.36.0 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/../../bin/glnx86/libboost_thread-gcc42-mt-1_36.so.1.36.0 (0x00fc2000)
libboost_signals-gcc42-mt-1_36.so.1.36.0 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/../../bin/glnx86/libboost_signals-gcc42-mt-1_36.so.1.36.0 (0x0017d000)
libboost_system-gcc42-mt-1_36.so.1.36.0 => /opt/Matlab-2009a/bin/glnx86/../../bin/glnx86/../../bin/glnx86/libboost_system-gcc42-mt-1_36.so.1.36.0 (0x00a06000)
/lib/ld-linux.so.2 (0x001db000)
So, how can I make g++ to compile engdemo.cpp ?
Assuming $MATLABROOT is the path to MATLAB:
$MATLABROOT/bin/mex -f $MATLABROOT/bin/engopts.sh engdemo.cpp
If you add the -v switch, the verbose output will show you what commands are being used to compile the engine application.
Why are you compiling with -static? From "man gcc":
-static
On systems that support dynamic linking, this prevents linking with the shared libraries. On other systems, this option has no effect.
In other words, the -static option forces the linker to only consider static libraries, meaning that it will try to find libmx.a rather than libmx.so. Since Matlab only ships with shared (dynamic) libraries, it fails.
Try removing that option & see what happens.
If that doesn't work, you may need to run libtool to help it find the .so's at runtime.
I thought I'd post something that related that might be of use to someone who stumbles upon this post in the future, on the theme of calling a Matlab function from C++.
In a tutorial posted on the Mathworks site the use of shared libraries is demonstrated for calling Matlab function(s) from a C++ file. Here, the mcc command is used to create a shared library.
Subsequently, the mbuild command is used to build the executable. However, if you have a complicated C++ code, which itself needs its own set of shared libraries for compilation, mbuild won't work. The tutorial doesn't demonstrate what needs to be done in this case. So, the purpose of my reply is to post that solution. The user C++ file is vigenere.cpp, and the shared library to be linked in this case is libvigenere.so, and this is the resultant call to g++:
g++ -o vigenere -L/usr/local/MATLAB/R2013b/runtime/glnxa64 -L. -I/usr/local/MATLAB/R2013b/extern/include/ vigenere.cpp -lmwmclmcrrt -lm -lvigenere
Some prerequisites:
The Matlab Compiler Runtime (MCR) needs to be installed. Either type mcrinstaller at the Matlab prompt, or download the appropriate installer from the Matlab site.
After doing this, make sure to set your LD_LIBRARY_PATH as per the instructions at the end of the installer.
The current working directory needs to be added to the LD_LIBRARY_PATH. In bash, I do this by export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD
Note that 1&2 are also described in a readme.txt file generated by the mcc command.
Related
I want to build a standalone bainary (static linking) of my fortran code so that it does not use any shared libaries anymore.
The program uses mpi so I need all connected libaries.
I started with generating my own libary pack:
ar rc my_lib.a /opt/intel/impi/4.1.0.030/intel64/lib/* /opt/intel/composerxe/mpirt/lib/intel64/*
Followed by compiling my files:
ifort -c -I/home/.../Remote/mpif.h -L/home/../Remote/my_lib.a file1.f
ifort -c -I/home/.../Remote/mpif.h -L/home/.../Remote/my_lib.a file1.f
ifort -O3 -o dns zufall.o dnspipe.o my_lib.a
But this returned the following error message:
ld: dns: hidden symbol `stat' in /usr/lib/x86_64-linux-gnu/libc_nonshared.a(stat.oS) is referenced by DSO
ld: final link failed: Bad value
How could I fix that?
Remark 1: #Gilles
I tried that now and it works:
mpiifort -c zufall.f
mpiifort -c dnspipe.f
ifort -o dns zufall.o dnspipe.o -L/opt/intel/impi/4.1.0.030/intel64/lib -Wl,-non_shared,-lmpigf,-lmpi,-lmpigi,-call_shared
The ldd dns output than is:
linux-vdso.so.1 => (0x00007fff6ace6000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f557a6f9000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f557a4dd000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f557a151000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f5579f3b000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5579d37000)
/lib64/ld-linux-x86-64.so.2 (0x00007f557a993000)
Is this now static?
I don't have the same version of Intel MPI so I can't test for sure my solution here. But still, here is how it goes after a few remarks:
Having a fully static binary might not be such a good idea, especially when it comes to the libc... But on a fully homogeneous cluster, why, not.
Normally, just using mpiifort -static should do the trick. However, experience shows that this is rarely the case because of some random functions missing here and there in the static libs, etc.
If only some of the libraries are the ones you want to have statically linked, then there is a solution. If for example this is the Intel libraries you want static, the -intel-static linking option is supposedly doing the tick. But again, unfortunately, most of the time it doesn't work as advertised, notably for the MPI libraries.
So let's assume that what you want is at least packing the MPI libraries into your binary. So this is how I do it:
> mpiifort -c hello_mpi.f90
> ifort -o hello_mpi hello_mpi.o -L$INTEL_MPI_PATH/intel64/lib -Wl,-non_shared,-lmpigf,-lmpi,-lmpigi,-call_shared
The list of libraries to include will depend on the version of the MPI library you use I guess, but you can easily get it with a mpiifort -show.
This works for me. Does it for you?
I need to cross compile C/C++ code for the Raspberry Pi (armV6). I followed the instructions on http://hertaville.com/2012/09/28/development-environment-raspberry-pi-cross-compiler/ and I got the building on my host machine (Ubuntu 14.04) working.
So my project builds on my host machine after some irritation with the needed libraries, I was happy enough. But when I transferred the program to my Raspberry Pi, I got the following error:
{ProjectName}: /usr/lib/arm-linux-gnueabihf/libstdc++.so.6: version `GLIBCXX_3.4.18' not found (required by {ProjectName})
{ProjectName}: /usr/lib/arm-linux-gnueabihf/libstdc++.so.6: version `GLIBCXX_3.4.19' not found (required by {ProjectName})
So I suspect the crosscompiler is using the libstd++.so of my host machine instead of the one that is part of the crosscompiler, but I have no idea how to fix it.
I'm using the gcc-linaro-arm-linux-gnueabihf-raspbian/arm-linux-gnueabihf-g++ crosscompiler.
The program that I try to get working is written by someone else directly on the pi, there it builds, compiles and runs perfectly.
My makefile looks like this:
CC=arm-linux-gnueabihf-g++
IFLAGS=-pthread -I./headers -lwiringPi -lortp -llinphone
LIBB = -I/home/david/rpi/rootfs/usr/lib/arm-linux-gnueabihf/
CFLAGS=-Wall -std=c++0x
LDFLAGS=-Wall
SOURCES=$(wildcard src/*cpp)
OBJECTS=$(addprefix obj/,$(notdir $(SOURCES:.cpp=.o)))
EXECUTABLE=bin/wackytalky
all: $(SOURCES) LINK_EXEC
debug: CFLAGS += -g
debug: $(SOURCES) LINK_EXEC
LINK_EXEC: $(OBJECTS)
$(CC) $(LDFLAGS) -o $(EXECUTABLE) $^ $(LIBB) $(IFLAGS)
obj/%.o: src/%.cpp
$(CC) $(CFLAGS) -o $# -c $< $(IFLAGS)
clean:
rm $(EXECUTABLE) obj/*.o
I had the same problem (exactly) as you yesterday. I don't have time to follow up on the Pi side yet, so I just modified modified my cross compile options (I use eclipse) and added -static-libstdc++ to the linker command. This statically links in the code on the Ubuntu side, so the problem with the .so on the Pi side never arises.
Obviously it makes for a much larger executable file.
You have to copy the libstdc++ and others to your respary pi. If you use an newer compiler which generate executables which needs a newer lib this lib must be present on the target. Static linking is not a useful option. Simply copy the new libs to the appropriate path on your target.
So I suspect the crosscompiler is using the libstd++.so of my host machine instead of the one that is part of the crosscompiler, but I have no idea how to fix it.
No, I don't believe this. If your compiler was configured correctly, it uses the correct libs. And if it tries to use you x86 libs, you don't get an message of wrong version because the dynamic linker can not work with x86 libs at all.
For the downvoters :-):
You can have more then one version on the target, so it is no problem to do this, see ldconfig for details. Also you can have the lib in the local or any other path without a problem, for this you can use LD_LIBRARY_PATH. And yes, I have not written that you should remove older versions. Linux is not windows so a added library will not break the system. Linux have no problems like the dll hell of win...
Of your special request I build one program with two different compilers and get from ldd:
gcc 4.9:
linux-vdso.so.1 => (0x00007fff4b7fe000)
librt.so.1 => /lib64/librt.so.1 (0x00000030f2200000)
libdl.so.2 => /lib64/libdl.so.2 (0x00000030f1200000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00000030f0e00000)
libstdc++.so.6 => /opt/linux-gnu_4.9-20140105/lib64/libstdc++.so.6 (0x00007fa4aadc4000)
libm.so.6 => /lib64/libm.so.6 (0x00000030f1600000)
libgcc_s.so.1 => /opt/linux-gnu_4.9-20140105/lib64/libgcc_s.so.1 (0x00007fa4aabad000)
libc.so.6 => /lib64/libc.so.6 (0x00000030f0a00000)
gcc 4.8.2:
linux-vdso.so.1 => (0x00007fff4b7fe000)
librt.so.1 => /lib64/librt.so.1 (0x00000030f2200000)
libdl.so.2 => /lib64/libdl.so.2 (0x00000030f1200000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00000030f0e00000)
libstdc++.so.6 => /opt/linux-gnu_4.8.2/lib64/libstdc++.so.6 (0x00007fa4aadc4000)
libm.so.6 => /lib64/libm.so.6 (0x00000030f1600000)
libgcc_s.so.1 => /opt/linux-gnu_4.8.2/lib64/libgcc_s.so.1 (0x00007fa4aabad000)
libc.so.6 => /lib64/libc.so.6 (0x00000030f0a00000)
As you can see: Two versions of one library one one system and no problems at all.
Some more infos on different of libs on the os look here at:
How do applications resolve to different versions of shared libraries at run time?
If it will not work on your system, feel free to ask again.
I have been working on a project which will be loaded on an embedded system, has not enough memory/disk space to install a C++ compiler and compile the code, natively.
So, I need to “cross-compile” the code on my development (Host) machine to be used on the target machine (Embedded Linux).
The happening problem related to using strings and iostreams which are a feature of the C++ standard template library (STL). However, because memory is so critical in an embedded system, the standard template library (libstdc++), can not be available on target side.
I need to statistically link the standard libraries on host machine, rather than dynamically link on target side. So, in my Makefile I need to have a slightly complex modification in both compiling and linking steps in order to build my project.
I have used some parameters such as -nodefaultlibs, -static-libstdc++, and -lstdc++ in the linking step and also added -nostdinc++ to the compiler flags. Still, there exist the problem on target side; " can not load library libstdc++.so.6 "
Most of these settings I have tried did not work. Is there any solution?
-lstdc++ overrides -static-libstdc++, try linking with just -static-libstdc++.
See this for example:
$ g++ -o foo foo.cpp -static-libstdc++ -lstdc++
$ ldd foo
linux-gate.so.1 => (0x0056b000)
libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0x007ae000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00110000)
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0x005dd000)
/lib/ld-linux.so.2 (0x002bc000)
libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0x0095e000)
libstdc++ is linked dynamically!
$ g++ -o foo foo.cpp -static-libstdc++
$ ldd foo
linux-gate.so.1 => (0x0097b000)
libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0x001f9000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x0037f000)
/lib/ld-linux.so.2 (0x00199000)
now it is not.
Im trying to link my program to the shared library. Im using a makefile to compile. It looks like this: `
make: sms_out.cpp SMSDispatch.cpp SMSDispatch.h
g++ -c -fPIC SMSDispatch.cpp -o SMSDispatch.o
g++ -shared SMSDispatch.o -o libSMSDispatch.so
` g++ sms_out.cpp -L. -lSMSDispatch -o sms_out
It works fine if I run the program in the command window with:
LD_LIBRARY_PATH="." ./sms_out
But I want to run it with just ./sms_out, can someone help me?
Tried to add export LD_LIBRARY_PATH=. to the makefile, but that didnt work, just got the error " error while loading shared libraries: libSMSDispatch.so: cannot open shared object file: No such file or directory" when I try to run the program.
Another option - provide -rpath options to linker to inform your binary where else search for dynamic objects.
g++ -Wl,-rpath=<path to .so> -o <your binary here> <cpp file name>.cpp
Add the directory where the .so file exists to LD_LIBRARY_PATH:
$ export LD_LIBRARY_PATH=/dir/containing/sharedobject
A utility you may find useful is ldd, which prints the shared library dependencies. For example:
$ ldd /bin/ls
linux-vdso.so.1 => (0x00007fff819ff000)
librt.so.1 => /lib64/librt.so.1 (0x00007fc0d3f67000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fc0d3d4a000)
libacl.so.1 => /lib64/libacl.so.1 (0x00007fc0d3b42000)
libc.so.6 => /lib64/libc.so.6 (0x00007fc0d37e9000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fc0d35cd000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc0d4170000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fc0d33c9000)
libattr.so.1 => /lib64/libattr.so.1 (0x00007fc0d31c4000)
If shared objects are not locatable a string not found, or similar, is displayed instead of the path to the shared object being used.
I'm trying to get libpng working on linux. I couldn't get it to work through netbeans, so I ran g++ directly as g++ -lpng -lz main.cpp -o test and it compiles. When I try to run it it it outputs ./test: error while loading shared libraries: libpng14.so.14: cannot open shared object file: No such file or directory. I assume this means I am linking dynamically and it can't find the .so file
~/Programs/NetBeansProjects/DiamondSquare$ ldd test
linux-gate.so.1 => (0x008a5000)
libpng14.so.14 => not found
libz.so.1 => /usr/local/lib/libz.so.1 (0x00209000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x0094b000)
libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0x00e3a000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00927000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00220000)
/lib/ld-linux.so.2 (0x00b85000)
I didn't really want to link dynamically in the first place. How could I resolve this?
I know that libpng14.so.14 is in /usr/local/lib also, if that matters.
Extra points if you can tell me how to do this within netbeans.
It's odd that g++ is able to find the library but test can not (you can tell that g++ can find it because test specifically expect libpn14 even though you only tell g++ '-lpng'). Are you sure you aren't passing any -L or -R flags to g++? Are your LD_PRELOAD or LD_LIBRARY_PATH environment variables set in the shell you're running g++ in but not in the shell you're running test in? You can point LD_PRELOAD at a specific shared library to tell an app or g++ how to find it, and any folders in LD_LIBRARY_PATH are automatically searched.
Also to link libpng statically put "-Wl,-Bstatic" before "-lpng." Beware, any libraries after the -Bstatic will be linked statically. You can switch back to dynamic and list some more libraries by using "-Wl,-Bdynamic -lfoo".
Dynamic linking is the default and should be preferred in general. You say libpng is in /usr/local/lib, are you really positive about this? It finds /usr/local/lib/libz.so.1. If libpng14.so.14 was in /usr/local/lib, too it should find it.