While it is not the only option, Qt Creator is the integrated development environment (IDE) of choice for Qt. It provides good support for developing for embedded systems, including cross-compiling, deploying to a target system, debugging and profiling. It's free, well documented (1), and actively developed.
Configuring Qt Creator for embedded development is sometimes a stumbling block for our Qt training students and consulting customers. In our recent Qt For Beginners webinar series (2) it was suggested we present detailed instructions showing how to configure Qt Creator for a common embedded board. That was an excellent suggestion, so here they are.
For this example, I'll use the Raspberry Pi platform. It is a popular and low-cost board that can be used for embedded applications. The steps would be similar for other boards, such as a BeagleBone Black.
I'll outline the procedure to get an embedded development environment up and running, including the commands used and configuration screen shots. For this exercise I'm using a Raspberry Pi 3 running the Raspbian Linux distribution. Development will be on an Ubuntu Linux desktop using Qt 5.7.0 and Qt Creator 4.0.3.
Here are the key steps:
- Install Qt Creator
- Get a Linux image running on the target system
- Set up the toolchain/SDK
- Build a cross-compiled Qt
- Configure Qt Creator
- Test the configuration and begin embedded development
Let's get started.
1. Install Qt Creator
To begin, you need to have the Qt Creator IDE up and running on your desktop development system. The latest version at the time of writing is 4.0.3, with a 4.1.0 version in beta. A number of useful features were added in the version 4 series, so I highly recommend you use at least version 4.0.0.
You can download precompiled versions of Qt Creator from https://www.qt.io/download or http://download.qt.io. You can choose to either install Qt Creator on its own or use the online installer, which will allow you to install Qt and Qt Creator based on your selection of components.
There is also an offline Qt installer that includes all of the components and doesn't require any additional downloads. Of course, you can also build Qt Creator from source code.
Make sure your Qt Creator installation works for native development using a native Qt version running on your desktop, as this is a prerequisite to extending it to work for embedded development.
I won't go over configuring Qt Creator for native desktop development as it is covered in the documentation, and in many cases it will automatically detect your installed Qt version and compiler and be ready to go the first time you fire it up.
2. Get a Linux Image Running on the Target System
You will need to have Linux running on your embedded system, in this case a Raspberry Pi. There are several choices for operating systems on the Raspberry Pi. We'll assume you are running the Raspbian Linux distribution as it is the most popular and recommended Linux for the Raspberry Pi. For a commercial embedded product you might want to look at Yocto (3) or boot2qt (4), which may be more suitable for an embedded Linux.
If you don't already have Raspbian running on your Raspberry Pi, you can download the image from https://www.raspberrypi.org/downloads/raspbian, uncompress it, and
write it to a MicroSD card. At the time of writing, the latest Raspbian image file was 2016-05-27-raspbian-jessie.zip. I used these commands from a Linux shell to obtain and install it:
sudo dd if=2016-05-27-raspbian-jessie.img of=/dev/mmcblk0 bs=4M
You will need a suitably-sized MicroSD card to write the image in the step above (at least 8 GB, preferably more). On my laptop system I have an SD slot built in and it appears as the device /dev/mmcblk0. It may be different on your system, particularly if you use a USB to SD card adaptor. Be sure to use the correct device name or you may overwrite some other storage device on your system!
Insert the MicroSD card in your Raspberry Pi and boot it up. You should perform the initial setup described on this Wiki page (5). Specifically, run the raspi-config program to set the system to boot to console and change the GPU memory to 256 MB. While running raspi-config you'll probably also want to resize the MicroSD card, set the locale settings to something suitable for your location and keyboard layout, and enable ssh.
You should also update to the latest Raspbian packages (run sudo apt-get update; sudo apt-get upgrade) and possibly configure WiFi (easily done from the desktop GUI) if you are using a Raspberry Pi 3.
Then, as described in step 3 on the Wiki page, install the required development files and create the installation directory for Qt.
3. Set Up the Toolchain/SDK
The next step is to set up the toolchain to be able to cross-compile code for the Raspberry Pi on the desktop development computer. While you can compile natively on a Raspberry Pi, a modern desktop computer is at least an order of magnitude faster and will quickly pay off in time saved.
Continue to follow the steps on the Wiki page (5) as they work well. I particularly like this procedure as it doesn't require repeatedly removing the SD card. My Raspberry Pi is in a case that makes this awkward to do and risks damaging the ribbon cable for the touchscreen.
Follow steps 4 through 6 of the Wiki page article. Your Raspberry Pi will need to be reachable over the network by ssh. After completing those steps you should now have a toolchain and the necessary files from the Raspberry Pi's root filesystem to be able to cross-compile software for it.
4. Build a Cross-Compiled Qt
Now let's build Qt for the Raspberry Pi. This is covered in steps 7 and 8 of the Wiki article. Note that I modified the procedure slightly. Rather that using the source from git, I downloaded the official Qt 5.7.0 source distribution and built all of the Qt modules rather than just qtbase. It will initially take longer, but will provide you with everything you might need in the future.
I used these commands to download, configure, and build Qt:
tar xzf qt-everywhere-opensource-src-5.7.0.tar.gz
./configure -release -opengl es2 -device linux-rasp-pi2-g++ -device-option CROSS_COMPILE=~/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- -sysroot ~/raspi/sysroot -opensource -confirm-license -prefix /usr/local/qt5pi -extprefix ~/raspi/qt5pi -hostprefix ~/raspi/qt5 -v
You'll probably want to add a -j option to the make commands (e.g. make -j4 on a four core CPU) as it will significantly speed up the build. (It may still take an hour or more depending on the speed of your computer.) You can choose to skip building some of the Qt modules if you wish. (QtWebEngine is very large, for example.)
I found one issue: the native rcc binary was missing from the SDK. You'll need this for building applications that use Qt resources. I simply copied the appropriate file into the right SDK bin directory:
cp ~/raspi/qtbase/bin/rcc ~/raspi/qt5pi/bin
When the Qt build completes, run the rsync command (step 8 of the Wiki procedure) to install Qt on the Raspberry Pi.
At this point, you might want to test the toolchain and Qt install by following steps 9 through 12 in the Wiki article. If you are brave, you can assume it works and move straight to the next step. In any case, be sure to run step 11, which fixes up the OpenGL libraries used.
5. Configure Qt Creator
Now let's get to what this blog post is all about, configuring Qt Creator. We have a Raspberry Pi with Qt 5 and a toolchain running on our desktop. We can configure Qt Creator to make it easy to build and run Qt applications for the Raspberry Pi. Here's how to do this.
First we need to add a device. Launch Qt Creator and select Tools / Options... and then click on the Devices tab near the bottom left of the dialog.
Click on Add... to open the Device Configuration Wizard. Select "Generic Linux Device" and then Start Wizard.
In the Connection screen, enter the appropriate parameters. The screen shot below shows typical values. You will need to enter the appropriate host name or IP address for the Raspberry Pi on your network.
Click Next > and then Finish.
The subsequent Device Test screen should confirm that Qt Creator can communicate with and log in to the Raspberry Pi. If not, go back and correct the settings.
After clicking on Close you should see the board show up as a device, similar to the screen shot below:
Next, add the cross-compiler. From the Tools / Options... screen click on the Build & Run left tab and select Compilers. Click on Add / GCC and enter a new compiler with the name "GCC (Raspberry Pi)" and the Compiler path set to ~/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++ (you can click on Browse and navigate to the file). You should then see the new compiler listed, as in the following screen shot.
Next, select the Debuggers tab and add a new debugger. Click on Add, enter a suitable name, like "gdb (Raspberry Pi)", and the path ~/raspi/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gdb. The debugger entry should look similar to this:
Now we can go to the Qt Versions tab of the Options screen. Check if an entry shows up with the qmake location set to ~/raspi/qt5/bin/qmake. If not, click on Add..., navigate to qmake, and give it a suitable version name. I used "Qt 5.7.0 (Raspberry Pi)" as shown below.
Finally, we are ready to combine these tools into what Qt Creator calls a kit. Click on the Options screen Kits tab, select Add, and create a kit using a suitable name, and the device, compiler, debugger, and Qt version we just created. The value of sysroot should be ~/raspi/sysroot and the other fields can be left empty. The kit I created is shown below.
6. Test the Configuration and Start Embedded Development
We're now ready to try a sample project! Let's select File / New File or Project... and then select the template for Application and Qt Widgets Application.
Click on Choose... and enter a project name or use the default.
Then click on Next > and select the desired kits. Let's select both Desktop (or whatever kit you previously set up for native development) and Raspberry Pi.
Click Next > and leave the Class Information settings at their defaults.
Hit Next > one more time, use the default settings, and select Finish.
We now have a project to test. I suggest you first build and run it locally on your desktop, which should be the default. Here's some of the code:
The default project settings:
And the example running on the desktop:
If that works, click on the "Raspberry Pi" kit under the Projects tab.
If you picked the same project type that I did, you'll need to add some lines to the qmake project file so that qmake knows what files must be deployed to the target system to run the application. An easy way to do this is to edit (from Qt Creator) the project file and add these lines at the bottom:
INSTALLS = target target.files = widgettest target.path = /home/pi
If you go back to the Projects pane, and click on the Run button under "Raspberry Pi" you should see a file now listed under "Files to deploy:".
If you click on the build button, the project should successfully build using the Raspberry Pi kit. Then, clicking on the run button should deploy and run the application on the Raspberry Pi. It won't look very impressive, just a full screen window since we didn't put any widgets in the application.
You might want to go back and add some widgets, like buttons, to the application and try running it again. You can do that from Qt Designer, available in the Design tab.
I suggest you try additional applications, either ones you may already have or some of the Qt examples and tutorials available from the Welcome tab in Qt Creator. You'll probably want to try a QML application, possibly using the Qt Quick Controls 2. These should all work, although for most of them you will need to add some deployment rules like we did with the first example.
The C++ debugger works much the same as when running an application locally, but will communicate with the debugger running on the target system through the network. Make sure you are using the Debug build configuration so you get symbolic debug information.
The valgrind profiler and memory analyzer functions should also work. The valgrind program needs to be installed on your Raspberry Pi (to do so, run sudo apt-get install valgrind). I had some issues running valgrind on certain Qt programs where it reported an error about unsupported ARM instructions.
The QML profiler should also work. I aim to cover this in detail in a future blog post, but basically you select Analyze / QML Profiler, run your application until it exits or you stop it, and then see the results graphically. A typical screen shot is shown below.
These steps were valid at the time of writing but your mileage may vary if using different versions. The basic process should apply to other versions of Qt and other embedded boards.
I have a Raspberry Pi 3 with on-board WiFi and the official touchscreen in a case. It makes for a nice self-contained unit. It will even run for several hours when powered by a low-cost USB power bank.
There are other tools available under Qt Creator that we don't have space to cover here. If you take the time to configure Qt Creator and learn how to use it, I think you will appreciate how productive you can be for embedded development.
I'm impressed that with Qt you can build and run your application locally on your desktop and then build, deploy and run the same code on an embedded board, all with just a few mouse clicks.
- Qt Creator Manual, Qt documentation website, last accessed 19 Jul 2016, http://doc.qt.io/qtcreator/index.html
- Qt for Beginners Part 1 - Overview and Key Concepts, ICS webinar, last accessed 19 Jul 2016, http://www.ics.com/webinars/qt-beginners-part-1-overview-and-key-concepts
- Linux Foundation Yocto Project, website, last accessed 19 July 2016, https://www.yoctoproject.org/
- About Boot to Qt, Qt documentation website, last accessed 19 Jul 2016, http://doc.qt.io/QtForDeviceCreation/qtee-about-b2qt.html
- RaspberryPi2EGLFS, Qt Wiki server, last accessed 19 Jul 2016, https://wiki.qt.io/RaspberryPi2EGLFS