2015-05-08 2 views
1

Я использую Eigen3 на скрещенном скомпилированном программном обеспечении, используя arm-linux-gnueabihf-g ++ (gcc версия 4.8 от Linaro). Целевая платформа - это duovero от gumstix с использованием дистрибутива Poky - ARMv7. Когда я запускаю программу с кодом Eigen, я получаю действительно странные значения на объектах Eigen (см. Пример вывода в конце этого сообщения).Собственные векторы, не инициализированные при скрещивании для ARM

Я попытался отключить векторизации, я играл со всеми этими флагами

-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-аби = мягкий я получаю эту ошибку

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.

Когда я связываю статически мой код работает хорошо (даже если кросс-компилятор предназначен для жесткого поплавка, это работает, потому что на оборудовании фактически есть FPU, даже если изображение настроено для soft fp). Следующее, что я сделал, это найти кросс-компилятор, который способен делать softfp, и он также работал, когда я добавил флаг. Я загрузил его с https://launchpad.net/linaro-toolchain-binaries/+milestone/2012.04.

Я предполагаю, что мой следующий шаг состоит в том, чтобы скомпилировать изображение poky для duovero, которое может делать жесткие поплавки. Кто-нибудь сделал это?

окончательное обновление: Я на самом деле только что собрали последнее убогое изображение из Yocto (убогая 1.7) для duovero с помощью этих инструкций https://github.com/gumstix/yocto-manifest

и понял, что эта сборка использует жесткий FP. Теперь мой кросс-компилятор (arm-linux-gnueabihf-g ++) и цель имеют одинаковую конфигурацию с плавающей запятой, а мой код с Eigen и все остальное работает отлично! Счастливый! :)

+0

Это, конечно, пахнет проблемой с плавающей ABI (я бы даже не исключал, что некоторые изворотливые «отлично работают на x86», кастинг в коде библиотеки) - в «играх с этими флагами», вы хотите сказать, что у вас есть явно пробовал '-mfloat-abi = soft'? Весьма вероятно, что кросс-компиляторы могут быть настроены с разными значениями по умолчанию из собственного, поэтому вы не можете ожидать, что параметр _absence_ будет подразумевать последовательное поведение. – Notlikethat

+0

Когда я добавляю -mfloat-abi = soft, я получаю эту ошибку: ld.exe: error: testingEigen использует аргументы регистра VFP, main.obj не делает (я отредактировал исходный вопрос и добавил полный вывод, который я получаю от компилятора). В настоящий момент мой кросс-компилятор, похоже, настроен только на жесткий флоат. Требует ли Eigen soft-float работать? – spacemig

+0

Добавьте флаг '-mfloat-abi = soft' в флаги компоновщика в дополнение к флагам компилятора. –

ответ

2

Проблема в том, что у вас есть soft-float libstdC++ (и друзья) на устройстве.

Рассмотрите безобидную функцию, такую ​​как std::ostream::operator<<(float) - при перекрестном компиляции с помощью инструментальной привязки с твердым поплавком вы генерируете код, который будет передавать поплавок функции в регистр FPU. Статический компоновщик знает достаточно, чтобы дважды проверить, что это соответствует библиотекам, на которые он ссылается (жестко-плавающие в комплекте с самой кросс-цепочкой). Затем вы берете этот двоичный код и запускаете его на устройстве ...

Динамический компоновщик, будучи менее умным, просто хочет убедиться, что любой найденный libstdC++ предоставляет символы, которые запрашивает программа.Он находит одну из подобных версий, которая соответствует этому счету, поэтому все кажется хорошим. Кроме того, теперь у вас есть ситуация, когда ваш код передает аргументы float библиотечным функциям в регистры FPU, но функции библиотеки (будучи soft-float) ожидают своих аргументов float в регистре общего назначения, поэтому они находят неинициализированный барахл.

Лучше всего сделать это, чтобы избежать «ссылки против одной библиотеки, работать против другого» несоответствия целиком, для которой есть 3 разумные варианты, примерно в порядке убывания степени тяжести:

  1. Link статический, когда вы перекрестно скомпилируете.
  2. Поместите библиотеки жестких плавающих кросс-инструментов в файловую систему устройства, где вы можете найти их с помощью кросс-скомпилированных программ (возможно, прибегая к LD_LIBRARY_PATH) - очевидно, вы не можете просто заменить существующие библиотеки или получить обратную ABI несоответствие для остальных установленных программ.
  3. Скопируйте системные библиотеки с устройства на свой хост-компьютер, чтобы вы могли указать на них сшивающий агент вместо своих объединенных библиотек и перекрестно скомпилировать с помощью --mfloat-abi=soft.

Обычно я предлагаю вариант 3 в качестве общего случая, однако hard-float имеет некоторое преимущество в производительности, поэтому для кода с плавающей запятой, так что, возможно, стоит потратить немного усилий на то, чтобы получить это работать.

Обратите внимание, что в то время как какой-то жесткий поплавок (то есть «рука-линукс-gnueabi ВЧ -») кросс-компилированные инструменты также включают библиотеки мягкого поплавка через мультибиблиотечность, другие (например, те, которые я использую Линаро) либо не , или использовать их только для определенных комбинаций опций, представляющих древние цели, которых вы, вероятно, не хотите. Если вы сделал есть подходящий мультибиблиотечные набор инструментов, это то, что @ предложение TurboJ в комментариях о - используя arm-linux-gnueabihf-gcc в качестве команды ссылки (неarm-linux-gnueabihf-ld) с --mfloat-abi=soft указанной бы сказать ему, чтобы связать против мягкого флоат версий его библиотек, если он поддерживает это.