交叉编译犰狳线性代数库

时间:2014-01-21 16:14:06

标签: cross-compiling lapack blas armadillo codesourcery

我喜欢使用Armadillo Linear Algebra Library。将八度.m文件移植到C ++时变得非常好,特别是当你必须使用本征方法时。

然而,当我不得不从我的原生香草G ++中取出我的程序并将其转储到我的ARM处理器上时,我遇到了问题。因为我花了几个小时糊涂我的方式虽然我想分享所以其他人可能会避免一些挫折。

如果其他人可以添加任何其他东西我会喜欢它。这是我用来解决这个问题的过程,肯定不是唯一或最好的方法。

2 个答案:

答案 0 :(得分:12)

首先,我使用Code Sourcery作为我的交叉编译器。我知道那里有其他人,但我还没有为另一个编译器重建,不管这应该适用于任何编译器。

信息:

Armadillo库需要LAPACK和BLAS,但Code Sourcery没有Fortran编译器。这让我得到了一个f2c'ed版本的LAPACK和BLAS。

1。获取来源:

首先去抢夺消息来源。

2。交叉编译CLAPACK

一旦我们获得了源代码,接下来要做的就是为我们的终端硬件交叉编译它们。就我而言,使用CodeSourcery的ARM7。阅读这里的自述文件是一个真的好主意,你真的可以通过花时间阅读它们来完成所有这些工作。

  1. 要做的第一件事是更改make.inc文件以查看我们的交叉编译器而不是普通的GCC。通常你会导出$,但我发现修改makefile更容易跟踪。

    编辑clapack-3.2.1-CMAKE / make.inc:

    CC = GCC
    LOADER = GCC
    

    为:

    CC = [CROSS-COMPILER-GCC location]
    LOADER = [CROSS-COMPILER-GCC location]
    

    编辑clapack-3.2.1-CMAKE / F2CLIBS / libf2c / Makefile来自:

    ld -r -x -o $*.xxx $*.o
    

    为:

    [CROSS-COMPILER-LD location] -r -x -o $*.xxx $*.o
    
  2. 编译f2c库:

    $make f2clib
    

    当我制作f2c库时,我在最后得到一个错误:

    ./a.out > arith.h
    /bin/sh: ./a.out: cannot execute binary file
    make[1]: *** [arith.h] Error 126
    make[1]: Leaving directory `/home/matt/clapack-3.2.1-CMAKE/F2CLIBS/libf2c'
    make: *** [f2clib] Error 2
    

    这里没有实际问题。当然它会执行有问题,它是交叉编译的!

  3. 编译BLAS:

    $make blaslib
    

    一旦完成,你会发现你有一个新的“blas_XXXXX.a”。这是您的交叉编译BLAS库。

  4. 编译LAPACK:

    make.inc将指向您使用$make lapacklib,但这会导致它尝试更多地执行交叉编译的项目。而是$cd进入SRC目录并且:

    $make
    

    那应该生成你的新“lapack_XXXXX.a”。现在我们有了F2C,LAPACK和BLAS,我建议将它们放在有意义的地方,这样你以后就可以找到它们。在我的情况下,我将它们放在我保留Code Sourcery编译器/ CodeSourcery / arm-none-linux-gnueabi / usr / lib的地方。请记住重命名这些文件:

    $cp libf2c.a [CROSS-COMPILE LIBRARY PATH]/libf2c.a
    $cp blas_XXXXX.a [CROSS-COMPILE LIBRARY PATH]/libblas.a
    $cp lapack_XXXXX.a [CROSS-COMPILE LIBRARY PATH]/liblapack.a
    

    请记住,他们必须稍后才能识别“lib”。再次继续将这些存储在交叉编译的库位置中。我使用我的工具链进行设置,以便更容易与普通的gcc / g ++分开。

  5. 3。交叉编译ARMADILLO

    首先阅读README,始终是最好的起点   继续运行:

        $cmake .
    

    这将使一切准备就绪并生成cmake创建共享armadillo库所需的一切。我在这里进行的方式并不是我认为你应该如何,但由于我不是一般的makefile文件,因此我认为展示我所做的是为了让它进行交叉编译会很有帮助。   我使用以下内容修改了生成的CMakeCache.txt行:

        //CXX compiler.
        CMAKE_CXX_COMPILER:FILEPATH=[CROSS-COMPILER-G++ location]
    

    我知道CMakeCache.txt文件中有某处你可以指定BLAS和LAPACK位置的路径,但我很难弄明白。我没有对这个问题猛烈抨击,而是修改了“CMakeFiles / armadillo.dir / link.txt”并手动添加了“-L [交叉编译的BLAS / LAPACK目录]。更熟悉如何执行此操作的人可以指定评论?   接下来因为我们想要在稍后编译程序时手动链接BLAS和LAPACK库(如README所说)修改“include / armadillo_bits / config.hpp”并确保定义arma包装器使用的行被注释掉:

        //  #define ARMA_USE_WRAPPER
    

    唯一要做的就是$cd回到armadillo目录的根目录和

        $make
    

    制作完成后,您应该可以在程序中使用Armadillo。

    4。在程序中使用ARMADILLO

    要在程序中使用Armadillo,请添加包含#include <armadillo>和命名空间using namespace arma;。现在,您应该能够使用您想要的所有vecmat。   通常在使用arma时,你需要在编译时完成链接libarmadillo.so库,但正如我之前所说,我们需要直接链接BLAS和LAPACK。所以这是我的GCC C ++编译器synatx:

        [CROSS-COMPILER-G++] -I [CROSS-COMPILED ARMADILLO DIRECTORY]/include ...
    

    和我的链接器:

        [CROSS-COMPILER-G++] -L [CROSS-COMPILED LIBRARY] -o ... -llapack -lf2c -lblas
    

    另请注意,链接库的顺序很重要! lapack必须先来,然后是f2c,然后是blas。

    真正需要确保的是,编译时包含交叉编译的armadillo目录,并且如上所述正确设置了链接。

    再次提供更多信息,请随时添加更多评论。对我有用的不同之处在于我做了什么,我做错了什么,可以做些什么来改进。

    感谢。

答案 1 :(得分:1)

我的具体设置是OSX(IDE Eclipse)交叉编译为Beaglebone Black。但是,这些说明适用于类似的设置。

可选

为了编译,我使用了Mac OS X ARM GNU Linux G++ Lite 2013.11-33 Toolchain。具体来说,是ARM GNU / Linux G ++ Lite 2013.11-33高级二进制文件。

1。下载:

就像Matt发布的那样,GCC交叉编译器并不支持Fortran,所以如果你想编译LAPACK和BLAS,请使用找到here的修改版本。我使用的是clapack-3.2.1-CMAKE.tgz

2。制作交叉编译cmake文件:

您可以使用工具链构建器或只编写一个。我写了一篇。

示例:

# http://www.cmake.org/Wiki/CMake_Cross_Compiling#The_toolchain_file

# REQUIRED
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)
SET(CMAKE_SYSTEM_PROCESSOR arm)

# Added for the beaglebone
SET(FLOAT_ABI_SUFFIX "")

# specify the cross compiler
SET(CMAKE_C_COMPILER   /usr/local/arm-2013.11/bin/arm-none-linux-gnueabi-gcc)
SET(CMAKE_CXX_COMPILER /usr/local/arm-2013.11/bin/arm-none-linux-gnueabi-c++)

# where is the target environment 
SET(CMAKE_FIND_ROOT_PATH  /usr/local/arm-2013.11)

# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

注意:这是我第一次制作cmake文件。它并不保证是正确的。

您希望将/usr/local/arm-2013.11/bin/arm-none-linux-gnueabi-gcc替换为所选编译器的路径,以及/usr/local/arm-2013.11 / bin / arm-none-linux-gnueabi -c ++和/usr/local/arm-2013.11

我选择将此cmake文件保存为beaglebone.cmake

3。编译:

提取clapack-3.2.1-CMAKE.tgz和cd

编译:cmake -DCMAKE_TOOLCHAIN_FILE =〜/ Dropbox / workspaces / beaglebone / beaglebone.cmake
其中〜/ Dropbox / workspaces / beaglebone / beaglebone.cmake是你的cmake文件的路径。

出于某种原因,我得到了:

ds-mac-pro:clapack-3.2.1-CMAKE bunny$ make
Scanning dependencies of target arithchk
[  0%] Building C object F2CLIBS/libf2c/CMakeFiles/arithchk.dir/arithchk.c.o
Linking C executable arithchk
[  0%] Built target arithchk
[  0%] Generating arith.h
/bin/sh: arithchk: command not found
make[2]: *** [F2CLIBS/libf2c/arith.h] Error 127
make[1]: *** [F2CLIBS/libf2c/CMakeFiles/f2c.dir/all] Error 2
make: *** [all] Error 2

奇怪的是,再次运行make编译好了:

ds-mac-pro:clapack-3.2.1-CMAKE bunny$ make
[  0%] Built target arithchk
Scanning dependencies of target f2c
[  0%] Building C object F2CLIBS/libf2c/CMakeFiles/f2c.dir/f77vers.c.o
[  0%] Building C object F2CLIBS/libf2c/CMakeFiles/f2c.dir/i77vers.c.o
[  0%] Building C object F2CLIBS/libf2c/CMakeFiles/f2c.dir/main.c.o
[  0%] Building C object F2CLIBS/libf2c/CMakeFiles/f2c.dir/s_rnge.c.o

...

[100%] Building C object TESTING/EIG/CMakeFiles/xeigtstz.dir/xerbla.c.o
[100%] Building C object TESTING/EIG/CMakeFiles/xeigtstz.dir/xlaenv.c.o
[100%] Building C object TESTING/EIG/CMakeFiles/xeigtstz.dir/chkxer.c.o
[100%] Building C object TESTING/EIG/CMakeFiles/xeigtstz.dir/__/__/INSTALL/dsecnd.c.o
Linking C executable xeigtstz
[100%] Built target xeigtstz

4。复制(安装):

find . | grep \.a$

返回

./BLAS/SRC/libblas.a
./F2CLIBS/libf2c/libf2c.a
./SRC/liblapack.a
./TESTING/MATGEN/libtmglib.a

cp libblas.a libf2c.a和liblapack.a到你最喜欢的库文件夹。我发了/usr/local/armadillo-4.300.3/lib

必需:

1。复制包括:

犰狳不需要编译。我没有运行任何基准来验证,但似乎使用LAPACK和BLAS在Armadillo的未编译副本中通过在代码中使用#define工作正常。代码示例稍后。

提取armadillo-4.300.3.tar.gz

(可选)cp armadillo-4.300.3 / include / /usr/local/armadillo-4.300.3/include
当然,用您选择的路径替换/usr/local/armadillo-4.300.3/include

2。设置GCC使用Armadillo:

我正在使用Eclipse和C / C ++交叉编译器支持插件(帮助菜单 - &gt;安装新软件......),但这些说明很容易转换为cli或其他IDE。

在项目属性窗口中:C / C ++ Build - &gt;设置

Cross G ++编译器 - &gt;包括 - &gt;包含路径(-I)

单击+添加包含。我的包含路径是:/usr/local/armadillo-4.300.3/include

3。可选 - 设置GCC以使用已编译的库:

Cross G ++ Linker - &gt;图书馆 - &gt;

图书馆(-l)

LAPACK
F2C
blas

图书馆搜索路径(-L)

单击+添加路径。我的路径是:/usr/local/armadillo-4.300.3/lib

3。代码示例:

在cpp文件中尝试:

#include <armadillo>
using namespace arma;

mat A = randu<mat>(4,5);
mat B = randu<mat>(4,5);

std::cout << A*B.t() << std::endl;

成功! :d

某些功能Armadillo不直接支持,仅适用于已编译的库。您可以通过运行如下的简单测试来测试库是否已编译并正常工作:

#define ARMA_DONT_USE_WRAPPER
#define ARMA_USE_LAPACK
#define ARMA_USE_BLAS
#include <armadillo>
using namespace arma;

mat    A = randu<mat>(5,5);
double x = det(A);

std::cout << x << std::endl;