This article describes how to cross compile a Qt application (named qt_tutorial) with OpenEmbedded, and several best practices you should consider. OpenEmbedded currently includes fairly good support for building Qt — both Qt Embedded and Qt X11. OE also includes a number of qt classes that make building Qt applications easy. One of the main considerations with embedded Linux application development is that you keep the build system flexible so that you can easily build on a PC or for your embedded hardware. This means that hand crafted Makefiles with hardcoded paths to cross compilers do not quality.
Put Your Application in a SCM system
No matter what type of application you are building, it is a good idea to put your source in a SCM or revision control system and fetch it directly using OE. OpenEmbedded supports fetching sources from a number of revision control systems including Subversion, Git, Bazaar, Mercurial, CVS, etc. The not so obvious reason we do this is so you can easily check out the source code and build it on a PC as well as your target system in OE. In this example we fetch the application source from a SVN repository:
SRC_URI = "svn://dev.bec-systems.com/svn/pub;module=qt_tutorial;proto=http"
For the above repository, the direct URI to the source would be: http://dev.bec-systems.com/svn/pub/qt_tutorial/
Put the Install logic in the Application Source
Most Linux applications support “make install”, and this is the case with autotools, and qmake (Qt’s build tool). We could put logic in the OE recipe to install the application something like the following:
do_install() { install -d ${D}/${bindir} install -m 0755 ${S}/qt_tutorial ${D}/${bindir} }
But, the problem with this approach is you can’t install the application in other environments (like a native x86 PC build) unless you are building with OE. So a better approach is to put the logic to install the application in the application source, so that in can be installed in both your PC environment, and your OpenEmbedded build. To accomplish this, you can set up the project as follows
application qmake project file (qt_tutorial.pro):
TEMPLATE = app TARGET = qt_tutorial DEPENDPATH += . INCLUDEPATH += . # Input HEADERS += lcdrange.h SOURCES += lcdrange.cpp main.cpp target.path = /usr/bin INSTALLS += target
OpenEmbedded recipe (qt-tutorial_svn.bb):
inherit qt4e SRCREV = "${AUTOREV}" PV = "1.0+svnr${SRCREV}" PR = "r1" SRC_URI = "svn://dev.bec-systems.com/svn/pub;module=qt_tutorial;proto=http" S = ${WORKDIR}/qt_tutorial FILES_${PN}-dbg += "${bindir}/.debug" do_install() { export INSTALL_ROOT=${D} make install }
Now, the same mechanism is used to install the application on both a PC native build, as well an OpenEmbedded build. If you look in the Makefile generated by qmake, you see the following:
install_target: first FORCE @$(CHK_DIR_EXISTS) $(INSTALL_ROOT)/usr/bin/ || $(MKDIR) $(INSTALL_ROOT)/usr/bin/ -$(INSTALL_PROGRAM) "$(QMAKE_TARGET)" "$(INSTALL_ROOT)/usr/bin/$(QMAKE_TARGET)" install: install_target FORCE
INSTALL_ROOT can be set to force the entire system to be installed in a subdirectory. This is required for build systems that generate packages, like OpenEmbedded. To build this example, put the qt-tutorial_svn.bb file in your OE recipes tree, and run: bitbake qt-tutorial. This will fetch the source code and build a package. To run the tutorial, install the package on a system that includes Qt Embedded, and then run: qt_tutorial -qws.
Great!
Hi,
Good tutorial. However, I missed the steps of qmake and make. I mean, considering this recipe, where and how does bitbake run qmake and make?
As the final question, what are the differences in the case of Qt3?
Thanks for the tutorial.
Regards,
“inherit qt4e” causes qmake and make to run automatically.
I started with Qt4, so I’m not sure about Qt3.
Hi Cliff,
Thanks for the answer. Though I couldn’t yet succeed, I’m newbie at OE.
When I run bitbake qt_tutorial, I get this error:
ERROR: Nothing PROVIDES ‘qt_tutorial’
I’ve tried to access the svn server with TortoiseSVN to be sure whether there’s no problem at the connection. But the server did not respond.
Then I’ve set SRC_URI as:
SRC_URI = “http://dev.bec-systems.com/svn/pub/qt_tutorial/;proto=http”
and as another case I tried:
SRC_URI = “http://dev.bec-systems.com/svn/pub/qt_tutorial/;module=qt_tutorial;proto=http”
Both cases have come up with the same error given above.
Finally, I created a “files/” directory and put all the source with .pro file inside. I’ve changed SRC_URI as:
SRC_URI = ” \
file://cannonfield.h \
file://cannonfield.cpp \
file://gameboard.h \
file://gameboard.cpp \
file://lcdrange.h \
file://lcdrange.cpp \
file://main.cpp \
file://qt_tutorial.pro \
”
I’ve also excluded SRCREV and PV lines to get rid of a parse error. And again, I’ve got the same error.
Any suggest would be highly appreciated.
Thanks again.
The tortoisesvn URI would be: http://dev.bec-systems.com/svn/pub/qt_tutorial
try it in a web browser to make sure it works.
The problem with your recipe is the name. The ‘_’ is used to separate PN (package name) from PV (package version). Try the recipe name: qt-tutorial_svn.bb, and it will work.
Hi Cliff,
It worked. Well, since this is the first qt4 application I compiled on OE, first qt-embedded libraries are compiled.
After the compilation, I transferred the package to target machine which is BeagleBoard. Now the problem is that the qt-tutorial requires qt libraries of version 4.4.3, but in the target machine libraries of version 4.4.1 are installed. Anyway, thanks for all helps. And again, great tutorial.
Regards,
nice tutorial, and it’s helpful 😉
thanks
hi, Cliff
thank for your tutorial.
I remain to have one question about this tutorial. what’s the difference between this:
do_install() {
install -d ${D}/${bindir}
install -m 0755 ${S}/qt_tutorial ${D}/${bindir}
}
and this:
do_install() {
export INSTALL_ROOT=${D}
make install
}
don’t they both set the installed directory as $(D)?
From an OE perspective you are correct. The advantage of the INSTALL_ROOT mechanism is the application has knowledge of how to install itself, so if you were to package the application using Debian, or Suse, then the install part would be mostly done. For a simple application this is not a big deal, but for complex applications that install dozens of files, you don’t really want to code the install logic in every distribution build system. For many embedded applications this does not really matter, but I think its always a good idea to use best practices where possible as projects often grow beyond the original scope.
I think it might eventually make sense to put the do_install logic in the qt4e class as it should be common with most Qt apps (similar to the autotools class), but I’ve not looked into this yet.
Pingback: Best practices for building Gtk+ applications with OpenEmbedded » BEC Systems
This is a lot of good information, but it seems I am having a bit of a problem here. Here is what I have:
I have a quadrobot directory that contains my quadrobot_0.1.bb file and a source directory. Within the source directory are my source files.
The BB is as follows:
inherit qt4e
DESCRIPTION = “My Program”
PR = “r1”
S = “${WORKDIR}/${P}”
SRC_URI=”\source://mainwindow.h \source://mainwindow.cpp \source://main.cpp \source://QuadrobotV0.pro;proto=file”
do_install () {
export INSTALL_ROOT=${D}
make install
}
Hello Erik, you are probably better off using the srctree mechanism if you want to build a source code tree in place with OE. See http://cgit.bec-systems.com/cgit.cgi/qt-overo-palo-gpio/tree/ as an example of using this mechanism.
Great. It worked excellent!
Fetching the project from my own svn-server was the easiest way.
I only had to change proto=http to proto=svn
Thank you very much.
Hi Cliff
Thanks for sharing your knowledge, again. Your guides really help.
Thanks
Sean
Hi Cliff
Great bit of information on building Qt application with openembedded. I’m doing something similar, but instead of and application I’m creating a library. My recipe successfully bakes, but I noticed that there are not any files deployed under my tmp/work/armv7a-angstrom-linux-gnueabi//packages-split packages directory. Here is my recipe (I had to remove the repository location and name for non-disclosure reasons):
inherit qt4e
MODULE = “MyMercurialRepoModule”
REF_VER ?= “1.1”
SRCREV ?= “default”
PV = “${REF_VER}+${PR}+hg${SRCREV}”
PR = “r0”
S = “${WORKDIR}/${MODULE}”
do_fetch() {
cd ${WORKDIR}
if [ ! -e ${MODULE} ]; then
hg clone https://mymercurialrepo.org/hg/${MODULE}
fi
}
do_install() {
# Install the libary into the destination
export INSTALL_ROOT=${D}
make ${PARALLEL_MAKE} install
# Install the headers into staging
install -m 0755 -d ${STAGING_INCDIR}/VICTORY
install -m 0644 ${INSTALL_ROOT}${prefix}/local/include/VICTORY/* ${STAGING_INCDIR}/VICTORY
# Install the libraries into staging
oe_libinstall -so lib${MODULE} ${STAGING_LIBDIR}
oe_libinstall -so lib${MODULE}_debug ${STAGING_LIBDIR}
}
FILES_${PN} += “${libdir}/lib${MODULE}.so.*”
FILES_${PN}-dbg += “${libdir}/lib{MODULE}_debug.so.*”
FILES_${PN}-dev += “${includedir}/*”
Could you give any insight as to why this recipe wouldn’t populate the packages folders?
Thanks,
Donald
Hi Cliff,
Thanks for the valuable info you have provided.I was working with the qt4-embedded_4.7.2.bb recipe file.More interested in changing the configuration in such a way that few libraries and executables do not get added in the root file system.These are the list of libraries and executables(in the format of .ipk files) :
Libs:
libphonone4_4.7.2-r34.14-arago8.6_armv7a.ipk
libqtclucenee4_4.7.2-r34.14-arago8.6_armv7a.ipk
libqtdesignercomponentse4_4.7.2-r34.14-arago8.6_armv7a.ipk
libqtdesignere4_4.7.2-r34.14-arago8.6_armv7a.ipk
libqthelpe4_4.7.2-r34.14-arago8.6_armv7a.ipk
libqtteste4_4.7.2-r34.14-arago8.6_armv7a.ipk
libqtwebkite4_4.7.2-r34.14-arago8.6_armv7a.ipk
executables:
qt4-embedded-assistant_4.7.2-r34.14-arago8.6_armv7a.ipk
qt4-embedded-demos_4.7.2-r34.14-arago8.6_armv7a.ipk
qt4-embedded-designer_4.7.2-r34.14-arago8.6_armv7a.ipk
qt4-embedded-pixeltool_4.7.2-r34.14-arago8.6_armv7a.ipk
qt4-embedded-plugin-phonon-backend-gstreamer_4.7.2-r34.14-arago8.6_armv7a.ipk
qt4-embedded-qmlimports-webkit_4.7.2-r34.14-arago8.6_armv7a.ipk
qt4-embedded-qt3to4_4.7.2-r34.14-arago8.6_armv7a.ipk
qt4-embedded-tools_4.7.2-r34.14-arago8.6_armv7a.ipk
I am not that much familiar with the bitbake recipe.I was not able to configure where to make changes in the qt4-embedded_4.7.2.bb(which internally calls qt4-embedded.inc & qt4.inc) so that the above lists don’t get included into the root file system.Any suggestion from your side would be helpful.
with regards,
Suman
Comments are closed.