Pull to refresh

Хак Bada IDE: собираем как хотим

Reading time4 min
Views2.4K
Привет!
Эта небольшая статья адресована разработчикам приложений под мобильную платформу Samsung Bada, которые не желают мириться с мыслью, что Samsung «знает лучше, что надо», а также людям, занимающимся сборкой кода под ARM с помощью GNU Compiler Collection.

Думаю, многие замечали, что при сборке проекта в Target-Release или Target-Debug пишется лог наподобие

arm-samsung-nucleuseabi-g++ -DSHP -I"D:/Work/Bada/1.2.1/include" -I"???/inc" -Os -Wall -E -fpic -fshort-wchar -mcpu=cortex-a8 -mfpu=vfpv3 -mfloat-abi=hard -mlittle-endian -mthumb-interwork -o"???/Target-Release/dirent.i" "../src/bada/dirent.cpp"
'Finished building: ../src/bada/dirent.cpp'

Нас будут интересовать флаги сборки, т.е. часть

-Os -Wall -E -fpic -fshort-wchar -mcpu=cortex-a8 -mfpu=vfpv3 -mfloat-abi=hard -mlittle-endian -mthumb-interwork

В свойствах проекта можно добавлять свои флаги, но вот незадача: они все приписываются слева, а кусок

-fpic -fshort-wchar -mcpu=cortex-a8 -mfpu=vfpv3 -mfloat-abi=hard -mlittle-endian -mthumb-interwork

вообще статичный и всегда дописывается справа, и в IDE про него ни слова. Более того, опция "-Os" — неизменяемая в свойствах проекта («серая»). Поясню, что происходит.
  • -Os — применяются только оптимизации, не увеличивающие размер объектника
  • -fpic — сборка по Position Independant Code relocation model. Напоминаю, что все результаты (т.н. артефакты) сборки на Bada Toolchain — динамические библиотеки (shared library). Для кого это новость — можете также посмотреть на типичный код <ИмяПроекта>Entry.cpp:

    _EXPORT_ int OspMain(int argc, char *pArgv[])

    Если скакнуть на определение _EXPORT_, то увидим (FBaseConfig.h):

    #if defined(_WIN32)             // MS Compiler & MinGW GCC<br/>
    #   define _EXPORT_ __declspec(dllexport)<br/>
    #elif defined(__GNUG__)         // GCC<br/>
    #   define _EXPORT_ __attribute__((visibility("default")))<br/>
    #elif defined(__ARMCC_VERSION)  // ARM Compiler (RVCT 3.1)<br/>
    # define _EXPORT_<br/>
    #else<br/>
    # define _EXPORT_<br/>
    #endif

    Это я все для чего? Так вот, PIC — надежная, но слегка медленная модель. Тем более, учитывая, что в Bada все приложения находятся в своих песочницах и не могут делить общие динамические библиотеки — бессмысленно использовать PIC. К сожалению, без этого флага сборка проекта может падать на этапе линковки динамической библиотеки (и падает, я проверял), т.к. ld (в исполнении arm-samsung-nucleusabi-ld) не умеет линковать в некоторых случаях, поэтому корейцы из Samsung зашили этот флаг внутрь. Из-за недоработки в GCC 4.x компилятор делает релок R_ARM_MOVW_ABS_NC, который не любят в binutils. Вот если бы сборка была с помощью LLVM… Я что-то увлекся. В общем, в данной ситуации без -fPIC не обойтись.
  • -mfpu=vfpv3 — версия модели вычислений с плавающей точкой
  • -mfloat-abi=hard — использовать только «железные» операции с плавающей точкой. Вообще говоря, если в коде встречается вызов функции с плавающей точкой, которой нет в ARM FPU, то компиляция упадет, но это очень маловероятно.
  • -mlittle-endian — непонятно зачем, т.к. про Cortex-A8 и так известно, что он little endian.
  • -mthumb-interwork — возможность безопасно сочетать в одном исполняемом файле код как ARM, так и Thumb. Как известно, ARM архитектура хороша помимо всего прочего еще и тем, что содержит набор 16-битных инструкций Thumb. Смысл в том, что одна ARM инструкция занимает 32 бита, а Thumb инструкция — в два раза меньше. Итого имеем сокращение размера результирующего кода в два раза (теоретически). Практически — почти в два раза (там есть накладные расходы в виде дополнительных операций и еще кое-что). По умолчанию сборка проходит в ARM код, в Thumb код программа может вообще не скомпилироваться (кто там например любит «оптимизированные» ассемблерные вставки? Наши компиляторщики кроют таких матом), в прошивке Samsung Wave скорее всего код Thumb, и корейцы перестраховались. В качестве минуса — размер объектников немного растет из-за дополнительных инструкций сопряжения.


Итак, видим следующую несправедливость:
  1. Не всегда оптимизация на размер исполняемого файла предпочтительней (особенно для системных, алгоритмических вещей!)
  2. mfpu=vfpv3 это, конечно, хорошо, но у кортекса есть NEON
  3. Проекты собираются в набор инструкций ARM вместо «няшного» Thumb


Позицию Samsung можно понять: шаловливые руки, изменив упомянутые флаги, запросто могут запороть сборку проекта, а корейской службе поддержки потом им доказывать, кто они на самом деле. Однако, мы с вами знаем, что делаем. Сможем ли мы исправить ситуацию? Да!

Обратим внимание на файл <корень Bada SDK>/IDE/buildoptions.xml. Там как раз и содержится набор флагов, который нельзя изменить обычным человеческим способом через IDE. После редактирования этого файла, не забудьте перезапустить Eclipse. Оттягиваемся по-полной:

<comp>-fpic -mthumb -fshort-wchar -O2 -mcpu=cortex-a8 -mfpu=vfpv3 -mfloat-abi=hard</comp>

-mthumb заставляет собирать Thumb код, -O2 нормально оптимизирует программу, а теперь уже бессмысленный -mthumb-interwork убран. Я проверил работу при таких флагах на множестве программ, и все они работают как надо. Замечу две вещи:
  1. Если сделать -mfpu=neon, приложения падают при запуске на устройстве. Почему — не ясно, я этот момент исследую. На работе на тестовых бордах так много раз делал.
  2. -mthumb-interwork возможно, все-таки будет нужен в некоторых частных случаях. Я прогнал тесты — без него отлично все работает.

Что же мы видим во флагах сборки на устройства Bada 1.1 (линейка бюджетных Wave, вроде 52x)?

<comp>-fpic -fshort-wchar -mcpu=arm9 -mfloat-abi=soft -mlittle-endian -mthumb-interwork</comp>

Во-первых, в глаза бросается убогий процессор, о котором вообще не написано в спецификации на официальном сайте Samsung, а также -mfloat-abi=soft, из-за которого FPU вообще не используется. В спецификации ARM9 на arm.com указано, что FPU действительно опционален. У меня этих устройств нет, и я не могу точно сказать, хорошая ли идея поменять этот флаг на -mfloat-abi=softfp или -mfloat-abi=hard. Зато я снова рекомендую добавить -mthumb.

Дам совет тем, у которых много вычислений с плавающей точкой: добавьте в флаги проекта (обычным способом) флаги -funsafe-math-optimizations -ffast-math. Не пожалеете.

Напоследок ссылка на все флаги GCC, специфичные для ARM.

Спасибо за внимание, удачной вам разработки!
Tags:
Hubs:
+6
Comments5

Articles