Archive for the ‘Uncategorized’ Category

Library versioning

18th November 2015

Do you maintain or contribute to a library, especially a KDE library (other than the Frameworks)? If so, I have a question for you.

First, some background. These days, the norm for libraries is to follow some variation of semantic versioning, where the version number follows the scheme x.y.z (eg: 1.4.3) and it should always be safe to upgrade the library to version with a higher y (minor) component as long as the x (major) component is the same. Qt follows this scheme, for example.

This scheme doesn’t really allow for alpha versions of software, though – the alpha releases for the (x+1) major version can be incompatible with both version x and with the final releases of version (x+1). The Semantic Versioning scheme prescribes using versions like x.y.z-alpha1, but this breaks the nicely numeric scheme we had, and not all tools can cope with that.

KDE Frameworks (and, in the past, kdelibs) approached this by defining some arbitrarily high minor version (typically 90+) to indicate pre-releases for the next major release. So the pre-release Frameworks were numbered like 4.90.1.

So where is all of this going? Well, CMake provides a helpful function to write package version information files that allow find_package() calls to only find compatible versions. So if you use the SameMajorVersion scheme, find_package(Foo 4.3) will find Foo 4.3.0 and Foo 4.5.2, but not Foo 4.2.5 or Foo 5.1.1. However, if project Foo uses the “high minor = next version prerelease” scheme, it will also find Foo 4.90.1, which is not compatible with Foo 4.3.

I wrote a SameMajorVersionWithPreleases scheme that would deal with this for Extra CMake Modules, but never committed it because I wasn’t sure if it would get used (KDE Frameworks doesn’t need it because we put KF5 in the package names). My question is: would your project find this useful? In other words, do you contribute to (or know of) a CMake-based project that uses the “high minor = next version prerelease” scheme I described above? If so, please comment!

CMake Conditionals

16th May 2014

[edited 17/04/14]

CMake has many wonderful features. However, CMake’s if() command handles variables in a way that can often trip people up. In particular, comparison operators like STREQUAL try to interpret their arguments as variable names, and only treat them as actual strings if there is no matching variable. Combined with the fact that basically any string you can write in a CMake file is a valid variable name, this can lead to some subtle bugs.

This script highlights all the potential pitfalls I could think of. The “FATAL_ERROR” branches are the ones that will not be taken, but many of them are ones you might expect to be taken if you either didn’t have a solid grasp of how if() parses its arguments or if you weren’t aware of what variables had been defined.


KF5 Sprint in Barcelona

6th May 2014

Two weeks ago, I landed back in my home country after spending a long weekend in Barcelona for the KDE Frameworks 5 sprint. It was a tiring weekend, but fun and productive.

I arrived in the early evening of the first day, happening to reach the door of the Blue Systems office at about the same time as Kai Uwe Broulik. This was after the discussion about what tasks needed completing had happened, so we both were greeted with a board full of post-it notes. I snuck a few more onto the board when Kévin Ottens wasn’t looking, as there were some failing autotests that needed fixing before another release happened, and I felt we needed to have a proper discussion about where we were installing things (having seen that Kubuntu were patching the KDEInstallDirs module of Extra CMake Modules).

That first evening, I mostly committed some changes that I’d been waiting for approval on, and either finished or delegated the last few parts of the “removing references to KDE4” task that I’d been working on. We went out for a very nice dinner, and sometime after midnight, Kai, Mark Gaiser and I headed to the apartment we were sharing to sleep.

The next day, Kai set off early to see his old school choir, who happened to be on tour to Barcelona, and beat Mark and I to the office (we rocked up around 11am, having been breakfast-shopping before going back to the apartment to eat). I pinned people down for approval on several things I’d had sitting on my hard drive or on Review Board for a while, clearing out my backlog of “completed but not yet committed” tasks. This included a lot of improvements and clean-ups for Extra CMake Modules.

Most of Friday afternoon and evening, however, was spent trying to understand the KItemModels unit tests and figure out why one of the tests was failing. I eventually determined that the pattern of signal emission when moving rows around had probably changed between Qt4 and Qt5, and the fix was fairly simple. I also found time to apply at least a temporary fix to a KImageFormats unit test that was failing on i386, and take part in discussions on install paths (with David Faure and Aleix Pol) and the Framework metadata files (with Kévin, Aurélien Gâteau, and Aleix). I didn’t have the energy to join in the release cycle discussion, although I subsequently decided that Extra CMake Modules would tend to release in sync with Frameworks (largely because David Faure has kindly agreed to deal with the ECM release process if it does), but won’t necessarily have a new release for every Frameworks release.

The install paths discussion resulted in the decision that “kf5” (or, indeed, “kde5”) shouldn’t appear in paths that we expect applications to use (such as where applications install plugins for their own use) – application versions are not necessarily related in any way to KDE Frameworks versions. As a result, we altered a bunch of paths in KDEInstallDirs, and added some KF5-specific variables for the use of the frameworks themselves, as well as making sure some other framework-releated directories were properly versioned. Aleix and I worked through the resulting tasks throughout Saturday. One nice outcome of these changes was that we moved a step closer to deprecating KPluginLoader: it is no longer needed to find plugins installed using the variables in KDEInstallDirs, and other than that it mostly provides plugin versioning (as in a version number for the plugin or plugin interface), which could be upstreamed to QPluginLoader.

In the metadata file discussion, we decided to rename the metadata files from <framework>.yaml (eg: kconfig.yaml) to the more consistent metadata.yaml (which is easier for scripts to find). We also decided that these files would be the canonical location for information such as the maintainer, tier (an indication of a framework’s dependencies) and lifecycle (yet-to-be-released, actively developed, deprecated, no-longer-released), and so set out a list of fields they needed to contain. Kévin and Aurélien did most of the work of implementing these changes, I believe.

As well as dealing with install paths and other coinstallability issues, I spent part of Saturday adding a section to the KDE git manual called Advanced Git. This details how to merge history between repositories, including use of git-filter-branch. I’ve ended up doing a lot of these merges for KDE Frameworks as we’ve realised files have ended up in the wrong repository, and had to pick it up as I went along, learning from my mistakes. Hopefully this will make it easier for other people.

Having been noticably short of sleep on Saturday (getting into the office late doesn’t mean waking up late, and I’d only left the office at 2am on Friday night), I got an early night in, so I would be refreshed for Sunday, which mostly involved similar tasks to Saturday. We got all the coinstallability tasks done by early Sunday afternoon, and I spent the rest of the day working on the failing unit tests for the SoftImage PIC format plugin in KImageFormats. In the end, I completely rewrote the plugin using QDataStream, ensuring it would handle endianness correctly (which the old code emphatically did not), and that wasn’t finished until last Friday.

All in all, it was a successful sprint, and it was great to meet the people I’d been working with over the last several months. Bring on KDE Frameworks 5.0!

The Ada Initiative

17th February 2011

LWN has an interesting article on a new startup: The Ada Initiative (“Supporting women in open technology and culture”), and about how it is taking a different approach to similar initiatives.

The link above is to an article on the LWN that is subscriber-only for the next week.  Being a subscriber, I can provide a link that you can use – if you are interested in what’s happening in Linux, and FOSS in general, I highly recommend subscribing.

There is also other press coverage.

Also, I would suggest that the founders do Ada Lovelace a disservice in calling her “the world’s first woman open source programmer” – she is arguably the world’s first programmer, full stop.

The Magic of QtDBus, and the PropertyChanged signal

7th September 2010

I’ve had reason recently to delve into the inner workings of QtDBus.  It does more for programmers than I (and probably many of you) realised.

For example, when you tell qdbusxml2cpp to generate a proxy for you, it creates a subclass of QDBusAbstractInterface, and populates it with properties, signals and slots that correspond to the D-Bus properties, methods and slots.  But there’s more going on under the hood than it seems.  In particular, all those annotations for input and output types are used for more than just simple casting of QVariants.

Consider, for example, what happens when you fetch the value of a property of D-Bus type a{sv}.  This is a map from strings to variants.  The natural representation in Qt is a QVariantMap, but it could just as easily be in a QHash<QString, QVariant>, or even something based on std::map.  Qt doesn’t know.  So you can put an annotation in your D-Bus interface specifications, indicating what type it should be represented as:

<annotation name="com.trolltech.QtDBus.QtTypeName" value="QVariantMap"/>

OK, so what does qdbusxml2cpp do with this information?  Well, in this case, we’re annotating a property.  qdbusxml2cpp will produce the following code in the proxy class:

Q_PROPERTY(QVariantMap Foo READ foo)
inline QVariantMap foo() const
{ return qvariant_cast< QVariantMap >(property("Foo")); }

As you can see, it casts a property (which is a QVariant) to a QVariantMap.  But that surely demands that the QVariant already contains a QVariantMap and not, say, a QHash<QString,QVariant>?  Well, there’s some magic in QDBusAbstractInterface to deal with this for you.

Basically, when you request a property (QObject::property()), QDBusAbstractInterface requests it over D-Bus.  If it’s something simple, like a string (D-Bus type s), it gets demarshalled automagically in the internals of QtDBus, giving you a QString in this example.  But if it’s something more complex, like the above a{sv} type, QDBusAbstractInterface looks up the type information in Qt’s meta-object system, and uses that to demarshall it into the correct type – if the property type is QVariantMap, it will be demarshalled into a QVariantMap.

A similar trick is done for signals (note that if you get the signal signature wrong, you will simply never receive the signal).  Sidenote: if you add a QDBusMessage parameter as the last parameter of the slot you connect to a D-Bus signal, you’ll get a copy of the signal message.  You can even just have the QDBusMessage parameter, although you’ll be creating more work for yourself.

So, this is all very nice, but why am I telling you about stuff that “just works”?  Well, you have to watch out for the times when it doesn’t “just work”.  I’ll illustrate just such a case with an implementation of the PropertyChanged signal.

The PropertiesChanged signal is a recent addition to the org.freedesktop.DBus.Properties interface in the D-Bus specification that allows you to receive notifications when a property value changes.  It’s rather new and hasn’t even made it into the released version of the spec yet.  However, it will be supported by the next version of GIO.  Hopefully, it will be supported in a not-too-distant release of Qt (4.8?), but in the meantime you can quite easily add support yourself.

The signal looks like

org.freedesktop.DBus.Properties.PropertiesChanged (
    STRING interface_name,
    DICT<STRING,VARIANT> changed_properties,
    ARRAY<STRING> invalidated_properties);

where changed_properties is a dictionary containing the changed properties with the new values and invalidated_properties is an array of properties that changed but the value is not conveyed.

Now, on the server side, you can’t support it “properly”, because the introspection for the org.freedesktop.DBus.Properties interface is fixed by QtDBus, but you can emit the signal yourself anyway:

QDBusMessage signal = QDBusMessage::createSignal(
signal << "";

QVariantMap changedProps;
changedProps.insert("somestringprop", "newstringvalue");
changedProps.insert("someintprop", 4);
changedProps.insert("somemapprop", newmapvalue);
signal << changedProps;

QStringList invalidatedProps;
invalidatedProps << "invprop1" << "invprop2";
signal << invalidatedProps;


Easy as pie, right?  You can even have a helper method that does this:

void notifyPropertyChanged( const QString& interface,
                            const QString& propertyName )
    QDBusMessage signal = QDBusMessage::createSignal(
    signal << interface;
    QVariantMap changedProps;
    changedProps.insert(propertyName, property(propertyName));
    signal << changedProps;
    signal << QStringList();

On the client side, things are slightly more complex.  My approach is to insert a class into the proxy code heirachy.  While qdbusxml2cpp produces subclasses of QDBusAbstractInterface, I modify these to inherit a class of my own (DBusAbstractInterface) that in turn inherits QDBusAbstractInterface.  This class has all the magic needed to deal with the PropertiesChanged signal.

Essentially, it connects to the PropertiesChanged signal using QDBusConnection::connect(), and forwards this to any listeners.  So far, so simple.  But what happens if we have a property with D-Bus type a{si} (a map from strings to integers)?  Then the changed_properties map will contain an entry mapping the property name to an a{si} value.  How does QtDBus know how to demarshall this?

Well, the fact is, it doesn’t.  QtDBus will demarshall the changed_properties map into a QVariantMap (or whatever appropriate type the second argument of the slot has), but it can’t demarshall any complex types that are values in that map.  Do you want your a{si} map as a QMap or a QHash?  QtDBus doesn’t know, and so puts off the demarshalling by inserting a QDBusArgument value into the map.

If you know what structure you’re expecting here, you can just demarshall it with something like

QMap<QString,int> map;
changed_properties.value("foo").value<QDBusArgument>() >> map;

My helper class does something roughly similar to what QtDBus does internally, and uses the meta type system to figure out how it should demarshall the values in changed_properties.  But just remember that if you have a complex structure passed over D-Bus as a variant (D-Bus type v) and received in your code as a QVariant, the chances are it’ll be in the form of a QDBusArgument, and you’ll have to demarshall it yourself.

The Party of Gno

18th June 2010

I came across an interesting blog post about the FSF’s strategy on LWN, and thought it was worth sharing.

The essential argument is that the FSF does too much preaching about what people shouldn’t do, without offering constructive alternatives.


16th March 2009

I discovered a new option in KMail for displaying email headers today.  I’m not sure how long it’s been there, but you can now select “Enterprise Headers” for your emails:

KMail with Enterprise Headers

KMail with Enterprise Headers

I quite like it, apart from the fact that you can’t have variable-width text in the header and fixed-width text in the body of the email.


13th March 2008

I went to see Spamalot last night in London.  It was an amazing show, happily sending up everything, especially itself.  I would happily go and see it again.  And again.  And again.

Nina Söderquist made a fantastic Lady of the Lake, the petulant diva of the show (well, along with Lancelot…).  Steven Kynman (Historian, Not Dead Fred, lead Minstrel and Prince Herbert) was also excellent, as was Andrew Spillett, who played Patsy (King Arthur’s “horse”).  Alan Dale, who played King Arthur, was a little wooden.  He was fine, but didn’t blow me away.

A special mention has to go to Ian Waller (“Swing”, which I think means dancers), who was the only person to write his biography in the spirit of the show (it starts “Ian started dancing at 7 but by 8.45 was back in bed thinking up a new career”).  Everyone else is far to serious.

The programme also contains a joke based on the subtitles of the original film.  Buy it and find out…

You Won’t Succeed In Broadway (If You Haven’t Any Jews)  was, I’m sure, a hilarious statement about musical theatre in New York.  However, it doesn’t translate very well to the West End of London.  It’s still a good song, but the joke isn’t that funny.

That said, I had an excellent time (right in front of the stage, on row A in the stalls!).  Go and see it!


Get every new post delivered to your Inbox.