Кросс-компиляция С++, Qt приложений для Raspberry Pi

  • Автор
Поскольку вычислительные мощности Raspberry Pi достаточно слабы, то компиляция приложений прямо на плате может оказаться очень длительным процессом, особенно если это касается каких-то сложных приложений, а не элементарных Hello World'ов.

Намного удобнее разрабатывать и компилировать приложения на мощном стационарном компьютере. Так как процессоры обычных компьютеров и ноутбуков чаще всего имеют архитектуру x86, которая отличается от архитектуры ARM процессора Raspberry Pi, то просто скомпилированное и работающее на компьютере приложение при копировании на Raspberry Pi работать не будет.  

Чтобы собрать приложение на своём стационарном компьютере или ноутбуке для Raspberry Pi нужно скачать и настроить специальный инструментарий (toolchain), который включает в себя ARM-компилятор и некоторые библиотеки, скомпилированные для целевой ARM-платформы (например glibc).

Далее будет описано, как наиболее просто заполучить такой инструментарий.


Здесь нам отлично поможет Buildroot.  Это  ПО для сборки кастомизированных Linux дистрибутивов для embedded-систем. Как это работает?Скачивается  Buildroot, запускается его конфигуратор, где выбирается тип процессора, тулчейн для кросс-компиляции, набор библиотек и программ, которые необходимо включить в дистрибутив, версию ядра и т.д. Далее нужно закрыть конфигуратор и вбить в консоли команду make. После этого buildroot начнёт скачивать всё, что необходимо, компилировать¸ применять всякие патчи (процесс длительный, занимает несколько часов). На выходе получим образ ядра, загрузчик и корневую файловую систему.И в качестве бонуса тулчейн для кросс-компиляции, который можно использовать для сборки своих программ.

Разработчики Buildroot включают в программу конфигурации для различных популярных платформ, у меня стоит версия Buildroot от 08.12, там ещё нет официальной конфигурации для Raspberry Pi(может в декабрьской версии что-то появилось, не проверял). В Интернете можно найти несколько конфигураций Buildroot'а, заточенных для работы с Raspberry Pi от энтузиастов. Мне больше всего понравился http://bsquask.com/. Работа с ним строится следующим образом
1. Скачиваем Bsquask с сайта разработчика. git clone git://github.com/nezticle/RaspberryPi-BuildRoot.git BuildRoot

2.  Создаём папку, в которую Buildroot будет собирать новый дистрибутив и всё необходимое:
export BSQUASK_DIR=/opt/bsquask
mkdir -p $BSQUASK_DIR


3. Заходим в папку с Buildroot'ом, скаченную в шаге №1. Выполняем команду make raspberrypi_defconfig O=$BSQUASK_DIR
Она указывает Buildroot'у, что нужно использовать файл конфигурации "raspberrypi_defconfig", а сборку производить в каталог BSQUASK_DIR, заданный в шаге 2.
Можно также выполнить команду make xconfig, чтобы посмотреть, что из себя представляет конфигуратор BuildRoot'а и внести свои коррективы. 

4. Заходим в BSQUASK_DIR и отдаём команду на начало сборки. Процесс займёт несколько часов.
cd $BSQUASK_DIR
make
  Когда процесс сборки завершится, в папке BSQUASK_DIR/images появятся архив с загрузчиком (boot.tar.gz) и архив с корневой файловой системой (rootfs.tar.gz), которые можно записать на подготовленную SD-карту и использовать на Raspberry Pi:
mount /dev/sd[x]1 /media/BOOT 
mount /dev/sd[x]2 /media/rootfs
tar -zxvf boot.tar.gz -C /media/BOOT
sudo tar -zxvf rootfs.tar.gz -C /media/rootfs


Важно, чтобы при распаковке на SD-карту архива с корневой файловой системой у вас были права пользователя root, иначе при загрузке возможны проблемы 
На SD-карте должно быть два раздела - FAT32 для загрузчика и ядра и ext для корневой файловой системы. 

Подготовить карту можно скриптом mkcard (http://downloads.angstrom-distribution.org/demo/beagleboard/mkcard.txt): 

$ chmod +x mkcard.txt //делаем скаченный скрипт исполняемым
$ ./mkcard.txt /dev/sdx //где x - буква, соответствующая SD-карте. Это можно выяснить,вставив карту и выполнив команду dmesg | tail. В выводе должна содержаться информация об обнаруженном устройстве. Моя монтируется как sdc


После подготовки SD-карты и записи на неё загрузчика и корневой файловой системы, её можно использовать в Raspberry Pi. Логин/пароль для входа после загрузки: root/root

Использование средств для кросс-компиляции, сгенерированных Buildroot'ом
В папке $BSQUASK_DIR/host содержатся все необходимые инструменты для кросс-компиляции. Чтобы воспользоваться arm компилятором нужно добавить папку $BSQUASK_DIR/host/usr/bin в переменную окружения PATH: export PATH=$BSQUASK_HOST_DIR/usr/bin:$PATH

Теперь пробуем скомпилировать простое приложение на С для Raspberry Pi. Исходный код программы hello.c:
#include  'stdio.h'
int main()
{
printf ("Hello World!\n");
return 0;
}


Компилируем: arm-raspberrypi-linux-gnueabi-gcc -o hello_app hello.c

Получившийся файл hello_app можно скопировать на Raspberry Pi и запустить

Аналогично можно компилировать и Qt приложения:
$BSQUASK_DIR/host/usr/bin/qmake yourproject.pro
make


В BSQUASK включена 5-ая версия Qt. Несмотря на то, что разработчиками Qt было заявлено, что она полностью совместима с 4-ой, на практике всё не так гладко. Так например из Qt5 модуль Phonon был полностью выпилен и заменён на QtMultimedia. Наверняка и ещё где есть несовместимости. Рассмотрим, как создать новый профиль в Qt Creator'е для создания Qt приложения для Raspberry Pi.  Потребуется последняя версия Qt Creator'а (у меня стоит 2.6.1). http://qt.digia.com/Product/Developer-Tools/
1. В верхнем меню: Инструменты->Параметры. В левой колонке выбираем "Сборка и запуск", в правой колонке вкладка "Профили Qt", нажимаем добавить, указываем путь до qmake. Либо "$BSQUASK_DIR/host/usr/bin/qmake", либо "$BSQUASK_DIR/build/qtbase-5.0.0/bin/qmake"
2. Переходим во вкладку "Инструментарии", добавляем новый. Название: Raspberry, sysroot: BSQUASK_DIR/host/usr/arm-unknown-linux-gnueabi/sysroot, профиль Qt - выбрать тот, который был создан в шаге 1.

После этого приложения Qt для Raspberry Pi можно будет компилировать прямо в QtCreator'е.  Для этого в нижнем левом углу нужно нажать на картинку с компьютером и выбрать профиль Raspberry

Приложения Qt, скомпилированные данным способом мне удалось запустить только в дистрибутиве, собранном Buildroot'ом.  О том, как сделать так, чтобы работало и в Raspbian'e напишу в ближайшее время

Не люблю Android

Комментарии:

RomanNV5
Спасибо! Ценная информация.
А как быть со специфическими для ARM библиотеками?
Как их подключить к QT на PC, чтобы их можно было использовать в своих проектах?
Mike3
А в чём проблема? в .pro файле добавляем
INCLUDEPATH += путь_к_хедеру_mylib
LIBS += -Lпуть_к_библиотеке -lmylib
В .cpp файле:
#include <mylib.h>
Sensor772
Спасибо за хорошую статью!

Есть проблема:
При попытке добавить профиль qt "$BSQUASK_DIR/host/usr/bin/qmake", либо "$BSQUASK_DIR/build/qtbase-5.0.0/bin/qmake" qtcreator выдаёт сообщение: "Умолчальная символьная ссылка на mkspec повреждена".
Есть варианты решения проблемы?
Mike3
Какая версия Qt Creator'а установлена?
Нужно, чтобы была не ниже 2.6.1
Mike3
Папку $BSQUASK_DIR/build/qtbase-5.0.0/mkspecs нужно скопировать в sysroot (t: BSQUASK_DIR/host/usr/arm-unknown-linux-gnueabi/sysroot), если её там нет.
Sensor772
Спасибо, проблема решена!
Sensor772
Не получается найти в собранном дистрибутиве ни одного компилятора..
Скажите, пожалуйста, в собранном дистрибутиве присутствует какой-либо менеджер пакетов? Если "да", то какие репозитории доступны для скачивания пакетов?
Salamandra11
У меня есть проблемка. Наткнулся на эту статью. Написана отлично, однако есть пару замечаний.

Какая хостовая ОС использовалась для всех этих манипуляций?
Также есть проблема лично у меня, может кто поможет:
использую Centos 6.4 x64 на Hyper-V. Всё что нужно поставил: Denelopment Tools, texinfo, ncurses-devel, hg. Далее запускаю make menuconfig, ничего не меняю, создаётся конфиг - запускаю make, жду и через минут пять получаю вот такую неприятность:

Распознаётся bsquask.com... 176.58.100.20
Устанавливается соединение с bsquask.com|176.58.100.20|:80... соединение установлено.
Запрос HTTP послан, ожидается ответ... 200 OK
Длина: 43734928 (42M) [application/x-bzip2]
Saving to: «/home/BuildRoot/dl/arm-raspberrypi-linux-gnueabi.tar.bz2.tmp»

100%[======================================>] 43 734 928 342K/s в 3m 45s

2013-10-23 17:55:07 (190 KB/s) - «/home/BuildRoot/dl/arm-raspberrypi-linux-gnueabi.tar.bz2.tmp» saved [43734928/43734928]

mkdir -p /home/bsquask/host/opt/ext-toolchain
bzcat /home/BuildRoot/dl/arm-raspberrypi-linux-gnueabi.tar.bz2 | \
tar --strip-components=1 --exclude='usr/lib/locale/*' -C /home/bsquask/host/opt/ext-toolchain -xf -
>>> Checking external toolchain settings
Cannot execute cross-compiler '/home/bsquask/host/opt/ext-toolchain/bin/arm-raspberrypi-linux-gnueabi-gcc'
make[1]: *** [/home/bsquask/stamps/ext-toolchain-checked] Ошибка 1
make: *** [all] Ошибка 2


В чем может быть причина?
M_C
Надо запускать не "make menuconfig", а "make raspberrypi_defconfig", чтобы Buildroot использовал файл конфигурации для Raspberry Pi, иначе будут использованы дефолтные настройки из файла .config в корне Buildroot'а
messad_el
А у меня та же проблема что и у товарища выше при том что я пишу " make raspberrypi_defconfig O=$BSQUASK_DIR

" вроде как и указано в этой статье…
messad_el
Cannot execute cross-compiler '/home/bsquask/host/opt/ext-toolchain/bin/arm-raspberrypi-linux-gnueabi-gcc'

Потому что его там нету. А вот почему нету непонятно и qmake тоже нет там где он должен лежать.
meaning
Во время make отказало загружать архив libnih-1.0.3.tar.gz с launchpad.net — из-за сертификата. Скачал вручную. Архив закинул в /BuildRoot/dl(распаковывать архив в /opt/bsquask/bin не надо). После команды make поехало дальше.
vash_sa
Все эта статья уже не работает!!!
vash_sa
Можно такую статью повторить. С рабочим примером, пожалуйста.
M_C
Вы бы конкретно написали, на каком шаге ошибки возникают

Для написания комментариев необходимо зарегистрироваться