Одним из инструментов для создания приложений с графическим пользовательским интерфейсом является хорошо известный фреймворк Qt. Кроссплатформенность Qt позволяет нам успешно использовать его в том числе и для разработки на Raspberry Pi. Но здесь есть один нюанс, о котором мы и поговорим в этой статье.
В принципе, можно без проблем установить Qt Creator и сопутствующие библиотеки непосредственно на Raspberry. И, соответственно, на самой же плате и заниматься разработкой. Но! Компиляция требует достаточно серьезных мощностей, в связи с чем этот процесс на Raspberry будет занимать довольно продолжительное время, что, естественно, нежелательно.
Решение данной проблемы такое - разработка и дальнейшая компиляция выполняются на ПК, а уже готовое приложение загружается и используется на Raspberry Pi. Для реализации этого нам нужно будет кросс-компилировать Qt на хосте (ПК), чтобы затем можно было разворачивать и отлаживать приложения уже на плате. Итак, в отправной точке у нас в наличии:
- Raspberry Pi 4 с установленной Raspberry Pi OS.
- Хост - ПК с ОС Ubuntu 20.04 (моя версия на момент написания статьи).
- Подключение по SSH.
В дальнейшем часть команд будут выполняться на ПК, а часть - на Raspberry Pi, поэтому во избежание путаницы для каждой команды и каждого шага будем добавлять наглядные метки: [PC] или [Raspberry Pi].
Кросс-компиляция Qt.
Шаг 1. [Raspberry Pi]
Произведем необходимые настройки:
sudo raspi-config
Первым делом включаем поддержку OpenGL driver with fake KMS. Для этого переходим в Advanced Options - GL Driver:
И второй момент - настраиваем Raspberry Pi OS на загрузку без запуска графической оболочки. Идем в System Options - Boot / Auto Login:
Шаг 2. [Raspberry Pi]
Редактируем файл /etc/apt/sources.list, например, при помощи редактора nano:
sudo nano /etc/apt/sources.list
Нашей целью здесь является раскомментирование строки:
deb-src http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi
Шаг 3. [Raspberry Pi]
Обновляем систему и устанавливаем необходимые пакеты:
sudo apt-get update sudo apt-get upgrade sudo apt-get build-dep qt5-qmake sudo apt-get build-dep libqt5gui5 sudo apt-get build-dep libqt5webengine-data sudo apt-get build-dep libqt5webkit5 sudo apt-get install libudev-dev libinput-dev libts-dev libxcb-xinerama0-dev libxcb-xinerama0 gdbserver pkg-config mesa-utils libgles2-mesa-dev libdrm.dev libgbm.dev
Шаг 4. [Raspberry Pi]
Создаем на Raspberry Pi папку для пользователя pi для дальнейшего развертывания в ней Qt:
sudo mkdir /usr/local/qt sudo chown pi:pi /usr/local/qt
Шаг 5. [PC]
Теперь создаем папку на хосте и скачиваем тулчейн для кросс-компиляции:
mkdir ~/raspberrypi cd ~/raspberrypi wget https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz tar xf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
У меня 64-битная ОС, соответственно, версия - x86_64.
Шаг 6. [PC]
Создаем sysroot для кросс-компиляции под Raspberry Pi:
mkdir sysroot sysroot/usr sysroot/opt
Шаг 7. [PC]
Синхронизируем sysroot на ПК с Raspberry Pi:
rsync -avz pi@192.168.0.101:/lib sysroot rsync -avz pi@192.168.0.101:/usr/include sysroot/usr rsync -avz pi@192.168.0.101:/usr/lib sysroot/usr rsync -avz pi@192.168.0.101:/opt/vc sysroot/opt
Соответственно, здесь и далее имя пользователя (pi) и ip-адрес платы (192.168.0.101) нужно заменить на свои.
Шаг 8. [PC]
Заменяем символьные ссылки sysroot на относительные при помощи готового скрипта sysroot-relativelinks.py. Скачиваем скрипт и запускаем:
wget https://raw.githubusercontent.com/riscv/riscv-poky/master/scripts/sysroot-relativelinks.py chmod +x sysroot-relativelinks.py ./sysroot-relativelinks.py sysroot
Шаг 9. [PC]
Скачиваем исходники Qt. Будем использовать LTS версию 5.15.1:
git clone git://code.qt.io/qt/qtbase.git -b 5.15.1 cd qtbase
Шаг 10. [PC]
Выполняем конфигурацию перед сборкой. Для Raspberry Pi 4 аргументом -device будет linux-rasp-pi4-v3d-g++:
./configure -release -opengl es2 -eglfs -device linux-rasp-pi4-v3d-g++ -device-option CROSS_COMPILE=~/raspberrypi/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- -sysroot ~/raspberrypi/sysroot -prefix /usr/local/qt -extprefix ~/raspberrypi/qt -hostprefix ~/raspberrypi/host-qt -opensource -confirm-license -skip qtscript -skip qtwayland -skip qtwebengine -nomake tests -make libs -pkg-config -no-use-gold-linker -v -recheck
При успешном выполнении данного шага в консоли должны быть активированы следующие пункты:
При неудавшейся конфигурации или сборке не забываем выполнить полную очистку перед повторной попыткой:
git clean -dfx
Шаг 11. [PC]
Приготовления закончены, собираем:
make -j8 make install
Шаг 12. [PC]
Разворачиваем собранный Qt на Raspberry Pi:
cd ~/raspberrypi rsync -avz qt pi@192.168.0.101:/usr/local
И на этом процесс завершен 👍 Переходим к следующему аспекту - установке, запуску и настройке Qt Creator.
Qt Creator для Raspberry Pi.
Шаг 1. [PC]
Установка проста:
sudo apt install qtcreator
Шаг 2. [PC]
Добавляем устройство в Qt Creator. Переходим в меню Tools - Options, открываем раздел Devices и добавляем Generic Linux Device:
Здесь мы задали имя устройства, ip-адрес и имя пользователя. Кроме того, указываем приватный SSH-ключ для доступа к Raspberry Pi по SSH.
Шаг 3. [PC]
Идем в раздел Kits на вкладку Compilers и добавляем компиляторы для C и C++:
Шаг 4. [PC]
В том же разделе на вкладке Debuggers добавляем отладчик для работы с Raspberry. Но для этого предварительно устанавливаем:
sudo apt-get install gdb-multiarch
А затем уже возвращаемся в Debuggers:
Шаг 5. [PC]
Дальше по списку вкладка Qt Versions, где мы добавляем версию Qt:
Шаг 6. [PC]
И финишируем на вкладке Kits, добавив набор инструментов, которые мы будем использовать для Raspberry Pi. Собственно, систематизируем все, что мы добавили ранее:
Теперь при создании нового проекта будет доступен созданный набор, названный нами - Raspberry Pi. В общем-то, как раз и переходим к созданию тестового проекта.
Создание проекта.
Шаг 1. [PC]
Создаем проект и выбираем добавленный ранее набор инструментов:
Шаг 2. [PC]
В настройках проекта в .pro файле можно задать путь для установки приложения на Raspberry Pi. К примеру:
# Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /home/pi/Qt_Projects/$${TARGET} !isEmpty(target.path): INSTALLS += target
То есть в данном случае созданное приложение будет развернуто в папке /home/pi/Qt_Projects/ на Raspberry Pi.
Шаг 3. [PC]
Создаем простейшее приложение с одной кнопкой. По нажатию кнопки, а также в конструкторе и деструкторе MainWindow выдаем сообщение через qDebug().
Собираем приложение и разворачиваем на Raspberry Pi:
Итогом будет успешный запуск на Raspberry:
Собственно, цель достигнута. В завершение, разберем одну потенциальную проблему. При компиляции тестового проекта могут возникнуть ошибки вроде:
error: variable has incomplete type 'QApplication' error: unknown type name 'MainWindow'
Часто это связано с тем, что Ubuntu 20.04 по умолчанию использует clang-10. А Qt требует clang-8. Поэтому для устранения ошибок выполняем последовательно:
sudo apt install clang-8 sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-8 100 sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-8 100
Вот на этом точно все, спасибо за внимание и до скорого 🤝