The Raspberry Pi has become a favorite tool for hobbyists and developers alike, offering a versatile platform for tinkering and experimentation. For my recent project, I needed to develop a custom application for my Raspberry Pi 4. As a newcomer to the world of Raspberry Pi development, I opted for Qt 6, a powerful cross-platform framework, using C++ as my language of choice.
Raspberry Pi 4: We'll be working with a Raspberry Pi 4, running the 64-bit version of Debian 11 (Bullseye).Host Machine: I used Ubuntu 20.04 (Focal Fossa), a reliable and widely used Linux distribution.Compatible Versions: The success of cross-compilation hinges on aligning the versions of essential libraries between the host and target systems. Here's the breakdown of the versions I used:CMake: Ubuntu: 3.23.0GCC: Ubuntu: 9.4.0, Raspberry: 10.2.1GLIBC: Both Ubuntu and Raspberry: 2.31GNU Binutils: Ubuntu: 2.34, Raspberry: 2.35.2OpenSSL: Both Ubuntu and Raspberry: 1.1.1w (11 Sep 2023)
sudo apt update
sudo apt upgrade
sudo apt-get install build-essential libssl-dev make cmake build-essential libclang-dev clang ninja-build gcc git bison python3 gperf pkg-config libfontconfig1-dev libfreetype6-dev libx11-dev libx11-xcb-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libxcb-glx0-dev libxcb-keysyms1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0-dev libxcb-util-dev libxcb-xinerama0-dev libxcb-xkb-dev libxkbcommon-dev libxkbcommon-x11-dev libatspi2.0-dev libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev
cd /tmp
wget https://github.com/Kitware/CMake/releases/download/v3.23.0/cmake-3.23.0.tar.gz
tar -zxvf cmake-3.23.0.tar.gz
cd cmake-3.23.0
./bootstrap
make
sudo make install
sudo apt-get install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
cd ~
mkdir qt-host qt-raspi qt-hostbuild qtpi-build
git clone https://code.qt.io/qt/qt5.git qt6
cd qt6
git switch 6.5.3
perl init-repository --module-subset=qtbase, qtsharertools, qtdeclarative
cd $HOME/qt-hostbuild
cmake ../qt6/ -GNinja -DCMAKE_BUILD_TYPE=Release -DQT_BUILD_EXAMPLES=OFF -DQT_BUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX=$HOME/qt-host
cmake --build . --parallel 8
cmake --install .
cd $HOME
mkdir rpi-sysroot rpi-sysroot/usr rpi-sysroot/opt
rsync -avzS --rsync-path="rsync" --delete <pi_username>@<pi_ip_address>:/lib/* rpi-sysroot/lib
mkdir $HOME/rpi-sysroot/usr
rsync -avzS --rsync-path="rsync" --delete <pi_username>@<pi_ip_address>:/usr/include/* rpi-sysroot/usr/include
rsync -avzS --rsync-path="rsync" --delete <pi_username>@<pi_ip_address>:/usr/lib/* rpi-sysroot/usr/lib
mkdir $HOME/rpi-sysroot/opt
rsync -avzS --rsync-path="rsync" --delete <pi_username>@<pi_ip_address>:/opt/vc rpi-sysroot/opt/vc
pi_username: Your Raspberry Pi's username.pi_ip_address: The IP address of your Raspberry Pi.
wget https://raw.githubusercontent.com/riscv/riscv-poky/master/scripts/sysroot-relativelinks.py
chmod +x sysroot-relativelinks.py
python3 sysroot-relativelinks.py $HOME/rpi-sysroot
cd ~
nano toolchain.cmake
cmake_minimum_required(VERSION 3.18)
include_guard(GLOBAL)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(TARGET_SYSROOT /path/to/your/sysroot)
set(CMAKE_SYSROOT ${TARGET_SYSROOT})
set(ENV{PKG_CONFIG_PATH} $PKG_CONFIG_PATH:/usr/lib/aarch64-linux-gnu/pkgconfig)
set(ENV{PKG_CONFIG_LIBDIR} /usr/lib/pkgconfig:/usr/share/pkgconfig/:${TARGET_SYSROOT}/usr/lib/aarch64-linux-gnu/pkgconfig:${TARGET_SYSROOT}/usr/lib/pkgconfig)
set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT})
# if you use other version of gcc and g++ than gcc/g++ 9, you must change the following variables
set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc-9)
set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++-9)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${TARGET_SYSROOT}/usr/include")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}")
set(QT_COMPILER_FLAGS "-march=armv8-a")
set(QT_COMPILER_FLAGS_RELEASE "-O2 -pipe")
set(QT_LINKER_FLAGS "-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_BUILD_RPATH ${TARGET_SYSROOT})
include(CMakeInitializeConfigs)
function(cmake_initialize_per_config_variable _PREFIX _DOCSTRING)
if (_PREFIX MATCHES "CMAKE_(C|CXX|ASM)_FLAGS")
set(CMAKE_${CMAKE_MATCH_1}_FLAGS_INIT "${QT_COMPILER_FLAGS}")
foreach (config DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
if (DEFINED QT_COMPILER_FLAGS_${config})
set(CMAKE_${CMAKE_MATCH_1}_FLAGS_${config}_INIT "${QT_COMPILER_FLAGS_${config}}")
endif()
endforeach()
endif()
if (_PREFIX MATCHES "CMAKE_(SHARED|MODULE|EXE)_LINKER_FLAGS")
foreach (config SHARED MODULE EXE)
set(CMAKE_${config}_LINKER_FLAGS_INIT "${QT_LINKER_FLAGS}")
endforeach()
endif()
_cmake_initialize_per_config_variable(${ARGV})
endfunction()
set(XCB_PATH_VARIABLE ${TARGET_SYSROOT})
set(GL_INC_DIR ${TARGET_SYSROOT}/usr/include)
set(GL_LIB_DIR ${TARGET_SYSROOT}:${TARGET_SYSROOT}/usr/lib/aarch64-linux-gnu/:${TARGET_SYSROOT}/usr:${TARGET_SYSROOT}/usr/lib)
set(EGL_INCLUDE_DIR ${GL_INC_DIR})
set(EGL_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libEGL.so)
set(OPENGL_INCLUDE_DIR ${GL_INC_DIR})
set(OPENGL_opengl_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libOpenGL.so)
set(GLESv2_INCLUDE_DIR ${GL_INC_DIR})
set(GLESv2_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libGLESv2.so)
set(gbm_INCLUDE_DIR ${GL_INC_DIR})
set(gbm_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libgbm.so)
set(Libdrm_INCLUDE_DIR ${GL_INC_DIR})
set(Libdrm_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libdrm.so)
set(XCB_XCB_INCLUDE_DIR ${GL_INC_DIR})
set(XCB_XCB_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libxcb.so)
cd ~/qtpi-build
cmake ../qt6/ -GNinja -DCMAKE_BUILD_TYPE=Release -DINPUT_opengl=es2 \
-DQT_BUILD_EXAMPLES=OFF -DQT_BUILD_TESTS=OFF -DQT_HOST_PATH=$HOME/qt-host \
-DCMAKE_STAGING_PREFIX=$HOME/qt-raspi -DCMAKE_INSTALL_PREFIX=/usr/local/qt6 \
-DCMAKE_TOOLCHAIN_FILE=$HOME/toolchain.cmake \
-DQT_QMAKE_TARGET_MKSPEC=devices/linux-rasp-pi4-aarch64 \
-DQT_FEATURE_xcb=ON -DFEATURE_xcb_xlib=ON -DQT_FEATURE_xlib=ON
cmake --build . --parallel 4
cmake --install .
rsync -avz --rsync-path="sudo rsync" /path/to/qt-raspi/* <pi_username>@<pi_ip_address>:/usr/local/qt6
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/qt6/lib/
export DISPLAY=:0
Clone your project onto your host machine. Make sure it has a CMakeLists.txt file.Configure your project with the cross-compiled Qt libraries.
cd ~/your_project
../qt-raspi/bin/qt-cmake CMakeLists.txt
cmake --build . --parallel 4
cmake --install .
Transfer the compiled application to the Raspberry Pi:
scp -r app_name <pi_username>@<pi_ip_address>:/home/pi
Connect to the Raspberry Pi via SSH:
ssh <pi_username>@<pi_ip_address>
Navigate to the directory where you copied the application and run it:
cd home/pi
./app_name
0 comments:
Post a Comment