This tutorial shows you how to set up a Qt 5.2.1 cross compile environment for the Beaglebone Black on Ubuntu. I had some trouble in the past with this procedure, so here I show you how I accomplished this task.
I choose the Ubuntu 14.04 LTS image for the Beaglebone Black, because it will be supported from Canonical officially until April 2019 and it’s a very nice and minimalistic image. So in this part of the tutorial we will create an Ubuntu image with all needed packages.
In this tutorial, I will speak about two systems:
- host: with host I mean your PC, running Ubuntu, where the cross compile environment will be set up and where you will be able to cross compile Qt application for the Beaglebone Black.
- target: with target I mean the Beaglebone Black system.
Requirements
- Beaglebone Black
- micoSD (>= 2 GB) and an adapter for the PC
- Ethernet cable
Prepare the microSD card (on host)
You can find the installation instructions on the armhf homeage, but for the completeness, i will show you this steps to. First we need to prepare the partitions on the microSD card.
Inset the microSD in your computer and check which device is your microSD with following command:
$ export DISK=/dev/sdc
Now we have to create two partitions on this microSD card. One for the boot loader (u-boot) and one for the root file system (rootfs). Make shore the microSD card is not mounted.
Note: please be very careful in this step, you can delete your whole system if you choose the wrong device!! This will delete all data from your microSD card!!
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 465,9G 0 disk
├─sda1 8:1 0 200M 0 part /boot/efi
├─sda2 8:2 0 45G 0 part
├─sda3 8:3 0 279,4G 0 part /
└─sda4 8:4 0 139,7G 0 part
sdc 8:32 1 1,9G 0 disk
└─sdc1 8:33 1 1,7G 0 part
$ sudo fdisk $DISK
Print the partition table using p
to make sure this is the correct device. (In this example it is a 2 GB microSD card):
Command (m for help): p
Disk /dev/sdc: 1,9 GiB, 2002780160 bytes, 3911680 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000
Device Boot Start End Sectors Size Id Type
/dev/sdc1 * 2048 3481599 3479552 1,7G 83 Linux
Delete all partitions (using d, enter):
Command (m for help): d
Selected partition 1
Partition 1 has been deleted.
Note: If you have more than one partition repeat this step until each partition is deleted on the microSD.
Create a new dos partition table (using o):
Command (m for help): o
Created a new DOS disklabel with disk identifier 0xe7264b01.
Create a new 1 MiB partition for the boot loader (n
, enter
, enter
, enter
, 4095
):
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p):
Partition number (1-4, default 1): 1
First sector (2048-3911679, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-3911679, default 3911679): 4095
Change the partition type to W95 FAT32 (t, b)
:
Command (m for help): t
Selected partition 1
Hex code (type L to list all codes): b
If you have created or modified any DOS 6.x partitions, please see the fdisk documentation for additional information.
Changed type of partition 'Linux' to 'W95 FAT32'.
Enable the boot flag for this partition (a
):
Command (m for help): a
Selected partition 1
The bootable flag on partition 1 is enabled now.
Created a second partition for the rootfs with the rest of the storage (n
, enter
, enter
, enter
, enter
):
Command (m for help): n
Partition type
p primary (1 primary, 0 extended, 3 free)
e extended (container for logical partitions)
Select (default p):
Using default response p.
Partition number (2-4, default 2):
First sector (4096-3911679, default 4096):
Last sector, +sectors or +size{K,M,G,T,P} (4096-3911679, default 3911679):
Created a new partition 2 of type 'Linux' and of size 1,9 GiB.
Now your partition table should look something like this:
Command (m for help): p
Disk /dev/sdc: 1,9 GiB, 2002780160 bytes, 3911680 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xe7264b01
Device Boot Start End Sectors Size Id Type
/dev/sdc1 * 2048 4095 2048 1M b W95 FAT32
/dev/sdc2 4096 3911679 3907584 1,9G 83 Linux
Write the partition table to the disk and exit using w
:
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
Format the two partitions:
$ sudo mkfs.vfat ${DISK}1 -n BOOT
$ sudo mkfs.ext4 ${DISK}2 -L rootfs
Install u-boot to the first partition:
$ wget http://s3.armhf.com/dist/bone/bone-uboot.tar.xz
$ sudo mkdir /mnt/boot
$ sudo mount ${DISK}1 /mnt/boot
$ sudo tar xJvf bone-uboot.tar.xz -C /mnt/boot
Install rootfs to the second partition:
$ wget http://s3.armhf.com/dist/bone/ubuntu-trusty-14.04-rootfs-3.14.4.1-bone-armhf.com.tar.xz
$ sudo mkdir /mnt/rootfs
$ sudo mount ${DISK}2 /mnt/rootfs
$ sudo tar xJvf ubuntu-trusty-14.04-rootfs-3.14.4.1-bone-armhf.com.tar.xz -C /mnt/rootfs
Unmount the partitions:
$ sudo umount ${DISK}1
$ sudo umount ${DISK}2
Now insert the microSD into the Beaglebone Black, connect the ethernet cable
and power it on.
Install the build dependencies (on target)
In order to find out the IP address of the Beaglebone Black you can search it in your network with the nmap
command. Assuming your router has the IP 192.168.1.1
you can use nmap
as following:
$ sudo nmap -sP 192.168.1.1/24
You should get a list of all devices connected to the network. An example of a Beaglebone Black could look like this:
Nmap scan report for 192.168.1.54
Host is up (-0.093s latency).
MAC Address: 11:22:33:44:55:66 (Texas Instruments)
Note: the device with Texas Instruments in it is possibly the Beaglebone Black.
Connect to the new system with the user ubuntu
and the password ubuntu
:
$ ssh This email address is being protected from spambots. You need JavaScript enabled to view it.
This email address is being protected from spambots. You need JavaScript enabled to view it.'s password: ubuntu
Update and upgrade all packages:
Note: the sudo password for root is also ubuntu. The ssh login for root is by default disabled. You can change that in the /etc/ssh/sshd_config by replacing the line PermitRootLogin without-password with PermitRootLogin yes. It’s recommended to set the root password first with `passwd`.
$ sudo apt-get update
$ sudo apt-get upgrade
Installing the kernel header files (on target)
If you want to build or cross compile kernel modules for the Beaglebone Black, you need to install the kernel header files for the kernel in this image. for that you can run following commands in your fresh system:
$ wget http://s3.armhf.com/dist/bone/linux-headers-3.14.4.1-bone-armhf.com.tar.xz
$ sudo tar xJvf linux-headers-3.14.4.1-bone-armhf.com.tar.xz -C /
$ rm linux-headers-3.14.4.1-bone-armhf.com.tar.xz
Installing build dependencies for Qt 5.2.1 (on target)
Since this tutorial shows hot to cross compile Qt 5.2.1 which is available in the repository, we need to install the build dependencies of the Qt packages. A good reference can be found here.
$ sudo apt-get build-dep qt5-default
Install all dependencies for libxcb
:
$ sudo apt-get install "^libxcb.*" libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev
If you want to crosscompile the QtMultimedia
module you will need:
$ sudo apt-get install libasound2-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev
If you want to build the QtWebEngine
:
$ sudo apt-get install libcap-dev libbz2-dev libgcrypt11-dev libpci-dev libnss3-dev build-essential libxcursor-dev libxcomposite-dev libxdamage-dev libxrandr-dev libdrm-dev libfontconfig1-dev libxtst-dev libasound2-dev gperf libcups2-dev libpulse-dev libudev-dev libssl-dev flex bison ruby
If you want to build QtConnectivity
module (Blutooth support):
$ apt-get install bluez libbluetooth-dev bluetooth bluez-tools
If you are working with I2C you will also need the libi2c-dev
:
$ apt-get install i2c-tools libi2c-dev
Clean up rootfs (on target)
In order to keep the cross compile rootfs as small as possible, you can delete all the downloaded packages, which are already installed:
$ sudo apt-get clean
Now power off the Beaglebone Black and insert the microSD in the host.
Set up the cross compile environment (on host)
Create the working directory, where the whole cross compile environment will be created:
$ sudo mkdir /opt/qt-beaglebone-black/
$ sudo chown $USER /opt/qt-beaglebone-black/
$ cd /opt/qt-beaglebone-black/
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 465,9G 0 disk
├─sda1 8:1 0 200M 0 part /boot/efi
├─sda2 8:2 0 45G 0 part
├─sda3 8:3 0 279,4G 0 part /
└─sda4 8:4 0 139,7G 0 part
sdc 8:32 1 1,9G 0 disk
├─sdc1 8:33 1 1M 0 part
└─sdc2 8:34 1 1,9G 0 part
Create a backup of you rootfs:
$ sudo mount /dev/sdc2 /mnt/rootfs
$ cd /mnt/rootfs
$ sudo tar cpjfv /opt/qt-beaglebone-black/rootfs.tar.bz2 ./
$ sudo chown $USER /opt/qt-beaglebone-black/rootfs.tar.bz2
Cross compile Qt 5.2.1 for Beaglebone Black
For this whole procedure I have written a script which will do everything for you, but for the completeness I will explain what it does in the next chapter.
$ wget http://guh.guru/downloads/scripts/crosscompile-Qt_5.2.1-beaglebone-black.sh
$ chmod +x crosscompile-Qt_5.2.1-beaglebone-black.sh
Your folder should look like this before you start the script:
$ pwd
/opt/qt-beaglebone-black/
$ ls -l
crosscompile-Qt_5.2.1-beaglebone-black.sh
rootfs.tar.bz2
Now you can start the build process by running the script:
Note: please read the script carefully before you start it. The script is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
./crosscompile-Qt_5.2.1-beaglebone-black.sh
Once the script is finished, you should be have a working crosscompile environment and can jump to the chapter Set up QtCreator
or read the explanation during the build process.
Explanation of the script
Since this script is the result of quiet a few runns here is the manual procedure and explanation of the script steps.
Download Qt source code and the cross compiler
You can find the qt source code files here:
$ wget http://download.qt.io/archive/qt/5.2/5.2.1/single/qt-everywhere-opensource-src-5.2.1.tar.xz
$ md5sum qt-everywhere-opensource-src-5.2.1.tar.xz
0c8d2aa45f38be9c3f7c9325eb059d9d
$ tar xfv qt-everywhere-opensource-src-5.2.1.tar.xz
You can find the cross compiler files here:
$ wget http://releases.linaro.org/14.04/components/toolchain/binaries/gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux.tar.xz
$ md5sum gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux.tar.xz
44fbcca1478e477916bdf6a03b6ab85a
$ tar xfv gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux.tar.xz
Export all variables we need during the build process:
$ export CURRENT_DIR=`pwd`
$ export QT_SRCDIR="${CURRENT_DIR}/qt-everywhere-opensource-src-5.2.1"
$ export CC_DIR="${CURRENT_DIR}/gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux"
$ export CC="${CC_DIR}/bin/arm-linux-gnueabihf-"
$ export PREFIX="${CURRENT_DIR}/Qt-5.2.1"
$ export ROOTFS_DIR="${CURRENT_DIR}/rootfs"
$ export LOG_DIR="${CURRENT_DIR}/logfiles"
$ export NPROC=`nproc`
Create qmake mkspecs
Create linux-beaglebone-g++
device
$ cd ${QT_SRCDIR}/qtbase/mkspecs/devices/
$ cp -rv linux-beagleboard-g++ linux-beaglebone-g++
$ sed 's/softfp/hard/' <linux-beagleboard-g++/qmake.conf >linux-beaglebone-g++/qmake.conf
Create the linux-linaro-gnueabihf-g++
qmake configuration
$ cd ${QT_SRCDIR}/qtbase/mkspecs
$ cp -r linux-arm-gnueabi-g++/ linux-linaro-gnueabihf-g++/
$ export TO_REPLACE="arm-linux-gnueabi-"
$ sed "s|${TO_REPLACE}|${CC}|g" <linux-arm-gnueabi-g++/qmake.conf >linux-linaro-gnueabihf-g++/qmake.conf
Fix the library symbolic links
Since the library links in our Beaglebone Black rootfs point to point to the host roofs and not to the crosscompile rootfs thy need to be fixed. This script makes all absolute library symbolic links relative:
Note: this script is originally from https://gitorious.org/cross-compile-tools/cross-compile-tools.git.
$ cd ${CURRENT_DIR}
$ wget http://guh.guru/downloads/scripts/fixQualifiedLibraryPaths
$ chmod +x fixQualifiedLibraryPaths
$ sudo ./fixQualifiedLibraryPaths ${ROOTFS_DIR} ${CC}g++
Configure qtbase
$ cd ${QT_SRCDIR}/qtbase/
Now it’s time to run the configure script:
$./configure -prefix ${PREFIX} -sysroot ${ROOTFS_DIR} -device linux-beaglebone-g++ -xplatform linux-linaro-gnueabihf-g++ -device-option CROSS_COMPILE=${CC} -release -silent -opensource -confirm-license -continue -v -nomake examples -nomake tests 2>&1 | tee -a ${LOG_DIR}/qtbase-configure-log.txt
Note: the output of the configure process and make process will be stored in the logfiles directory.
Once the configuration script is finished, your configuration should look like this:
Build options:
Configuration .......... accessibility accessibility-atspi-bridge alsa audio-backend c++11 clock-gettime clock-monotonic compile_examples concurrent cross_compile cups dbus egl eglfs evdev eventfd fontconfig full-config getaddrinfo getifaddrs glib gtk2 gtkstyle iconv icu inotify ipv6ifname large-config largefile linuxfb medium-config minimal-config mremap neon nis no-harfbuzz opengl openssl openvg pcre png posix_fallocate precompile_header pulseaudio qpa qpa reduce_exports reduce_relocations release rpath shared silent small-config system-freetype system-jpeg system-zlib xcb xcb-glx xcb-render xcb-sm xcb-xlib xinput2 xlib xrender
Build parts ............ libs
Mode ................... release
Using C++11 ............ yes
Using PCH .............. yes
Target compiler supports:
iWMMXt/Neon .......... no/yes
Qt modules and options:
Qt D-Bus ............... yes (loading dbus-1 at runtime)
Qt Concurrent .......... yes
Qt GUI ................. yes
Qt Widgets ............. yes
JavaScriptCore JIT ..... yes (To be decided by JavaScriptCore)
QML debugging .......... yes
Use system proxies ..... no
Support enabled for:
Accessibility .......... yes
ALSA ................... yes
CUPS ................... yes
FontConfig ............. yes
FreeType ............... system
Iconv .................. yes
ICU .................... yes
Image formats:
GIF .................. yes (plugin, using bundled copy)
JPEG ................. yes (plugin, using system library)
PNG .................. yes (in QtGui, using bundled copy)
Glib ................... yes
GTK theme .............. yes
Large File ............. yes
mtdev .................. no
Networking:
getaddrinfo .......... yes
getifaddrs ........... yes
IPv6 ifname .......... yes
OpenSSL .............. yes (loading libraries at run-time)
NIS .................... yes
OpenGL ................. desktop
OpenVG ................. yes-auto
PCRE ................... yes (bundled copy)
pkg-config ............. yes
PulseAudio ............. yes
QPA backends:
DirectFB ............. no
EGLFS ................ yes
KMS .................. no
LinuxFB .............. yes
XCB .................. yes (system library)
MIT-SHM ............ yes
Xcb-Xlib ........... yes
Xcursor ............ yes (loaded at runtime)
Xfixes ............. yes (loaded at runtime)
Xi ................. no
Xi2 ................ yes
Xinerama ........... yes (loaded at runtime)
Xrandr ............. yes (loaded at runtime)
Xrender ............ yes
XKB ................ yes
XShape ............. yes
XSync .............. yes
XVideo ............. yes
Session management ..... yes
SQL drivers:
DB2 .................. no
InterBase ............ no
MySQL ................ no
OCI .................. no
ODBC ................. yes (plugin)
PostgreSQL ........... no
SQLite 2 ............. no
SQLite ............... yes (plugin, using bundled copy)
TDS .................. yes (plugin)
udev ................... no
xkbcommon .............. yes (system library)
zlib ................... yes (system library)
Build qtbase
Now we can build qtbase. With following command the build process will be logged in the logfiles/qtbase-build-log.txt
file and all CPU’s will be used for compiling:
$ make -j$NPROC 2>&1 | tee -a ${LOG_DIR}/qtbase-build-log.txt
Once the build process has successfully finished you can install all files. This command will create a $CURDIR/Qt-5.2.1
folder where qmake and the other Qt tools for cross compiling will be installed. The cross compiled Qt libraries will be installed in rootfs/opt/qt-beaglebone-black/Qt-5.2.1/
.
$ sudo make install
Build other qt modules
If you need other Qt modules like qtmultimedia
or qtserialport
you need to compile and install them. Since there is a certain dependency between the Qt modules, the order of the module compilation is important and can be found here:
http://qt-project.org/wiki/Qt_Library_Cross_Dependencies
In order to cross compile a Qt module, we need to use our fresh compiled qmake:
$ export QMAKE_CROSS="${PREFIX}/bin/qmake"
$ cd ${QT_SRCDIR}
Now you can start compiling the modules you need (for me following order worked great):
- qtgraphicaleffects
$ cd qtgraphicaleffects $ ${QMAKE_CROSS} 2>&1 | tee -a ${LOG_DIR}/qtgraphicaleffects-qmake-log.txt $ sudo make -j${NPROC} 2>&1 | tee -a ${LOG_DIR}/qtgraphicaleffects-make-log.txt $ sudo make install $ cd ..
- qttools
$ cd qttools $ ${QMAKE_CROSS} 2>&1 | tee -a ${LOG_DIR}/qttools-qmake-log.txt $ sudo make -j${NPROC} 2>&1 | tee -a ${LOG_DIR}/qttools-make-log.txt $ sudo make install $ cd ..
- qtscript
...
- qtserialport
- qtsensors
- qtimageformats
- qtsvg
- qtactiveqt
- qtxmlpatterns
- qtdeclarative
- qtquick1
- qtquickcontrols
- qtmultimedia
- qtconnectivity
Now you have a working Qt 5.2.1 cross compile environment for the Beaglebone Black. Since you can install Qt native from the repository, you can install qt5-default
and all modulus you want on the target system.
Set up QtCreator
Now you can set up you QtCreator with the new cross compile environment. This will allow you to compile and deploy applications to the target Beaglebone Black over the network and follow the debug output in the QtCreater on the host.
Configure device
First we need to create a new Generic Linux Device, which will represent the Beaglebone Black.
- In the QtCreator main window click →
Tools
→Options
- In the left menu click on →
Devices
→Add...
Generic Linux Device
→Start Wizard
- Fill out the data of your Beaglebone Black
- →
Next
→Finish
If the test was successful, you can continue.
Configure gcc
- In the QtCreator main window click →
Tools
→Options
- In the left menu click on →
Build & Run
→Compilers
→Add
→GCC
- Name:
BeagleBone Black GCC
- Compiler path:
/opt/qt-beaglebone-black/gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux/bin/arm-linux-gnueabihf-g++
Configure gdb
- In the QtCreator main window click →
Tools
→Options
- In the left menu click on →
Build & Run
→Debuggers
→Add
- Name:
BeagleBone Black GDB
- Path:
/opt/qt-beaglebone-black/gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux/bin/arm-linux-gnueabihf-gdb
Configure Qt Version
- In the QtCreator main window click →
Tools
→Options
- In the left menu click on →
Build & Run
→Qt Version
→Add
- Brows to our crosscompiled
qmake
, which sould be in/opt/qt-beaglebone-black/Qt-5.2.1/bin/qmake
→Open
- Version name: Qt 5.2.1 (BeagleBone Black)
Configure Kit
- In the QtCreator main window click →
Tools
→Options
- In the left menu click on →
Build & Run
→Kits
→Add
- Name:
Beaglebone Black
- Next to the name you can set an icon.
- Device: Your configured Beaglebone Black device
- Sysroot:
/opt/qt-beaglebone-black/rootfs
- Compiler:
BeagleBone Black GCC
- Debugger:
BeagleBone Black GDB
- Qt Version:
Qt 5.2.1 (BeagleBone Black)
That’s it. Now you can add the Kit to your project and press the play button!!!