对ARM进行交叉编译时,特征向量未初始化

时间:2015-05-08 22:04:57

标签: gcc arm cross-compiling eigen eigen3

我使用arm-linux-gnueabihf-g ++(来自Linaro的gcc版本4.8)在交叉编译的程序中使用Eigen3。目标平台是来自gumstix的duovero使用Poky发行版 - ARMv7。当我使用Eigen代码运行程序时,我在Eigen对象上得到了非常奇怪的值(请参阅本文末尾的输出示例)。

我试图关闭矢量化,我玩过所有这些旗帜

-marm 
-mcpu=cortex-a7
-mfpu=neon 
-mfloat-abi=hard 

但总是得到相同的行为。如果我在duovero上编译相同的代码,它可以正常工作(向量已正确初始化),但在交叉编译时则不行。我甚至从不同的主机(windows7和ubuntu 14.04)交叉编译。

知道为什么会这样吗?

这是我的简单程序(从评论中更新)

#include <iostream>
using namespace std;

#include <stdio.h>

#include <Eigen/Eigen>
#include <Eigen/Dense>
using namespace Eigen;

int main()
{
    cout << "Hello World!" << endl;
    int j =3;
    cout << j << endl << endl; // ok

    float k =4.2;
    cout << k << endl << endl; // not ok

    printf("%f\n\n", k ); // ok

    Vector3d test1;
    test1 << 1.2, 2.3, 3.4;
    cout << test1 << endl << endl; // not ok

    printf("%f\n\n", test1(0) ); // ok

    Vector3d test2(1,2,3);
    cout << test2 << endl; // not ok
    cout << test2(1) << endl << endl; // not ok

    printf("%f\n\n", test2(0) ); // ok

    cout << 0.5f << endl; // not ok
    printf("%f\n\n", 0.5f ); // ok

    return 0;
}

这是我得到的输出(更新)

Hello World!
3

0

4.200000

-1.24694e-06
-1.24695e-06
-1.24695e-06

1.200000

-1.24692e-06
-1.24692e-06
-1.24693e-06
3.8852e+68

1.000000

0
0.500000

编辑 当我添加标志:-mfloat-abi = soft时出现此错误

arm-linux-gnueabihf-g++ -c -mfloat-abi=soft -g -Wall -W -fPIE  -IC:\tmp\testingEigen -I. -IC:\COSMOS\source\thirdparty\arm\eigen3 -IC:\Qt\5.4\mingw491_32\mkspecs\linux-arm-gnueabihf-g++ -o main.obj C:\tmp\testingEigen\main.cpp
arm-linux-gnueabihf-g++  -o testingEigen main.obj    
c:/program files (x86)/linaro/gcc-linaro-arm-linux-gnueabihf-4.8-2014.01/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld.exe: error: testingEigen uses VFP register arguments, main.obj does not
makefile:79: recipe for target 'testingEigen' failed
c:/program files (x86)/linaro/gcc-linaro-arm-linux-gnueabihf-4.8-2014.01/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld.exe: failed to merge target specific data of file main.obj

更新 我尝试了Notlikethat建议的内容。测试了这些库(例如readelf -h /usr/lib/libstdc++.so.6.0.18),发现当前构建的是明确的软浮动ABI。

当我静态链接时,我的代码运行良好(即使交叉编译器用于硬浮动,这也可行,因为即使图像配置为软fp,硬件实际上也有FPU)。我接下来要做的是找到一个能够做softfp的交叉编译器,当我添加标志时它也能工作。我是从https://launchpad.net/linaro-toolchain-binaries/+milestone/2012.04下载的。

我想我的下一步是为duovero编制一个可以做硬浮动的poky图像。有没有人这样做过?

最终更新 我实际上只是使用这些说明从yocto(poky 1.7)为duovero编制了最新的poky图像https://github.com/gumstix/yocto-manifest

并意识到这个版本使用了硬fp。现在我的交叉编译器(arm-linux-gnueabihf-g ++)和目标具有相同的浮点配置和我的代码与Eigen和其他一切工作完美!快乐! :)

1 个答案:

答案 0 :(得分:2)

问题似乎是你在设备上有一个软浮动的libstdc ++(和朋友)。

考虑一个看似无害的函数,如std::ostream::operator<<(float) - 当您使用hard-float工具链进行交叉编译时,会生成将浮动函数传递给FPU寄存器中的函数的代码。静态链接器知道足以仔细检查它是否匹配它链接的库(与交叉工具链本身捆绑的硬浮点数)。然后你拿这个二进制文件并在设备上运行它......

动态链接器不那么聪明,只是要确保它找到的libstdc ++提供程序要求的符号。它找到了一个类似的版本,适合该法案,所以一切似乎都很好。除了现在你已经得到了你的代码将浮点参数传递给FPU寄存器中的库函数的情况,但是库函数(软浮点函数)期望它们在通用寄存器中的浮点数,所以它们找到未初始化的垃圾

最好的办法是避免与一个库相关联,与另一个库运行。完全不匹配,有3种合理的选择,严重程度大致递减:

  1. 交叉编译时静态链接。
  2. 将交叉工具链的硬浮动库放在设备的文件系统中,交叉编译的程序可以找到它们(可能需要使用LD_LIBRARY_PATH) - 显然你不能简单地替换它们现有的库或您获得的其他已安装程序的反向ABI不匹配。
  3. 将系统库从设备复制到主机上,这样您就可以将交叉链接指向它们而不是它的捆绑库,并与--mfloat-abi=soft进行交叉编译。
  4. 我通常会建议将选项3作为一般情况,但是对于浮点密集型代码而言,硬浮动确实有一些性能优势,因此获得它可能值得花一些时间。工作。

    请注意,虽然一些硬浮动(即&#34; arm-linux-gnueabi hf - &#34;)交叉工具链还包括通过multilib的软浮动库,其他(如#34; arm-linux-gnueabi hf - &#34;)我使用的Linaro(或者不是),或者只是为了代表古代目标的特定选项组合启用它们,这些选项可能是您不想要的。如果确实有一个合适的multilib工具链,那么@TurboJ在评论中的建议是什么 - 使用arm-linux-gnueabihf-gcc作为链接命令( not指定arm-linux-gnueabihf-ld --mfloat-abi=soft)会告诉它链接其库的soft-float版本(如果它支持的话)。