Введение
На сегодняшний день в сети есть достаточно много мануалов сборки qt4.8 для Raspberry PI или BeagleBone Black, но они уже безвозвратно устарели (изменились опции для ./configure).
В сети уже есть несколько инструкций как собирать qt5.2 и qt5.5, но без дополнительных тайных знаний вы можете потратить много времени и нервов, так ничего и не добившись.
За основу я взял статью Simon Stürz : Crosscompile Qt 5.2.1 for the Beaglebone Black и скрипт автоматической сборки, делающий всю работу за вас.
Здесь же не только перевод этой статьи, но и важные ньюансы и пояснения, позволяющие вам не тратить много времени на набивании шишек.
Ставим линукс
Есть куча примеров кросс-компиляции под windows, но если вы хотите сэкономить себе время и нервы, используйте Linux. Позже, когда вы разберётесь как всё работает на линуксе, можно уже будет попробовать собрать и под виндой.
Ставить линукс второй операционной системой вовсе не обязательно, вы можете запустить его на виртуальной машине, например при помощи VirtualBox. Такой способ будет даже удобнее: пока идёт сборка qt можно спокойно работать на основной машине.
Ставим Ubuntu 14.04. Если вы ставите Linux на виртуалку, то настоятельно рекомендую именно этот дистрибутив или другой хорошо распространнённый. Посколько в других дистрибутивах могут отличаться названия пакетов.
Подготовка rootfs
Для успешной сборки нам понадобится образ файловой системы с вашего работающего Beaglebone. Это нужно, чтобы слинковаться с конкретными библиотеками, установленными на вашу систему.
Важно: для образа вашей файловой системы используйте SD-карту. Файловую систему на карте памяти намного проще скопировать на компьютер. Делается это через обычный кардридер. Сложнее скопировать файловую систему на внутренней памяти BeagleBone: для этого придётся разбираться с копирование файлов по SSH.
В качестве дистрибутива для BeagleBone я использую Debian 7.9.
Установка обновлений (выполняем на BeagleBone)
Для начала, установим системные обновления:
$ sudo apt-get upgrade
Установка зависимостей
Все библиотеки и include-файлы, необходимые для сборки Qt будут браться не с вашего компьютера, а с rootfs BeagleBone. Поэтому, необходимо поставить туда все необходимые пакеты.
Основные зависимости:
Зависимости для libxcb:
Зависимости для QtMultimedia:
Зависимости для QtWebEngine:
Зависимости для QtConnectivity (поддержка Bluetooth):
Работы с шиной I2C (если вы не знаете что это такое, то скорее всего вам это не нужно):
Подготовка директории на диске
Прежде чем копировать образ файловой системы с BeagleBone на компьютер, нужно подготовить директорию.
Важно: директория на вашей TARGET-машине будет в точности соответствовать директории на HOST-машине (BeagleBone). Т.е если вы решите производить сборку в /home/vasya/Projects/build. То все пути будут завязаны именно на эту директорию. Настоятельно рекомендуется указывать пути не зависящие от конкретного пользователя. Например /opt/qt-beaglebone/.
Создаём директорию под рутом (т.к. обычный пользователь не может писать в корень диска) и меняем владельца на текущего пользователя:
$ sudo mkdir /opt/qt-beaglebone/
$ sudo chown $USER /opt/qt-beaglebone/
Создание снимка rootfs
Извлекаем карту памяти из BeagleBone, вставляем её в кард-ридер своего компьютера.
Затем монтируем файловую систему sd-карты (под Ubuntu файловая система монтируется сама) и заходим в корень смонтированной файловой системы.
Там выполняем:
$ sudo chown $USER /opt/qt-beaglebone/rootfs.tar.bz2
Сборка QT для кросс-компиляции
Подготовка машины для сборки
Ставим необходимые пакеты:
Скрипт сборки Qt
Можно было бы самим скачать пакет qt-everywhere-opensource. Наложить на него патч для поддержки BeagleBone и компилятора gcc-linaro-arm-linux-gnueabihf, но есть уже готовый скрипт от товарища Simon Stürz. С 2015 года пути немного поменялись и скрипт безнадёжно устарел. Пришлось его немного допилить. Новый скрипт можно взять здесь.
Если у вас есть rootfs со всеми необходимыми библиотеками, то остальное скрипт сделает за вас. Нужно только его скачать и запустить:
$ wget http://guh.guru/downloads/scripts/crosscompile-Qt_5.2.1-beaglebone-black.sh
$ chmod +x crosscompile-Qt_5.2.1-beaglebone-black.sh
$ ./crosscompile-Qt_5.2.1-beaglebone-black.sh
Скрипт распакует архив с rootfs (лучше не удалять исходный архив. Если что-то пойдёт не так вы всегда сможете вернутся к исходной версии). Далее скрипт скачает дистрибутив Qt-5.2.1, компилятор и начнёт сборку.
Собранный Qt для ARM
Собранный Qt будет лежать на распакованном образе rootfs в директории /opt/qt-beaglebone/. Полный путь на вашей HOST-машине будет: /opt/qt-beaglebone/rootfs/opt/qt-beaglebone/Qt-5.2.1/.
qmake для кросс-компиляции
qmake для кросс-компиляции будет находиться здесь: /opt/qt-beaglebone/Qt-5.2.1
Компилятор будет находиться здесь: /opt/qt-beaglebone/gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux/bin
Кросс-компиляция Qt-приложений под ARM
Кросс компиляции Qt-приложений под ARM будет посвещена следующая статья.
Возможные проблемы
1. gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux/bin/arm-linux-gnueabihf-g++: error while loading shared libraries: libstdc++.so.6
Решение: скорее всего не хватает пакетов на вашей сборочной системе:
2. arm-linux-gnueabihf/libz.a: error adding symbols: Bad value
Вместо libz.so тут может быть любая библиотека. Проблема в то, что libz.so не найден на вашей файловой системе. И компилятор пытается использовать вместо динамической либы libz.so статическую libz.a, которой тоже нет на вашей rootfs. Решение: идём в директорию rootfs и создаём libz.so как ссылку на существующую библиотеку (в моём случае это libz.so.1.2.7).
$cd /opt/qt-beaglebone/rootfs/usr/lib/arm-linux-gnueabihf/ $ln -s libz.so.1.2.7 libz.so
Скорее всего тоже самое придётся проделать и для других библиотек. Мне пришлось повторить это действие для libm.so, libdl.so. Притом в директориях /lib/arm-linux-gnueabihf и /usr/lib/arm-linux-gnueabihf
Внимание! Проверять нужно не только наличие библиотеки *.so но и куда ссылается символическая ссылка.
Например:
$ cd /opt/qt-beaglebone/rootfs/usr/lib/arm-linux-gnueabihf/ $ ls -l |grep libdl
выводит
-rw-r--r-- 1 root root 9022 фев 12 2016 libdl.a
lrwxrwxrwx 1 root root 35 фев 12 2016 libdl.so -> /lib/arm-linux-gnueabihf/libdl.so.2
Т.е. символическая ссылка с абсолютными путями и ссылается не на библиотеку для Beaglebone, а на библиотеку для x86 процессора, на котором мы выполняем сборку.
Исправляем:
$ cd /opt/qt-beaglebone/rootfs/usr/lib/arm-linux-gnueabihf/
$ rm -rf libdl.so
$ ln -s ../../../lib/arm-linux-gnueabihf/libdl-2.13.so libdl.so
3. crosscompile-Qt_5.2.1-beaglebone-black.sh: /opt/qt-beaglebone/Qt-5.2.1/bin/qmake: not found
Найдя директорию Qt-5.2.1, скрипт считает, что всё уже собрано, и пытается запустить qmake, который не собрался из-за ошибки. Самый простой способ будет - удалить директорию Qt-5.2.1.
4. undefined reference to `clock_gettime`
Проблема линковки в librt.so. Для неё также нужно создать символическую ссылку как для libz.so, обозначенной во второй проблеме.
5. undefined reference to `__dlopen'
Та же самая проблема, что и проблема 2: /usr/lib/arm-linux-gnueabihf/libdl.so отсутствует, либо символическая ссылка ведёт не туда.
Исправляем:
$ cd /opt/qt-beaglebone/rootfs/usr/lib/arm-linux-gnueabihf/
$ rm -rf libdl.so
$ ln -s ../../../lib/arm-linux-gnueabihf/libdl-2.13.so
То же самое нужно сделать и для libm.so.
Если и это не помогает, то удаляем/переименовываем статическую библиотеку, чтобы компилятор начал использовать динамическую:
$ cd /opt/qt-beaglebone/rootfs/usr/lib/arm-linux-gnueabihf/
$ sudo mv libdl.a old-libdl.a