In my previous article, I discussed some alternatives to C++ for systems programming. Today, I want to provide an example of why you might care.

Tyler and I recently debated rewriting Fog Creek Copilot in Qt, a powerful, high-level, cross-platform C++ framework. The idea came to us when we started discussing the implications of maintaining four helper applications (Windows Helper, Windows Helpee, Mac Helper, Mac Helpee), each of which shares depressingly little code with the others. Because Qt is fully cross-platform, and, unlike some other toolkits, doesn’t stick out like a sore thumb on Macs, we figured we ought to be able to cut down the number of real code bases to two (and hopefully greatly increase the amount of code shared between Helper and Helpee in the process). To evaluate the practicality of using Qt, I grabbed the open-source version and a copy of C++ GUI Programming with Qt 4 and sat down to write a small demo app (“Virtual SysAdmin”—the only app that simulates a rapid-fire deluge of mindless support emails).

The good news is that I love Qt. As far as C++ frameworks go, I can now say without hesitation that it’s my favorite. Both its low-level and high-level libraries are very well thought-out and easy to use. Its willingness to extend C++ with its signal-slots mechanism effectively makes C++ as flexible as Objective-C, and enables a wonderfully clean MVC implementation compared to any other C++ GUI framework I’ve used. Working in the GUI designer is effortless, and Qt makes the refreshingly correct (and depressingly rare) decision to have its GUI designer generate descriptor files rather than the convoluted C++ code with tons of “DO NOT MODIFY BELOW THIS LINE” comments spat out by other designers. I think I still prefer Cocoa over Qt for Mac-only development, but otherwise, I’d probably pick Qt at the moment for writing an end-user app.

To be suitable for Copilot, though, the framework’s ease-of-use doesn’t matter. What matters is how large the framework is when statically linked. Qt, sadly, falls flat. I worked with the Qt mailing list to get a small version of Qt, but, even following their advice, I was only able to shrink “Hello, world” to about 2 MB—well more than double what Copilot has to be with all of its code and data files. That is, sadly, a deal-breaker. (I admittedly have not yet had a chance to play with qconfig as suggested late in the thread. If that substantially changes things, I’ll be happy to post again, but I’ve dedicated enough time to compiling Qt for the time being and need to focus on other things.)

What makes me sad, though, is that the bloat in a “Hello, world” app isn’t entirely Qt’s fault. Some of it may be; it’s possible that the framework really does have that many interdependencies. But an equally likely culprit is the C++ language and linker.

Back in 1996, when I was 13, had just learned Squeak Smalltalk, and was trying to get into lower-level languages, I picked up a copy of Delphi 3. Delphi is (or at least was) based on Object-Pascal—basically Turbo Pascal with a lot of additional object-oriented extensions (including interfaces and COM support) and a powerful run-time library to support introspection. Delphi 3 had a rich framework that was extraordinarily similar to Qt. It had the same way of building forms, a nearly identical class hierarchy, and, though not having a concept quite as powerful as signals and slots, had an event system that bears more than a passing similarity to the Qt-comparable event system in .NET. (Hardly a coincidence, since Anders Hejlsberg, who designed Delphi, went to Microsoft to work on J++ and later C#.) Yet despite Delphi’s similarity to Qt in features and capabilities, its executables were far, far smaller. “Hello World” in Delphi comes in at about 100 kB, give or take. A fairly full-featured app I wrote at the time that tells you what kind of rock you’re looking at comes in at a heftier, but still petite, 300 kB. Other Delphi apps I wrote at the time have similarly small sizes.

Part of the reason that Delphi apps could be so small was that the Borland compiler did a spectacular job compared to the likes of GCC/MinGW, which is what I was using for tests. But in turn part of why it could do such a stellar job is that the Delphi language made it easy. Object files had rich metadata that made it easy for the linker to find and remove dead code. Certain facets of the language, such as having native strings, sporting a simpler, more consistent object system, and lacking templates, meant that the linker frequently had less total code it needed to sift through. The generally higher-level nature of Object Pascal also meant that the compiler could do a better job reasoning about what the code was actually trying to accomplish, allowing it to make superior optimizations earlier on. All of these features combined made for a system that could simultaneously deliver a rich object framework without giving up small executable sizes and without requiring a massive DLL. C++, at least in its current form, simply can’t achieve the same performance.

Would Qt be small enough to be viable if only it were written in a different language? I honestly have no idea. But from experience, I can only imagine that, at the very least, it would have helped.