Tuesday, December 8, 2009

Registering Qt Creator as a Post-Mortem Debugger on Windows

When you install Qt Creator on Windows you are offered the chance to register it as a post-mortem debugger. This means, if your app should crash, you can launch Qt Creator to debug it. Very handy. However, if you forget to select this option when installing you can register it after the event from the command-line:

<CreatorDir>\bin\qtcdebugger -register

Note that you need to be an Admin user for this to work.

Thanks to Robert Löhning at Nokia for the top tip.

Qt Creator 1.3/Qt 4.6.0 Released

Yes, this post is a little late for the party, but you can get the new Qt SDK from here:


This version now ships with the MinGW 4.4 toolset which includes a faster compiler and generates better code.

Oh, and Qt have released a version of the 4.6.0 framework that is built using MS Visual Studio 2008. This means, if you have the relevant MS development tools installed, you can compile your apps using the MS compiler (which might generate even better, smaller code than MinGW but let's not get into that argument now...) This is useful as, previous to this release, you'd have to build an MS version of Qt yourself which was a PITA (it takes hours and gobbles disk space.)

All hail the Trolls!

Monday, November 2, 2009

Qt Creator Keyboard Reference Card

This is very, very useful.

http://kdab.net/qtcreator

Thanks to Nicolas Arnaud-Cormos who posted this on the Qt Creator mailing list.

Tuesday, October 27, 2009

Breakpoint Issue Fixed!

The breakpoint bug has been fixed in the October 27th nightly Windows build.

ftp://ftp.qtsoftware.com/qtcreator/snapshots/2009-10-27/qt-creator-win-opensource-1.2.93-200910270102-setup.exe

Sunday, October 25, 2009

Breakpoint Update

Further to my breakpoint issues, the latest snapshot is a little better - breakpoints don't work the second time you run your application, but they do the third time ... but not the fourth ... fifth is a charm though! You get the idea. :) So, the Trolls are getting there.

Unused Variables

Qt Creator will display unused variables in grey, which I absolutely love. For example:


Once the variable is referenced in the method, the colour will change:


It's little touches like this that make this product a joy to use.

Monday, October 19, 2009

Breakpoint Woes

I am having some serious breakpoint woes with Qt Creator 1.2.92 at the moment. Breakpoints work fine the first time I set them, but once the application has been terminated, attempting to add/remove breakpoints will fail and they are never triggered. This is driving me nuts and only a restart of Qt Creator seems to fix it.

Reproducing this problem is easy.
  1. Fire up Qt Creator and create a new Qt4 Console Application project.
  2. In main() set a breakpoint on the first line of code.
  3. Hit F5 to debug. The breakpoint is triggered.
  4. Quit the application, then set a new breakpoint, or remove the existing one and set it again.
  5. Hit F5 to debug. The breakpoint won't be triggered.
It looks like the second time gdb is started you can only set breakpoints once the application is being debugged. This is all well and good for a GUI app where you may have the opportunity to toggle the breakpoint as your app is running, but for applications such as unit test projects, you don't have time to do this before the application quits!

I find it hard to believe that something so fundamental is broken so if anyone has any hints, I'll be grateful. FWIW I am using the version of gdb that ships with Qt Creator 1.2.92. I have tried pointing this to the 2009.03 version instead, but it makes no difference at all.

Now, what I think is happening is this... when Qt Creator starts a debug session it should apply any breakpoints you've set by registering them with gdb. This explains why, until you debug your app, the breakpoint symbol in your code has a little wait cursor next to it:


When you debug your app the first time this icon changes as Qt Creator successfully applies the breakpoint:


Any new breakpoints you add stay displayed with the wait cursor so it looks like Qt Creator isn't applying them.

Stepping Through Build Errors/Search Results

Built your project and now you need to step through the build errors? Or done a 'Find in Files' and you don't want to use the mouse to cycle through the results? On Windows, hit F6 to display the next error/result or Shift+F6 to display the previous.

Friday, October 16, 2009

Blogger Source Code Formatting

OK, this is nothing to do with Qt Creator but I wanted to share this site that formats source code ready for using in Blogger posts:


The results are pretty sweet:

 #include <QtGui/QApplication>  
#include "mainwindow.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

XP-style Common Dialogs

If you are using Qt to create Windows apps for XP then you might of noticed that the standard file dialogs (e.g. QFileDialog::getOpenFileName) are still using 'classic mode':


If you want XP mode versions then you'll have to add a resource file that contains a reference to a magic manifest file which specifies that your app using v6 of the MS common controls library. This is a similar process to adding an application icon as described in my previous post.

First create a file with a .manifest extension (e.g. MyApp.manifest) containing the following XML:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*' />
</dependentAssembly>
</dependency>
</assembly>

Then create (or edit) your applications resource file (e.g. MyApp.rc) and add the following line:

1 24 DISCARDABLE "MyApp.manifest"

If you haven't done already, add a win32 specific entry to your .pro file that points to your .rc file:

win32:RC_FILE = MyApp.rc

Build your project and you'll now have shiny XP common file dialogs:

Application Icon on Windows

So you've written a cool Windows app using Qt - but hey, it doesn't have an icon! Well, adding one is quite easy.

Simply create a special resource file that contains a reference to the .ico file that you want to use and then add a RC_FILE entry to your .pro file. The resource file usually has a .rc extension, and will look something like this (e.g. MyApp.rc):

IDI_ICON1 ICON DISCARDABLE "path/to/an/icon.ico"

The .pro entry that points to this file should be win32 specific:

win32:RC_FILE = MyApp.rc

Rebuild and hey presto! a nice Windows icon for your app.

You can also give your Linux/Mac applications an icon. More info on this can be found here:

Tuesday, October 13, 2009

Shipping Qt DLLs

If you're using Windows and you want to ship a Qt application then, unless you're statically linking, you'll need to ship some Qt DLL files. Be warned - there are two sets of these files installed with the Qt Creator SDK and only the ones found in the qt\bin folder will work. This set of DLLs have been built using the MinGW compiler, which is the one used by default when you build a project using Qt Creator. However, the set found in the bin folder (and Qt Creator itself) are built using MSVC and are essentially private to Qt Creator - shipping these instead will result in DLL Entry Point Not Found errors when you launch your application.

Now, this begs the question - why is Qt Creator built using MSVC? Isn't MinGW up to the task? Good question. The version of MinGW that ships with the Qt 4.5 SDK is quite an old release and the MSVC compiler generates much smaller files (and arguably generates better code.) I guess the Nokia team wanted to ensure that their flagship tools use the best compiler for each platform.

Whether the forthcoming MinGW update due to be shipped with Qt 4.6 later this year does a much better job or not remains to be seen. It will be interesting to see which compiler they decide to built their toolset with...

Monday, October 12, 2009

Generating Automatic Version Numbers

All of my projects use a special version numbering scheme - major.minor.revision.build - revision is the Subversion revision and build is a build number based on the current date. Whenever I build a project I want this version number to be updated automatically (if it has changed), but making this work using QMake isn't obvious ... but once you know how, it could be used for a variety of different uses.

I have a special Qt-based EXE project that generates the version number by creating a version.h file that looks something like this:

#ifndef VERSION_H
#define VERSION_H

namespace Version
{
static const int MAJOR = 1;
static const int MINOR = 2;
static const int REVISION = 2572;
static const int BUILD = 15280;
}

#endif // VERSION_H

I then #include this header where necessary. The EXE is passed the major/minor version number and the name of the output file (e.g. version.h) and it extracts the SVN revision and generates the special build number. I'll spare you the code - all you need to know is how to ensure this EXE is launched each time I build a project that requires it.

First, I use a subdirs project that contains the version-generator .pro file, ensuring I have a version.exe file to execute. Then, in my main apps .pro file I have something like this:

MAJOR = 1
MINOR = 2
VERSION_HEADER = ../version.h

versiontarget.target = $$VERSION_HEADER
versiontarget.commands = ../version/debug/version.exe $$MAJOR $$MINOR $$VERSION_HEADER
versiontarget.depends = FORCE

PRE_TARGETDEPS += $$VERSION_HEADER
QMAKE_EXTRA_TARGETS += versiontarget

The MAJOR and MINOR definitions are changed by hand when required, the rest is automatic. The key part here is the FORCE keyword - this is poorly (if at all?) documented and ensures that the QMAKE_EXTRA_TARGETS command works every time. Extending this scheme to run additional targets would be simple - create another 'target' type and add it to the list (for example, you may want to launch a shell script that generates some code, etc.)

Getting this to work involved a lot of StackOverflow/Qt-list posts - I hope you find it useful.

Automatically Running Unit Tests

QMake supports a useful post link step via the QMAKE_POST_LINK keyword that allows you to execute a command once your project has been built. One handy use for this is to execute unit tests - simply add something similar to your .pro file:

CONFIG(debug, debug|release) {
QMAKE_POST_LINK = ./debug/$${TARGET}.exe
}
else {
QMAKE_POST_LINK = ./release/$${TARGET}.exe
}

When linking is complete the appropriate EXE will be launched, and your tests will run (note that the above would need to be changed for Unix/Mac builds as the .exe file won't exist - I'll leave this as a lesson for the user.)

You can use this in conjunction with a subdirs project to ensure that your tests are executed whenever any of the code they reference changes.

Tuesday, October 6, 2009

Qt Creator 1.2.91

The latest snapshot of v1.2.91 will group your project source files into Forms, Headers, Resources and Sources which is very useful indeed. Get it here:

ftp://ftp.qtsoftware.com/qtcreator/snapshots/


Monday, October 5, 2009

Running Multiple Unit Tests

Qt Creator supports creating a unit test project but the Qt documentation only describes running a single test. To run multiple tests you need to modify your main function to create an instance of each test object and then call qExec on it. Easy enough, but when you start creating lots of tests it's easy to forget to add the necessary code. I decided to simplify this process and came up with a small header file that you can use to make running multiple tests a breeze.

The code for the header, AutoTest.h can be found below. To use it, simply:
  1. Add a #include "AutoTest.h" to all your QObject-derived test headers.
  2. Add DECLARE_TEST(YourTestClassName) below your class definition.
  3. Change your main.cpp to look like this:

    #include "AutoTest.h"

    TEST_MAIN

Easy. If you still need to supply your own main function (you might have other initialization code in here) then you can run all the tests with the following line of code:

AutoTest::run(argv, argc);

This function will return 0 if all the tests passed.

The source for AutoTest.h:

#ifndef AUTOTEST_H
#define AUTOTEST_H

#include <QTest>
#include <QList>
#include <QString>
#include <QSharedPointer>

namespace AutoTest
{
typedef QList<QObject*> TestList;

inline TestList& testList()
{
static TestList list;
return list;
}

inline bool findObject(QObject* object)
{
TestList& list = testList();
if (list.contains(object))
{
return true;
}
foreach (QObject* test, list)
{
if (test->objectName() == object->objectName())
{
return true;
}
}
return false;
}

inline void addTest(QObject* object)
{
TestList& list = testList();
if (!findObject(object))
{
list.append(object);
}
}

inline int run(int argc, char *argv[])
{
int ret = 0;

foreach (QObject* test, testList())
{
ret += QTest::qExec(test, argc, argv);
}

return ret;
}
}

template <class T>
class Test
{
public:
QSharedPointer<T> child;

Test(const QString& name) : child(new T)
{
child->setObjectName(name);
AutoTest::addTest(child.data());
}
};

#define DECLARE_TEST(className) static Test<className> t(#className);

#define TEST_MAIN \
int main(int argc, char *argv[]) \
{ \
return AutoTest::run(argc, argv); \
}

#endif // AUTOTEST_H

A typical test class header would look something like this:

#ifndef FOOTESTS_H
#define FOOTESTS_H

#include "AutoTest.h"

class FooTests : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void test1();
void test2();
void cleanupTestCase();
};

DECLARE_TEST(FooTests)

#endif // FOOTESTS_H

Apologies for the formatting - haven't worked out how to post decent looking code using blogger yet.

Ctrl+Click

How did I miss this? Hold down the Ctrl key and when you hover over a symbol with the mouse, it changes to a hyperlink - click it to go to the symbol definition. Brilliant!

Qt Creator 1.2.90

There is a Qt Creator Technology Snapshot available - version 1.2.90. It's well worth upgrading. Goodies include #include completion and local symbol rename feature. You can also supply a template to use when creating new .cpp/.h files - the contents of the specified template file are inserted at the top of the file. I have a very simple one that adds the Subversion $Id$ tag. Very handy.

Project Not Linked When Dependent Library Changes - Update

PRE_TARGETDEPS fixes this linking issue. You need to add something similar to the following to your .pro file that uses a static library:

PRE_TARGETDEPS += ../path/to/your/lib.a

This will ensure that if your lib changes (but not the project using it), everything will be correctly relinked.

Bit of a hack, but this is not unusual with qmake. :)

Monday, July 20, 2009

Gdb Typedef Bug - Update

Looks like the gdb typedef debugging helper issue isn't going to be easy to fix:

The type reported by gdb is 'List'. I could resolve this to 'QList' 'manually', However, doing so would generally impact the debugging helper performance as this would need an additional roundtrip for each item in the Locals&Watchers view (and an roundtrip takes several dozen milliseconds even on fast machines, so we are talking about slowing down each 'step' by a second or so.)

You can get a 'nice' display of list2 'manually' by creating a 'Watcher' with expression *('QList'*)&list2 .

I understand this is neither obvious nor convenient, but I am also a bit afraid of the general slowdown.

So for now I am tempted to leave it as it is.
The manual watcher tip is one to remember.

The Qt Bible

If you're new to Qt development then you must buy this book - I really cannot recommend it highly enough.

Sunday, July 19, 2009

Context-Sensitive Help

The Qt help is superb and makes the MSDN help in Visual Studio look like the dog we all know it is (every C++ developer knows that the MSDN has sucked since the MSVC 6 days). However, the context-sensitive help in Qt Creator doesn't always do what you'd expect. For example, if you have a #include selected, F1 will not display the relevant help page, which is a shame.

#include <QString>

Put your cursor between the braces and hit F1. I would expect the QString help page to appear, but instead I get No documentation available. Hardly the end of the world, but little touches like this would add even more shine to an already shiny IDE.

Delete All Breakpoints?

There is no way to delete (or disable) all breakpoints in Qt Creator - they have to be disabled individually. Ack. I would find such a feature very useful.

Debugging Helpers typedef Bug

Debugging helpers are great. They show you the contents of common Qt types such as maps, lists and strings and are invaluble when debugging code. However, a bug exists that means if you typedef a QMap, QList, etc. then the debugging helper won't work. Take the following example:

#include <QtCore/QCoreApplication>
#include <QMap>

#include <QString>

#include <QListv


int main(int argc, char *argv[])

{

QCoreApplication a(argc, argv);

QMap<QString, QString> map1;

map1["Hello"] = "World!";


typedef QMap<QString, QString> Map;

Map map2;

map2["Hello"] = "World!";


QList<int> list1;

list1.append(1234);


typedef <int> List;

List list2;

list2.append(1234);

return a.exec();

}


If you stick a breakpoint on the last line the debugger happily displays the contents of map1 and list1, but not map2 and list2 as they have been declared using the typedef. Now, I use the typedef keyword a lot, so this is a PITA, but it's been reported so I'm sure a fix is in the works.


Debugging With gdb Using A Dell Laptop

When I started out with Qt Creator I had a big show-stopping problem debugging apps on my Dell work laptop. I thought I'd post my original messages to the mailing list in case anyone else suffers from the same problem.

**********

I have Qt Creator 1.1.1 running on Windows XP and I cannot debug GUI apps. As soon as I start the debugger, it stops with 'signal-received' somewhere in C:\WINDOWS\system32\wxvault.dll. Further up the call stack is 'QGraphicsWidget::paintWindowFrame'. Here is what I am getting:

0 wxvault!??0Cwxvault@@QAE at XZ C:\\WINDOWS\\system32\\wxvault.dll 0
1 ?? 0
2 ?? 0
3 ?? 0
4 ?? 0
5 ?? 0
6 ?? 0
7 QGraphicsWidget::paintWindowFrame qgraphicswidget.cpp 2184
8 wxvault!??0Cwxvault@@QAE at XZ C:\\WINDOWS\\system32\\wxvault.dll 0
9 ?? 0
10 wxvault!??0Cwxvault@@QAE at XZ C:\\WINDOWS\\system32\\wxvault.dll 0
11 ?? 0

This is my first day with Qt Creator and not being able to debug is a show stopper.

My version of gdb is the one that ships with QT Creator, v6.8. I can run my app fine with Ctrl+R.

**********

OK, I found the problem - a package called 'Embassy Security Center' by 'Wave Systems'. This comes pre-installed on most Dell's. Instead of uninstalling it (which I'm told will cause me a lot of grief) I stopped the wxvault.dll being loaded with other DLLs by editing
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Windows\AppInit_DLLs

(the DLL was in this list). Removing it makes gdb play nicely.

Unit Test Results In The Application Output Pane

I would find it really useful if when displaying the results of a QTestLib app in the Application Output pane I could double-click on a FAIL! to jump directly to the test that failed. Once you have a lot of tests, this feature would prove to be a real time-saver. FWIW I have used the Boost.Test framework with MSVC in the past and you can do something similar.

For example, consider the following output from a test run (this is copied directly from the Application Output pane in Qt Creator):

********* Start testing of LogFileTests *********
Config: Using QTest library 4.5.1, Qt 4.5.1
PASS : LogFileTests::initTestCase()
FAIL! : LogFileTests::LoadFile() 'entries.last() == LogEntry("Test")'
returned FALSE. ()
LogFileTests.cpp(30) : failure location
PASS : LogFileTests::cleanupTestCase()
Totals: 2 passed, 1 failed, 0 skipped
********* Finished testing of LogFileTests *********

If I could double-click on either the FAIL! line or the line below (LogFileTests.cpp(30) : failure location) and jump straight to the test, I would be very happy.

Compiling a Single .cpp File

Qt Creator won't allow you to compile a single .cpp file - you have to build the the entire project - which is slightly annoying. When working on a complicated source file I sometime like to let the compiler rip to make sure it compiles.

However, a fix may be in the pipeline:

Latest Qt Creator Snapshots

If you want to grab the latest version of Qt Creator before it is released to the general public you can grab a copy using FTP from here:


You can also download the Qt Creator source and build it yourself - you can even build a copy of Qt Creator using Qt Creator!


MinGW/gcc 4.4

The current version of Qt Creator (1.2.1) ships with a free compiler based on gcc 3.4.5 which is now 5 years old. This compiler is free, so I can't complain too much, but it generates EXE/DLL files which are much larger than their MSVC equivalents (usually 15%-20% larger, sometimes up to 50%) and, by all accounts, slower code. Qt Creator itself is built using MSVC, and I have also built Qt from source using MSVC in both shared and static forms (details on how to do this next week.) I tend to use the MinGW Qt toolset for debug builds (as the debugging helpers for gdb are better) and the static MSVC version of Qt for release builds.

However, there is a new version of the MinGW toolset which includes a shiny new version of gcc (v4.4). By all accounts this is a much faster compiler that generates better code. This toolset will hopefully ship with Qt 4.6.

Although MSVC is a superb compiler, I don't want to have to depend on it, so I look forward to gcc 4.4. Having versions of Qt built with different compilers is an interesting exercise for the user but is ultimately a pain in the arse to manage.

Note that disabling support for exception handling can mean smaller executables when building with gcc, but I haven't tried this and am not sure how I can specify the relevant compiler options from Qt Creator itself.

Saturday, July 18, 2009

Qt Designer Action Naming

This is a minor niggle... Qt uses camelCase throughout, but when adding menu items using the designer, ampersands are replaced with an underscore - I always end up renaming these.

For example, if you add a menu item called E&xit the designer will create a QAction called actionE_xit. Bah. Just ignore ampersands and call it actionExit.

Support For Workspaces?

I'm not convinced about the Qt Creator support for 'sessions'. Currently, if I open a project and it depends on other projects, they won't be opened automatically, and the official advice is to use sessions to manage multiple projects. The problem is that these sessions are not stored in the root project folder and hence can't be added to your version control system. This is a pain. If I am working on a project that contains a number of different .pro files, another member of my team would need to create their own duplicate session in Qt Creator if they wanted to work on the same code.

I think either a simple 'workspace' or 'solution' concept is required that will group projects together, or a way of creating a session file that can be stored in the root folder and added to version control.

Note that that may be a way to do this by hand-editing your .pro files, but I haven't investigated this yet. I think the IDE should perform this task though...

Project Not Linked When Dependent Library Changes

I recently found a bug that was driving me nuts. If you have a project that depends on a separate .lib project, and you change the .lib but NOT the main project, when the main project builds it will correctly rebuild the .lib but will NOT re-link! This means your library changes are not included and you end up confusing both yourself and the debugger.

I use unit tests in a big way (a good thing) and tend to have core code in a .lib which is used by both the main application and the unit test project. One day last week a test failed so I fixed the code in the core lib and ran the tests EXE again ... which built the .lib but as it didn't link with it, the tests failed again. Cue much head scratching.

I posted this to the Qt Creator mailing list.


And at least one other user on the list was having a similar issue.


One suggested workaround was to add a PRE_TARGETDEPS line to the .pro file which I will try when I am back in the office.

Debugging a Project

One feature I would find really useful in Qt Creator would be the ability to right-click on a project and select a Debug option. Currently to debug a project you need to first right-click on the project and select Set Run Configuration before launching the debugger with F5 or via the Debug menu. When you have multiple projects loaded this is a bit of a pain (I always have a main project and a unit test project loaded for example.)

Linking With Release/Debug Libraries

If you have a project that depends on a library project then you'll want the debug version to link with the debug library and the release version to link with the release library. To do this you'll need to edit your main project's .pro file and do something like this:

debug {
LIBS += -L./libfolder -lmydebuglib.lib
}

release {
LIBS += -L./libfolder -lmyreleaselib.lib
}

Note that the first brace must appear on the same line as the configuration name - the following will cause qmake to error:

debug
{
LIBS += ...
}

I posted a question about this on Stack Overflow as well as asking on the Qt Creator mailing list.

Additional Include Folders

If you want to add additional include folders to your projects, then you need to edit the .pro file by hand and add an entry like the following:

INCLUDEPATH += [path]

This is especially useful if like me, you add core code to a separate .lib project but you don;t want to use relative paths in your #include statements.

You can add as many of these INCLUDEPATH statements as you like.

Eventually I'd like to see support for this in the IDE. In fact, I'd go as far as saying the editor should expose lots more additional .pro functionality without the user having to edit these files themselves.

Welcome

Welcome to my Qt Creator blog where I will document my experiences of this superb C++ IDE and framework. I have recently started using Qt Creator and am so impressed that I have decided to blog about it.