I enjoy using the Armadillo Linear Algebra Library. It becomes extremely nice when porting octave .m files over to C++, especially when you have to use the eigen methods.
However I ran into issues when I had to take my program from my native vanilla G++ and dump it onto my ARM processor. Since I spent a few hours muddling my way though it I wanted to share so others might avoid some frustration.
If anyone else could add anything else I would love it. This was the process I used to tackle this and surely isn't the only or best approach.
My specific setup is OSX (IDE Eclipse) cross compiled to a Beaglebone Black. However, these instructions should work for similar setups.
Optional:
For compiling I used the Mac OS X ARM GNU Linux G++ Lite 2013.11-33 Toolchain. Specifically, the ARM GNU/Linux G++ Lite 2013.11-33 Advanced Binary.
1. Download:
Just as Matt posted, the GCC cross compiler doesn't support Fortran, so if you want to compile LAPACK and BLAS, use a modified version found here. I'm using is clapack-3.2.1-CMAKE.tgz
2. Make a cross compile cmake file:
You can use a toolchain builder or just write one. I wrote one.
Example:
Note: This is my first time making a cmake file. It isn't guaranteed to be correct.
You'll want to replace /usr/local/arm-2013.11/bin/arm-none-linux-gnueabi-gcc with the path to your selected compiler, as well as /usr/local/arm-2013.11/bin/arm-none-linux-gnueabi-c++ and /usr/local/arm-2013.11
I chose to save this cmake file as beaglebone.cmake
3. Compile:
Extract clapack-3.2.1-CMAKE.tgz and cd
compile: cmake -DCMAKE_TOOLCHAIN_FILE=~/Dropbox/workspaces/beaglebone/beaglebone.cmake
where ~/Dropbox/workspaces/beaglebone/beaglebone.cmake is the path to your cmake file.
make
For some sort of reason I get:
Oddly, running make again compiles fine:
...
4. Copy (Install):
returns
cp libblas.a libf2c.a and liblapack.a to your favorite library folder. I made /usr/local/armadillo-4.300.3/lib
Required:
1. Copy Includes:
Armadillo doesn't need to be compiled. I haven't ran any benchmarks to verify, but it appears that using LAPACK and BLAS works fine with an uncompiled copy of Armadillo by using #define in code. Code examples later.
extract armadillo-4.300.3.tar.gz
(optional) cp armadillo-4.300.3/include/ /usr/local/armadillo-4.300.3/include
and of course, replace /usr/local/armadillo-4.300.3/include with your path of choice
2. Setup GCC to use Armadillo:
I'm using Eclipse with the C/C++ Cross Compiler Support addon (Help Menu -> Install New Software...), but the instructions are easy to convert to cli or other IDEs.
In the project properties window: C/C++ Build -> Settings
Cross G++ Compiler -> Includes -> Include paths (-I)
Click the + to add an include. My include path is: /usr/local/armadillo-4.300.3/include
3. OPTIONAL - Setup GCC to use the compiled libraries:
Cross G++ Linker -> Libraries ->
Libraries (-l)
lapack
f2c
blas
Library Search Path (-L)
Click the + to add a path. My path is: /usr/local/armadillo-4.300.3/lib
3. Code Example:
In a cpp file try:
Success! :D
Some functionality Armadillo does not directly support and will only work with compiled libraries. You can test that the libraries are compiled and working correctly by running a simple test like:
First off I use Code Sourcery as my cross-compiler. I know there others out there, but I haven't gotten around to rebuilding for another compiler yet, regardless this should be applicable to any compiler.
Information:
The Armadillo library requires LAPACK and BLAS, but Code Sourcery has no Fortran compiler. This led me to a f2c'ed version of LAPACK and BLAS.
1. Get the sources:
First off go grab the sources.
2. Cross-Compile CLAPACK
Once we've got the sources the next thing to do is cross-compile them for our end hardware. In my case an ARM7 using CodeSourcery. Its a REALLY good idea to read the READMEs here, you really can do all of this by just taking the time and reading them.
First thing to do is change the make.inc file to look at our cross-compiler instead of the normal GCC. Normally you would $export, but I found it easier to keep track by modifying the makefiles.
Edit clapack-3.2.1-CMAKE/make.inc from:
to:
Edit clapack-3.2.1-CMAKE/F2CLIBS/libf2c/Makefile from:
to:
Compile the f2c libraries:
When I make the f2c libraries I get an error at the very end:
No actual problem here. Of course it will have trouble executing, it was cross-compiled!
Compile BLAS:
Once this is done you will notice you have a new "blas_XXXXX.a". This is your cross-compiled BLAS library.
Compile LAPACK:
The make.inc will point you to use
$make lapacklib
, but this will lead it to attempt more execution of cross-compiled items. Instead$cd
into the SRC directory and:That should generate your new "lapack_XXXXX.a". Now that we have our F2C, LAPACK and BLAS I recommend placing them somewhere that makes sense so you can find them later. In my case I placed them where I keep my Code Sourcery compiler /CodeSourcery/arm-none-linux-gnueabi/usr/lib. Remember to rename these files:
Remember they have to have the "lib" to be recognized later. Again go ahead and store these in your cross-compiled library location. I have it setup with my tool-chain to make it easier to separate from normal gcc/g++.
3. Cross-Compile ARMADILLO
First off read the README, always the best place to start.
Go ahead and run:
This will get everything ready and generate everything cmake will need for creating our shared armadillo library. The way I proceeded here is not how I think you are supposed to, but as I am no wizard with makefiles in general I thought it would be helpful to show what I did to get it to cross-compile. I modified the generated CMakeCache.txt lines with the following:
I know there is somewhere in that CMakeCache.txt file where you can specify the path to the location of our BLAS and LAPACK, but I struggled to figure it out. Instead of bashing my head against this issue I just modified the "CMakeFiles/armadillo.dir/link.txt" and manually added "-L [Cross-Compiled BLAS/LAPACK directory]. Someone more familiar with how to do this could specify in the comments? Next since we want to manually link the BLAS and LAPACK libraries when we compile our program later (like the README says) modify "include/armadillo_bits/config.hpp" and make sure the line defining the use of the arma wrapper is commented out:
The only thing left to do is
$cd
back to the root of the armadillo directory andOnce the make completes you should be able to use Armadillo in your programs.
4. Using ARMADILLO in your program
To use Armadillo in your program add the include
#include <armadillo>
and the namespaceusing namespace arma;
. Now you should be able to use all of thevec
andmat
you feel like. Normally when using arma all you need to do at compile time is to link libarmadillo.so library, but as I stated earlier we will need to link BLAS and LAPACK directly instead. So here is my GCC C++ Compiler synatx:and my linker:
Also note that the order in which you link libraries does matter! lapack must come first, then f2c, then blas.
Really all you need to make sure happens is that the cross-compiled armadillo directory is included when you compile and your linking is setup correctly as above.
Again more information is better, please feel free to add more comments. What worked for you different that what I did, what I did wrong, what could be done to improve.
Thanks.