2013/11/07

Compile Qt 5 (qtbase) for LEGO Mindstorms EV3 on Linux

Requirements:


Tested with:
  • Ubuntu 12.04.
  • EV3 firmware v1.03H.
Devices:
  • a micro SD card to copy all the libraries and binaries
  • a way to access to your EV3 remotely:

Don't do what follows if you don't know what you are doing. I can't be held responsible for any damage caused to your EV3 or your PC.

Cross-compilation toolchain installation 

Download ARM cross-compilation toolchain, Code Sourcery:

wget -c http://www.codesourcery.com/sgpp/lite/arm/portal/package4571/public/arm-none-linux-gnueabi/arm-2009q1-203-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2


Extract the package wherever you want. For example, ~/codesourcery/:


cd
mkdir codesourcery
cd codesourcery
tar -xjvf arm-2009q1-203-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2

Add the toolchain binaries to your PATH, by adding the following line to your ~/.bashrc:

export PATH="~/codesourcery/arm-2009q1/bin:$PATH"


then open a new terminal to continue or enter:
 

source ~/.bashrc

The cross-compilation toolchain is now installed.




Qt compilation

Download Qt source package:

I used Qt 5.1.1, available from this link:

http://download.qt-project.org/official_releases/qt/5.1/5.1.1/single/qt-everywhere-opensource-src-5.1.1.tar.gz

If you want to try with the latest release, go to this page:

https://qt-project.org/downloads

Be careful, you need to download the source package, not an executable binary!

Let's talk about the 'qmake.conf' file. This file is used to compile and link suiting your needs.
Create it and put it where your Qt source package is.

 

qmake.conf:

#
# qmake configuration for building with arm-none-linux-gnueabi-g++
#


MAKEFILE_GENERATOR      = UNIX
CONFIG                 += incremental gdb_dwarf_index
QMAKE_INCREMENTAL_STYLE = sublib

include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)

#Compilers, they are in the directory you've just added to PATH

QMAKE_CC                = arm-none-linux-gnueabi-gcc
QMAKE_CXX               = arm-none-linux-gnueabi-g++
QMAKE_LINK              = arm-none-linux-gnueabi-g++
QMAKE_LINK_SHLIB        = arm-none-linux-gnueabi-g++

#Very important! These options tell the compiler that the target processor is an ARM926EJ-S which architecture is ARMV5TE.
QMAKE_CXXFLAGS       += -mcpu=arm926ej-s -march=armv5te
QMAKE_LFLAGS         += -mcpu=arm926ej-s -march=armv5te

#On the EV3, the SD card mounting point is /media/card
#I chose to install all the toolchain binaries and libraries in /media/card/sysroots/arm2009q1

TARGET_SYSROOT=/media/card/sysroots/arm2009q1

#and the Qt libraries in /media/card/lib
TARGET_LIBPATH=/media/card/lib

#Helps the EV3 find where the libraries are.
QMAKE_LFLAGS         += -Wl,-rpath=$$TARGET_SYSROOT/lib:$$TARGET_SYSROOT/usr/lib:$$TARGET_LIBPATH

#Mandatory for dynamic linking on the target
QMAKE_LFLAGS         += -Wl,--dynamic-linker=$$TARGET_SYSROOT/lib/ld-linux.so.3

# modifications to linux.conf
QMAKE_AR                = arm-none-linux-gnueabi-ar cqs
QMAKE_OBJCOPY           = arm-none-linux-gnueabi-objcopy
QMAKE_NM                = arm-none-linux-gnueabi-nm -P
QMAKE_STRIP             = arm-none-linux-gnueabi-strip

load(qt_config)


___________________________________________________

Extract the package:

tar -xzvf qt-everywhere-opensource-src-5.1.1.tar.gz

then copy the qmake.conf file to the directory corresponding to an 'ARM with Linux' Qt build:

cp qmake.conf qt-everywhere-opensource-src-5.1.1/qtbase/mkspecs/linux-arm-gnueabi-g++

This directory already contains a qmake.conf file, but it won't work if you keep it as it is.

Go to the qtbase directory:

cd qt-everywhere-opensource-src-5.1.1/qtbase



and run the configuration and build process:


./configure -v -opensource -confirm-license -release \
  -prefix
~/Qt5.1.1_ev3 \
  -xplatform linux-arm-gnueabi-g++ \

  -qpa linuxfb \
  -qtlibinfix _ev3 \
  -no-c++11 \
  -no-widgets \
  -no-opengl \
  -no-openvg \
  -no-compile-examples \
  -nomake tests \
  -nomake examples \
  -nomake tools \
  && make \
  && make install


If all went well, you must retrieve the fresh-made 'qmake' to compile your projects.
You can create a symlink or make a copy:

sudo cp
~/Qt5.1.1_ev3/bin/qmake /usr/bin/qmake.ev3

Notice that I've called it 'qmake.ev3' to avoid conflicts with other qmake versions.



Compile a "Hello world" application

Create a new directory which will contain your new project:


main.cpp:


#include <QtCore/QCoreApplication>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug("Hello Qt!");
   
    return a.exec();
}//main

_____________________________________________________

hello_qt.pro:

TEMPLATE = app
TARGET = hello_qt
INCLUDEPATH += .

CONFIG += release

QT -= gui

# Input
SOURCES += main.cpp
 


_____________________________________________________

Now, be sure that you are in your project directory and enter:

qmake.ev3
make


That's it! The program should compile and link.




Installation on the EV3

We need to copy all the libraries and binaries on the SD card. If you can copy all the files directly from your PC to the SD card, do it. If it's not possible, you can find some tutorials to copy files to your EV3 over SSH on the internet.

Copy all the files contained in the source directories to the destination directories on your SD card:

                  SOURCE                            DESTINATION
~/codesourcery/arm-2009q1/arm-none-linux-gnueabi/libc/etc => /media/card/sysroots/arm2009q1/etc
~/codesourcery/arm-2009q1/arm-none-linux-gnueabi/libc/lib => /media/card/sysroots/arm2009q1/lib
~/codesourcery/arm-2009q1/arm-none-linux-gnueabi/libc/sbin => /media/card/sysroots/arm2009q1/sbin
~/codesourcery/arm-2009q1/arm-none-linux-gnueabi/libc/usr/bin => /media/card/sysroots/arm2009q1/usr/bin
~/codesourcery/arm-2009q1/arm-none-linux-gnueabi/libc/usr/sbin => /media/card/sysroots/arm2009q1/usr/sbin
~/codesourcery/arm-2009q1/arm-none-linux-gnueabi/libc/var => /media/card/sysroots/arm2009q1/var


Regarding the /usr/lib directory, just copy the dynamic libs (.so files):


~/codesourcery/arm-2009q1/arm-none-linux-gnueabi/libc/usr/lib/*.so* => /media/card/sysroots/arm2009q1/usr/lib

Copy all the Qt libraries to your SD card:

~/Qt5.1.1_ev3/lib/libQt5*.so.5.1.1 => /media/card/lib

In your Qt SD card directory (/media/card/lib), rename all the Qt libs to *.so.5 :
eg: libQt5Core_ev3.so.5.1.1 -> libQt5Core_ev3.so.5

Copy your project binary to your SD card:

~/hello_qt/hello_qt => /media/card/hello_qt

Finally, connect to your EV3 using telnet and run your program. The IP address is available from the EV3 menu, in "Brick info":

telnet 192.168.1.3
 

login -> root
password -> simply press enter since no password is required.

cd /media/card/
./hello_qt


Hello Qt!

2 comments:

  1. Thank you for sharing. Allowed me to get started.
    What would be required to use the signal/slot features of Qt on the EV3 ?
    I guess one would have to implement specific classes for motors and sensors...
    Would you know of any existing related effort ?

    ReplyDelete
    Replies
    1. Hi,

      >> What would be required to use the signal/slot features of Qt on the EV3 ?

      It works, nothing more is required. I've run a simple TCP server with signals and slots connections.

      >> Would you know of any existing related effort ?

      I don't know any Qt API for the EV3. Maybe you could start with these links to write your own classes:
      - http://bricxcc.sourceforge.net/ : simple and efficient C code. I didn't check all the features.
      - http://www.robotnav.com : seems interesting. I've not tested it though.

      Delete