C-Made

I’ve been setting up CMake build files for Doomsday in the cmake-build branch. This has been quite an undertaking because Doomsday has about 50 individual components to build. (Mind you, some of those are tests and tools.) Not having done anything substantial with CMake in recent years, it was very useful to really jump into the deep end and get familiar with CMake version 3. While setting up the build for all the components on OS X, Windows, and Unix I gained a real understanding of CMake as a scripting language and now feel quite comfortable with how it operates.

After the switch to Qt, we started using qmake to generate the build files. While this has been a working solution, qmake is not the most advanced or well-rounded tool. It naturally has fully integrated Qt support, however it lacks in the scripting department and does not support many output formats. This has forced us to set up various helper scripts to deploy and package the built binaries. Considering that these are platform-dependent, it has added to the maintenance costs and generated substantial inertia when considering potential changes to the component structure of the project.

Using CMake solves all of these issues and provides additional benefits, too.

Native IDEs. One big issue with qmake has been poor support for the biggest native IDEs: Visual Studio and Xcode. When doing debugging it is crucial to be able to use the platform’s native tools, and this has not been easily possible with qmake. Also, people have tendency to favor one IDE over another, so being effectively forced to use Qt Creator has not been ideal.

Modularity. One of the long-standing issues I wanted to tackle with CMake was to enable modular builds. Since Doomsday comprises several libraries, plugins, tools, tests, and applications, it would be extremely beneficial if one could only build the relevant components instead of everything at once. I’ve set up the new CMake projects so that they allow building and installing libraries (including the full Doomsday SDK) separately, so that one can for instance focus on the client and server executables. Tools and tests are also both completely separate from the main applications. In general, any one project can be built separately if its dependencies have already been installed.

Build options. One of the great features of CMake is offering a clear way to set build options. There is even a GUI for this. One can now easily enable or disable certain features (like tests or debugging checks).

Dependencies. Doomsday has a number of required and optional dependencies, such as SDL 2, FMOD Ex, and the DirectX SDK. CMake is smarter than qmake when it comes to finding these (i.e., qmake only handles Qt, leaving everything else up to custom scripting), and one can provide clearer guidance as to what is missing and what to do to fix it.

Tools. All tools are now fully platform independent and buildable as part of the entire project; previously wadtool was only compilable on Windows. This was possible thanks to the modular setup of the shared libraries: all of them are now available to be used in any of the components in the project. (wadtool was relying on Windows-specific file APIs, but we have equivalent portable routines available in liblegacy.)

Documentation. Amethyst is now incorporated into the build, instead of being run from the autobuilder scripts. This is good because a regular build produces a more complete set of installed products, and in the future we can use Amethyst for generating additional kinds of documentation, too. Amethyst is also one of the tools that come with the source package, and can be built with CMake just like all the other tools.

Deployment. The task of deploying fully-functional binaries is very different on Windows, OS X, and Unix operating systems. Fortunately, CMake comes with a portable packaging tool called CPack, which allows generating installation packages in various formats with very little effort — assuming the CMake build itself has been set up correctly.

Code signing. One issue I ran into with deployment was the OS X code signing requirement. Code signing seems to be evolving rapidly on OS X, and even the latest versions of CMake don’t seem to fully support it. Furthermore, Doomsday’s bundle structure is not exactly conventional and Qt’s macdeployqt utility is also in the mix. Consequently, I had to set up the required code signing manually for the various executables, frameworks, and libraries included in Doomsday.app and Doomsday Shell.app. During this I learned valuable lessons about exactly when CMake evaluates variables in custom install logic. Particularly, CMAKE_INSTALL_PREFIX should not be evaluated during configuration because then CPack will apply the custom logic in the right directory — the install prefix is differently for packaging and regular installation.

Snowberry. An open question remains with regard to Snowberry. I really would like to avoid incorporating the existing Snowberry packaging scripts into the new CMake project, because they depend on obsolete versions of wxPython and py2exe/py2app. I have been putting off upgrading these since Snowberry is slated for removal. I would rather improve Doomsday’s own add-on/resource pack configuration UI than spend any time enhancing Snowberry. Besides, Doomsday 1.15 is usable without Snowberry although external resources can only be loaded manually via the console prompt.

Qt 5 required? I’ve also been considering that supporting Qt 4 is no longer necessary, particularly if Snowberry is out of the picture and CMake is used for handling the full build and packaging. One can certainly configure either Qt 4 or 5 in CMake, but I would welcome the chance to avoid adding any additional complexity to the build rules.

It will still take a while before cmake-build can be merged to the master, however it is certainly one of the first things to take care of after 1.15 has been released. For now I’ll start using CMake for my daily development. This will particularly help with debugging, since I can fully utilize Xcode and Visual Studio as needed.