Monday, October 24, 2011

Qt for the BlackBerry PlayBook

At the keynote to the BlackBerry Developer Conference last week, two very interesting things were announced.  First, the BlackBerry PlayBook Native SDK is finally in public release (it had previously been in a semi-closed beta).  Second, RIM unveiled the Native Open Source Components Initiative on GitHub.  This GitHub site includes ports of many open source libraries to the PlayBook, including the Qt Framework!  The only real downside here is that all they've done so far is to push out the code.  No how-to documentation has been provided.  Therefore, I'm going to attempt to give a walkthrough for setting yourself up to use their Qt port for PlayBook development.



Before we begin, I'm going to make the following assumptions:
  • You are using Linux (MacOSX is probably similar, Windows probably has more differences)
  • You have a Git client installed
  • You have installed the Native SDK in: /opt/RIM/bbndk
  • You have already requested and installed code signing keys
  • You have generated a debug token, and saved it in your home directory as "debugToken.bar"
  • You have an actual PlayBook, on an IP address your computer can connect to, that is in development mode with the above debug token installed.
(I'm sorry if those are a lot of assumptions, but RIM's own documentation covers all of those steps and I'd rather not get sidetracked.)


Downloading and Building Qt

First, put the following line at the bottom of your .bashrc file:

source /opt/RIM/bbndk/bbndk-env.sh

(Seriously, just do it. If you don't, then I don't want to hear all sorts of complaining about how various commands can't be found during the build processes to follow. If you insist on not putting that in your .bashrc, then make sure you run it in every single new shell window you open before doing anything I'm about to discuss.)

Now, time to download and build Qt:

~/pbdev$ git clone https://github.com/blackberry/Qt.git
Cloning into Qt...
remote: Counting objects: 46226, done.
remote: Compressing objects: 100% (29220/29220), done.
remote: Total 46226 (delta 14755), reused 45939 (delta 14468)
Receiving objects: 100% (46226/46226), 158.41 MiB | 832 KiB/s, done.
Resolving deltas: 100% (14755/14755), done.
~/pbdev$ cd Qt
~/pbdev/Qt$ ./configure-qsk arm v7le
 .  .  .
Qt is now configured for building. Just run 'gmake'.
Once everything is built, you must run 'gmake install'.
Qt will be installed into /home/octo/pbdev/Qt/stage/nto/armle-v7/usr/lib/qt4

To reconfigure, run 'gmake confclean' and 'configure'.

~/pbdev/Qt$ make
 .  .  .
~/pbdev/Qt$ make install
 .  .  .

Your first Qt app

Yes, now I'm going to show you how to build/package/install a simple "hello world" application. Once you get past this point, its mostly normal Qt development.

This example application consists of the following files, which I'll describe in detail below:

FileDescription
main.cppsource code for the application
helloworld.proqmake project file
blackberry-tablet.xmlbar descriptor file
icon.png80x80px icon
splashscreen.png1024x600px splashscreen image

main.cpp

#include <QApplication>
#include <QPushButton>
#include <QWidget>

int main(int argc, char *argv[])
{
    QCoreApplication::addLibraryPath("app/native/lib");
    QApplication app(argc, argv);

    QWidget window;
    window.resize(1024, 600);

    QPushButton quit("Quit", &window);
    quit.setGeometry(422, 100, 180, 40);
    QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit()));

    window.show();
    return app.exec();
}

This is a pretty basic Qt sample application so far. The only unique part is the first line, where we are explicitly telling QCoreApplication to add a library path.  This is necessary to enable the application to find the QPA plugin that RIM provides as part of their Qt port.  What is important to note is that the path is relative to the directory the app will be executed from on the device.


helloworld.pro

QMAKE_LFLAGS += '-Wl,-rpath,\'./app/native/lib\''
LIBS += -lbbsupport

SOURCES += main.cpp

package.target = $${TARGET}.bar
package.depends = $$TARGET
package.commands = blackberry-nativepackager \
    -devMode -debugToken ~/debugToken.bar \
    -package $${TARGET}.bar -arg -platform -arg blackberry \
    blackberry-tablet.xml $$TARGET \
    -e icon.png res/icon.png \
    -e splashscreen.png res/splashscreen.png \
    -e $$[QT_INSTALL_LIBS]/libQtCore.so.4 lib/libQtCore.so.4 \
    -e $$[QT_INSTALL_LIBS]/libQtGui.so.4 lib/libQtGui.so.4 \
    -e $$[QT_INSTALL_LIBS]/libQtOpenGL.so.4 lib/libQtOpenGL.so.4 \
    -e $$[QT_INSTALL_LIBS]/libQtNetwork.so.4 lib/libQtNetwork.so.4 \
    -e $$[QT_INSTALL_LIBS]/libbbsupport.so.4 lib/libbbsupport.so.4 \
    -e $$[QT_INSTALL_PLUGINS]/platforms/libblackberry.so lib/platforms/libblackberry.so

QMAKE_EXTRA_TARGETS += package

This file does a lot of important things:
  • Configures the linker to hard-code the path, relative to the directory the app will be executed from, where the Qt libraries will be installed
  • Includes the "bbsupport" library, which allows the app to interface with the device in a Qt-friendly way
  • Adds a special make target ("make helloworld.bar") that builds a BAR file with the following characteristics:
    • Development-mode build, using a debug token
    • Passes command-line arguments to use the "blackberry" QPA plugin
    • Bundles all the resources and libraries our app may need

blackberry-tablet.xml

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<qnx xmlns="http://www.qnx.com/schemas/application/1.0">
    <id>org.demo.helloworld</id>
    <filename>helloworld</filename>
    <name>Hello PlayBook</name>
    <versionNumber>1.0.0</versionNumber>
    <description>Hello World Example Application</description>
    <copyright>2011</copyright>

    <initialWindow>
        <systemChrome>none</systemChrome>
        <transparent>false</transparent>
        <autoOrients>true</autoOrients>
        <aspectRatio>landscape</aspectRatio>
    </initialWindow>

    <publisher>Logicprobe.org</publisher>
    <permission system="true">run_native</permission>
    <category>core.games</category>
    <icon><image>res/icon.png</image></icon>
    <splashscreen>res/splashscreen.png</splashscreen>
</qnx>

The descriptor file is pretty standard for the PlayBook, and described in far greater detail within RIM's own documentation. The graphics are not provided here, but you can use any appropriately sized PNGs of your choosing. If you omit the splash screen, remember to remove it from the descriptor file as well.

Building and installing

~/pbdev/helloworld$ ../Qt/stage/nto/armle-v7/usr/lib/qt4/bin/qmake
~/pbdev/helloworld$ make
qcc  .  .  .
qcc  .  .  .
~/pbdev/helloworld$ make helloworld.bar
blackberry-nativepackager  .  .  .
Info: Package created: helloworld.bar
~/pbdev/helloworld$ blackberry-deploy -installApp -device 192.168.1.42 -password foobar helloworld.bar
Info: Sending request: Install
Info: Action: Install
Info: File size: 6646238
Info: Installing ...
Info: Processing 6646238 bytes
Info: Progress 0%...
Info: Progress 21%...
Info: Progress 97%...
actual_dname::org.demo.helloworld.testDev__helloworld32c52fe1
actual_id::testDev__helloworld32c52fe1
actual_version::1.0.0.0
result::success

And that's all there is to it! If the size of the BAR file bothers you, try experimenting around to see if you can get away with including a smaller subset of the Qt libraries or building Qt with fewer features. However, the bulk of that size is from QtCore and QtGui.

18 comments:

Gatsu said...
This comment has been removed by the author.
Nickoto said...

Hey, this is a great tutorial on getting set up to build the Qt Libraries and a first application. Thanks for sharing it! I'd like to link the README to this post if that's okay with you.

Goldy Blank said...

Hey,
Can you zip the project files and share so that I can download and try running it myself?

Much obliged.

pelegri said...

Hi there. Want to contact me to talk about Qt on BBX? Tried to reach you at your AOL contact - I'm @pelegri on twitter, and pelegri.wordpress.com...

Anonymous said...

Great tutorial, thank you so much for this. Agree the size of the bar is substantial but I would hope that eventually RIM would see value in packaging Qt as part of the OS.

mb said...

nice post mate :)

octo said...

To those of you trying to follow up with me, I've fixed my contact info in my profile.

Yes, feel free to link to this blog from wherever you'd like. If there are better/easier/simpler ways of doing anything I discuss, feel free to let me know.

About the project files, I've actually posted the full text of everything within the post itself (except some PNGs), so you really just need to do copy/paste.

maetis said...

"Windows probably has more differences"

Indeed ! I was forced to update the source code of configure.exe in order to build QT (x86).

I am now able to build QT with MinGW32 on Windows but "mingw32-make install" command doesn't work fine...

I've installed manually QT in NDK workspace and built your sample. But when I launch the application on the simulator I don't see the windows which I am supposed to see...

incognito said...

Nice instructions, worked from first.
I have a question though, have you tried to build the demo code that comes with it?
I tried to build for example the "boxes" project but no luck. When I try to make it the compiler complains about a series of GL_XXX defines in glbuffers.h file.

kreflex said...

Very nice tutorial, thank you.

In the qt version I installed I do not find "bbsupport" lib!!!

have you any idea about that?

many thanks by advance.

Anonymous said...

trying to make the helloworld, I get the following error:

cannot find -lbbsupport

Where is the path for this lib?

Thanks

Anonymous said...

Yup, same problem as above: no libbbsupport library. It looks like it should be in the same dir as all Qt libs but for some reason it's not there. Did you try to build Qt app with recent NDK/Qt from Git?

Anonymous said...

I'll add my voice too, libbbsupport.so is missing!

Searching the net did not help either :S

Anonymous said...

FOUND A SOLUTION !!!

First of all:

You no longer need libbbsupport.so, so remove the line LIBS += -lbbsupport from the .pro file.

Finally:

Add the following the .xml file:






That is it folks!

Tested with lates Git snapshot from Blackberry's Qt repo, as of this date (5/Feb/2012).

Have fun :)

Anonymous said...

Ooooops, XML:

< env var="QT_DEBUG_PLUGINS" value="1" / >
< env var="LD_LIBRARY_PATH" value="app/native/lib" / >
< env var="QT_QPA_FONTDIR" value="/usr/fonts/font_repository/liberation" / >
< env var="QT_QPA_PLATFORM_PLUGIN_PATH" value="app/lib/platforms" / >

Norm said...

Awesome! Thanks for the tutorial (and thanks to the commentors for the mods)

I'm a total Qt/BBNDK/Linux newb. (Me windoze dev). Got a playbook recently and want to play...

Started yesterday evening, got vmware player, kubuntu, updates, installed bbndk, Qt, followed all instructions here and I'm lookin at a quit button on my PB.

Thanks!

best online casino said...

fantastic blog snapshots http://onlinecasinoworld.weebly.com casino games online

Pranjal Gandhi said...

Hey !!
I need the Qt4.0 library for development in momentics IDE on MAC OSX Mavericks.
I edited the bashrc file, successfully executed the first command and downloaded the Qt library. The problem I am facing is in configuration command. It gives me this response after I execute ...

bash-3.2# git clone https://github.com/blackberry/Qt.git
Cloning into 'Qt'...
remote: Reusing existing pack: 615184, done.
remote: Total 615184 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (615184/615184), 420.63 MiB | 187.00 KiB/s, done.
Resolving deltas: 100% (496057/496057), done.
Checking connectivity... done.
bash-3.2# cd Qt
bash-3.2# ./configure-qsk arm v71e
bash: ./configure-qsk: No such file or directory
bash-3.2# ls -l
total 16
drwxr-xr-x 13 root staff 442 Mar 24 15:09 .git
drwxr-xr-x 4 root staff 136 Mar 24 15:09 QtCascadesModels
-rw-r--r-- 1 root staff 327 Mar 24 15:09 Qt_SRC_REPOSITORY_MOVED
-rw-r--r-- 1 root staff 711 Mar 24 15:09 README
drwxr-xr-x 14 root staff 476 Mar 24 15:09 SocketClient
drwxr-xr-x 20 root staff 680 Mar 24 15:09 screenshots

Please Help !