Cross Platformity

Cross Platformity

Several years ago we started porting Calligra to Windows. Supported by NLNet. Some time later, Intel also supported KO to create two Windows versions of Krita, one for tablets, one for convertible ultrabooks and later still, a new version of Calligra Words, Stage and Sheets for convertible ultrabooks. Meanwhile, the Krita Foundation has been publishing Krita on Windows and OSX for some time now. That’s a fair amount of experience in puslishing software originally written on Linux on other platforms.

Let’s take a look at the starting position.

Calligra, or rather KOffice, as it was called when it started out, was created to be a native KDE application. Integrated with the KDE desktop environment, using all the features that KDE offers, ranging from inter-process communication to system-tray notifications, shared plugin loading, mimetype handling, and other resource icon locating. These applications are KDE applications through-and-through.

There are also some hidden assumptions in the way KDE works on Linux: for instance, that reading thousands of small files on startup isn’t a big deal. We Linux users are fortunate in having a choice of really good, really fast file systems, compared to Windows or OSX users.

So, on Linux, it’s not that big a deal if people aren’t running the KDE Plasma Desktop, since installing the libraries, the icons, maybe some system settings kcms will mean Krita will run just as well in Gnome as in KDE. It’s a pity that some distributions don’t make Krita depend on the oxygen icon set, and that others think that installing Krita means users need marble, but that’s the way Linux packaging works, or doesn’t work.

Now, there are two reasons for bringing a Linux application to another platform, two ways of going about it and two ways of implementing the port.

You can port an application to Windows or OSX because you want to use it yourself, as a Linux user in exile, or you can port an application to Windows because you want to gain a user-base on Windows.

And you can port an application to Windows or OSX by bringing the whole Linux and KDE environment with you, or by making the application as native as possible.

And finally, you can build on the target platform, with the target platform’s native compilers, or you can cross-compile from Linux.

If you’re porting for Linux exiles, the first approach is fine. It’s what on Windows is done by cygwin, msys, KDE’s emerge tool or KDE’s windows installer. It’s what FINK or MacPorts provide on OSX: a package manager, all the tools you’re used to, all the platform services the application depends on. It’s a big undertaking to maintain ports of so many components, and the porting system will often have temporary failures. I’m not saying that it’s wasted work: I use KDE’s windows installer to get Kate on Windows myself.

But it’s not going to work when you want to build a user base for your application on Windows or OSX. The package managers, the installers are too complicated, too alien and drag in too many unfamiliar things. Even using something as Emerge to build, and then package up the built bits into an installer is problematical, because those bits will still expect the full KDE environment to be available.

And a Windows user is going to freak out when starting an application starts daemons that keep running. No kded, therefore. Their “protection” software (snake oil, but scary snake oil) will yammer when there’s weird inter-process network communication. Bye-bye dbus. For a single application like Krita, a mimetype database is overkill. Loading icons by the hundred-weight, individually gives a bad hit on startup time. And yes, we’re getting nastygrams about the number of files we package with Krita versus the number of files Photoshop packs.

It’s really clear to keep in mind what the goal is. Because if you’re working together with someone else, and they’re of the linuxer-in-exile persuasion, and you’re of the native-user persuasion, conflicts will happen all the time. The first crowd won’t mind using glib in update-mime-database because, what’s the problem? While you’ll hate that requirement because building glib on windows and osx ain’t easy, and it’s a big dependency with a lot of other dependencies that come with it, and all just to be able to figure out that a .jpg file is a jpeg file.

Most ‘native’ Windows applications that use 3rd party libraries includes those libraries in their own source tree, either as dll’s or as source code. It’s easy, you never have to deal with newer versions of libraries breaking your code, you can build everything in one go. For some libraries, it’s even the only way: you cannot build the breakpad library outside the source tree of the application that uses it. But for a cross-platform application that also targets Linux distributions, this cannot be done. You cannot include all dependencies in your source tree.

So, we need to find a way to build all dependencies without dragging in a fake Linux or fake KDE environment. Without dragging in a package manager. One that creates applications that behave as natively as possible.

What we’re currently trying to do is this: build a cmake system that builds Krita’s dependencies and then builds krita. CMake’s external project system works pretty well for this. It’s not as complicated as the Emerge system, though there are similarities, and we’re even re-using patches from Emerge for our dependencies.

Here’s the list of all dependencies we currently build:

  • automoc: needed for kdelibs-stripped
  • boost: needed for Krita
  • bzip2: needed for kdelibs-stripped
  • eigen3: needed for Krita
  • exiv2: needed for kdelibs-stripped and Krita
  • expat: needed for exiv2
  • ffi: needed for glib (only on OSX)
  • gettext: needed for glib (only on OSX)
  • giflib: needed for kdelibs-stripped and qt
  • glew: needed for Krita
  • glib: needed for shared_mime_info (only on OSX)
  • gsl: needed for Krita
  • iconv: needed for gettext and exiv2
  • ilmbase: needed for openexr
  • intltool: for glib (only on OSX)
  • jpeg: needed for kdelibs-stripped, qt and krita
  • kdelibs-stripped: specially hacked up version of kdelibs4 that doesn’t need openssl, dbus and a whole lot of other things.
  • lcms2: needed for krita
  • libxml2: needed for kdelibs-stripped
  • libxslt2: needed for kdelibs-stripped
  • opencolorio: needed for krita, has it’s own 3rd party external projects: tinyxml, yaml
  • openexr: needed for Krita
  • patch: needed on windows only, creates a myptch.exe because patch.exe is banned on Windows…
  • pcre: needed for shared-mime-info
  • perl: needed on Windows to build Qt
  • pkgconfig: needed on OSX to build glib
  • png: needed for Krita and Qt
  • qt: we need to build this ourselves to strip out openssl, qtscript, the database stuff and more, and because we build with a version of Visual C++ that Qt4 doesn’t support out of the box
  • shared_mime_info: needed for kdelibs-stripped
  • tiff: needed for Qt and Krita
  • vc: needed for Krita
  • krita: what we finally want…

And this is what’s still missing:

  • kdcraw: would provide camera RAW import
  • poppler: would provide PDF import and export
  • openjpeg: would provide jpeg2000 import and export.

All this is described here for OSX and here for Windows. My goal is to make a CMake based project that can build everything on OSX and Windows, and on Linux, for Windows in one go. It needs much more work, in fact more time than I actually have… Anything that can slim the number of dependencies would be very welcome!

And now it’s coming full-circle: I actually would like to have installers for Krita that work on Linux, too. Just like Blender or Qt Creator have, a 32 and 64 bits installer that people can download, run and get the latest build of Krita, without weird extra dependencies, without waiting for distributions to pick up the next version of Krita. The system we’re building should be able to provide that…