Два года назад мы пытались использовать Raspberry Pi B+ для запуска нашей системы Умная остановка. В прошлый раз результат нас особо не вдохновил, и мы на какое-то время приостановили наши эксперименты. Но как известно время не стоит на месте, производители выпускают новые продукты. И мы решились повторить наш эксперимент уже на новой плате: Raspberry Pi 3 Model B. На этот раз мы решили не искать простых путей, и занялись кросс-компиляцией кросс-платформенного инструментария разработки ПО на языке программирования C++ QT 5.11 на Linux Ubuntu 17.10. Что из этого получилось можно прочитать под катом.
Обновлено для Qt 5.11 и Raspbian-2018-03-13 Stretch для Raspberry PI3 ModelB.
1. Первым делом необходимо скачать образ ОС для малинки, это будет raspbian и залить её на SD карточку, которая уже должна быть воткнута.
Bash Code:
mkdir ~/Projects/RaspberryPI cd ~/Projects/RaspberryPI wget https://downloads.raspberrypi.org/raspbian/images/raspbian-2018-03-14/2018-03-13-raspbian-stretch.zip unzip 2018-03-13-raspbian-stretch.zip sudo dd if=2018-03-13-raspbian-stretch.img of=/dev/mmcblk0 bs=4M sync
Что бы узнать адрес флэшки, наберите lsblk
Если так случалось, что нет картридера, то залить прошивку можно и на винде с помощью win32diskimager (запускать от рута)
2. Когда заливка завершиться, вытаскиваем СДшку и загружаем с неё малинку.
Теперь её немножко надо настроить, переходим Menu -> Preferences -> Raspberry Pi configuration
Жмём «expand filesyste», включаем «ssh», перезагружаемся.
Подключаемся к сети (можно по вафле), вбиваем в консольке (Menu->Accessories->Terminal) ifconfig, запоминаем айпишник, на этом пока что всё.
3. Приконнектимся к малинке по ssh, раскомментим получение исходников пакетов, установим нужные пакеты и создадим нужные папки
Bash Code:
IP=192.168.1.201 # айпишник малинки ssh pi@$IP #(пароль по дефолту "raspberry") sudo nano /etc/apt/sources.list #расскомментить строчку с deb-src sudo apt-get update sudo apt-get install -y libfontconfig1-dev libfreetype6-dev libx11-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libx11-xcb-dev libxcb-glx0-dev sudo apt-get install -y libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync1 libxcb-sync-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev libxcb-xinerama0-dev sudo mkdir /usr/local/qt5pi sudo chmod -R 777 /usr/local/qt5pi
4. Так, возвращаемся к хосту, качаем тулчейн:
Bash Code:
mkdir raspi cd raspi git clone https://github.com/raspberrypi/tools
4.1. После git clone https://github.com/raspberrypi/tools узнаем версию полученного компилятора например /opt/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc -v и видим что-то типа gcc версия 4.8.3 20140303 (prerelease) (crosstool-NG linaro-1.13.1+bzr2650 - Linaro GCC 2014.03). После этого заходим на малину по ssh, выполняем gcc -v и видим например gcc version 6.3.0 20170516 (Raspbian 6.3.0-18+rpi1). Сами понимаете собирать компилятором версии 4.8.3 под систему с gcc версии 6.3.0 не самая лучшая идея :))))) Поэтому идем сюда https://releases.linaro.org/ components/toolchain/binaries качаем версиюю gcc совпадающую с той что стоит на малинке, правим CROSS_COMPILE=путь к новому компилятору bin/префикс команд.
В нашем случае нужно качать файл gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf.tar.xz.
И путь получится такой: CROSS_COMPILE=$BASEPATH/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-6.3.1/bin/arm-linux-gnueabihf-6.3.1/bin/arm-linux-gnueabihf-. Где $BASEPATH/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-6.3.1/bin/arm-linux-gnueabihf-6.3.1/bin/ - путь к файлам компилятора, а arm-linux-gnueabihf- -префикс команд. Вот теперь должно нормально собираться.
5. Создаём sysroot и через rsync синхронизируем его с малиновым, что бы оттуда взять заголовочники, либы и компилятор
Bash Code:
rsync -avz pi@$IP:/lib sysroot # опять идём пить кофе rsync -avz pi@$IP:/usr/include sysroot/usr rsync -avz pi@$IP:/usr/lib sysroot/usr # можно сходить перекусить rsync -avz pi@$IP:/opt/vc sysroot/opt
6. Дальше необходимо поправить символьные ссылки, что бы они были относительно нашей скопированной sysroot, для этого есть готовый скриптик, качаем и запускаем:
Bash Code:
wget https://raw.githubusercontent.com/riscv/riscv-poky/master/scripts/sysroot-relativelinks.py chmod +x sysroot-relativelinks.py ./sysroot-relativelinks.py sysroot
7. Теперь можно склонировать Qt, сконфигурировать и запустить на компиляцию
Bash Code:
git clone git://code.qt.io/qt/qt5.git Qt511Sources perl init-repository git checkout 5.11 git submodule update --recursive cd Qt511Sources BASEPATH=~/Projects/RaspberryPI/raspi # базовый путь, где все наши манипуляции происходят (без слэша на конце) ./configure -skip wayland -skip webkit -skip script -qt-xcb -no-pch -no-use-gold-linker -nomake tests -nomake examples -reduce-exports -release -opengl es2 -device linux-rasp-pi3-g++ -device-option CROSS_COMPILE=$BASEPATH/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-6.3.1/bin/arm-linux-gnueabihf-6.3.1/bin/arm-linux-gnueabihf- -sysroot $BASEPATH/sysroot -opensource -confirm-license -make libs -prefix $BASEPATH/qt5pi -extprefix $BASEPATH/qt5pi -hostprefix $BASEPATH/qt5 -v make -j 4 # и поспим часик (4 - количество ядер проца, для ускорения) make install
Для Qt < 5.9.1 нужен -device linux-rpi3-g++
Если возникли ошибки при сборке и нужно переконфигурировать с другими параметрами, не забудьте удалить предыдущий результат, набрав «git clean -dxf» и «make clean» иначе будет ещё хуже =)
При ошибке с JavaScriptCore/wtf/Platform.h:370:6: error: #error «Not supported ARM architecture» добавьте к конфигурации «-skip script» или добавьте к make флаг:»make CFLAGS=»${CFLAGS}-D__ARM_ARCH_7M__»» (взял из /3rdparty/javascriptcore/ JavaScriptCore/wtf/Platform.h)
При ошибке с PCRE2: PCRE2_CODE_UNIT_WIDTH, LINK_SIZE и прочие мессаджы с ней связанные (отвечает за регулярные выражения) можно либо отключить ( в конфиге «-no-pcre»), но почему-то у меня не было такого параметра, либо прописать все дефайны вручную: make CFLAGS=»${CFLAGS} -ldl -DPCRE2_CODE_UNIT_WIDTH=16 -DHAVE_INTTYPES_H=1 -DHAVE_MEMMOVE=1 -DHAVE_LIMITS_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STDINT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DLINK_SIZE=2 -DMATCH_LIMIT=10000000 -DMATCH_LIMIT_RECURSION=10000000 -DMAX_NAME_COUNT=10000 -DMAX_NAME_SIZE=32 -DNEWLINE_DEFAULT=2 -DPARENS_NEST_LIMIT=250 -DSUPPORT_UNICODE» причина этому — почему-то не подключается файл config.h (Расположен qtbase/src/3rdparty/pcre2/src/config.h), где прописаны все эти дефайны.
При ошибке с zlib, можно её отключить -no-zlib (скорее всего каких-то либ на хосте нехватает, но т.к. мне было не важно, не стал разбираться, остальных проблем хватило)
При ошибке «ERROR: The OpenGL functionality tests failed! You might need to modify the include and library search paths by editing QMAKE_INCDIR_OPENGL[_ES2], QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your platform.» ИЛИ «In function `QEGLPlatformContext::getProcAddress(char const*)’: qeglplatformcontext.cpp:(.text+0xa4): undefined reference to `dlsym'» для Raspbian Stretch нужно подредактировать nano ./qtbase/mkspecs/devices/linux-rasp-pi3-g++/qmake.conf и изменить названия либ «-lEGL» и «-lGLESv2» на «-lbrcmEGL» и «-lbrcmGLESv2» так как названия в /opt/vc/lib/ отличаются. И make запускать так: «make CFLAGS=»${CFLAGS} -ldl»» или так: «LIBS=-ldl ./configure«. Хрен знает что из этого помогло, скорее первое.
В случае ошибки «error: invalid use of incomplete type ‘X509 {aka struct x509_st}’«, то это баг Qt: https://bugreports.qt.io/browse/QTBUG-52905. Исправления будут в версии 5.10, так что либо отключайте ssl при конфигурации: «-no-openssl» либо даунгрейдите openssl до 1.0
8. Теперь закинем на малинку скомпилированные библиотеки и заголовочники Qt:
Bash Code:
cd ../ rsync -avz qt5pi pi@$IP:/usr/local
9. Ну и можно собрать пример и закинуть на малинку:
Bash Code:
cd Qt511Sources/qtbase/examples/opengl/qopenglwidget $BASEPATH/qt5/bin/qmake make scp qopenglwidget pi@$IP:/home/pi
10. На девайсе необходимо дать знать линковщику о наших либах, а так же создать qt.conf в папке, откуда будем запускать все Qt приложения:
Bash Code:
ssh pi@$IP #пароль по дефолту "raspberry" echo /usr/local/qt5pi/lib | sudo tee /etc/ld.so.conf.d/00-qt5pi.conf echo QT_PLUGIN_PATH=/usr/local/qt5pi/plugins/ | sudo tee -a /etc/environment echo QT_QPA_FONTDIR=/usr/share/fonts/truetype/dejavu | sudo tee -a /etc/environment printf "[Paths]\nPlugins=/usr/local/qt5pi/plugins\nQml2Imports=/usr/local/qt5pi/qml" | sudo tee ~/qt.conf cd /usr/local/qt5pi/lib sudo ldconfig
При проблеме «QFontDatabase: Cannot find font directory /home/pi/lib/fonts. Note that Qt no longer ships fonts. Deploy some (from http://dejavu-fonts.org for example) or switch to fontconfig.» нужно указать, где лежат шрифты, для этого добавим переменную окружения (выше уже добавлена) : «echo QT_QPA_FONTDIR=/usr/share/ fonts/truetype/dejavu | sudo tee -a /etc/environment» видимо какую-то опцию забыл в конфиге добавить, наверное «-fontconfig«.
Перезагружаем малинку.
11. Но запускать ещё рано, у rasbian по дефолту грузиться mesa драйвер и opengl пахать не будет по нормальному, поэтому заставим её использовать нужный:
Не факт! Сначала всё таки лучше попробовать запустить =)
Bash Code:
sudo rm /usr/lib/arm-linux-gnueabihf/libEGL.so.1.0.0 /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0 sudo ln -s /opt/vc/lib/libEGL.so /usr/lib/arm-linux-gnueabihf/libEGL.so.1.0.0 sudo ln -s /opt/vc/lib/libGLESv2.so /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0 sudo ln -s /opt/vc/lib/libEGL.so /opt/vc/lib/libEGL.so.1 sudo ln -s /opt/vc/lib/libGLESv2.so /opt/vc/lib/libGLESv2.so.2
Вот теперь наконец-то можно запустить пример! Он на малинке /home/pi/qopenglwidget
Если не запускается, в консольке прописываем
Bash Code:
export QT_LOGGING_RULES=qt.qpa.*=true ./qopenglwidget
И гуглим ошибки. Если совсем не запускается, то прописываем:
Bash Code:
ldd ./qopenglwidget
И смотрим по правильному адресу ли лежат библиотеки и всех ли хватает. Потом гуглим на тему ldconfig.
12. С этим разобрались, теперь настроим QtCreator что бы можно было компилить и запускать на малинке в один клик:
12.1. Инструменты->Параметры->Устройства->Добавить
Обычное Linux-устройство
название на свой вкус и цвет
вводим айпишник, логин и пароль
завершить
Если все хорошо, то увидим следующее сообщение:
12.2. Инструменты->Параметры->Сборка и запуск->Компиляторы->Добавить
GCC->C++
Название: Raspberry PI3 GCC
Путь: /opt/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-6.3.1/bin/arm-linux-gnueabihf-6.3.1/bin/arm-linux-gnueabihf-g++
12.3. Инструменты->Параметры->Сборка и запуск->Отладчики->Добавить
Название: Raspberry PI3 GDB
Путь: /opt/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-6.3.1/bin/arm-linux-gnueabihf-6.3.1/bin/arm-linux-gnueabihf-gdb
12.4. Инструменты->Параметры->Сборка и запуск->Профили Qt->Добавить
Название: Qt 5.11.0 Raspberry PI3
Путь: /opt/raspi/qt5/bin/qmake
12.5. Инструменты->Параметры->Сборка и запуск->Комплекты->Добавить
Название: Raspberry PI3
Тип устройства: Обычное Linux-устройство
Устройство: выбираем добавленное из первого шага
Компилятор C++: Raspberry PI3 GCC
Отладчик: Raspberry PI3 GDB
Профиль Qt: Qt 5.11.0 Raspberry PI3
12.6. Нажимаем «Применить».
13. Создаём новый проект, в *.pro файл добавляем:
Bash Code:
INSTALLS = target target.path = /home/pi
Компилим и после завершения проект должен запуститься на малинке.
Вот как-то так в общем =)
P.S. Большая часть была взята с http://pavelk.ru с моими небольшими правками — думал всё сложнее будет =)
Ниже можно наблюдать видео работы нашей системы Умная остановка на Raspberry Pi 3 Model B.