Achtung sehr technisch. Ich schreibe diesen Eintrag hauptsächlich aus Eigennutz, denn ich muss irgendwie festhalten, wie man die Cairo-Bibliothek compiliert. Ich habe dafür unübertriebene drei Stunden gebraucht und das will ich beim nächsten mal unbedingt verhindern. Cairo ist eine quelloffene 2D-Vektorgrafik-Bibliothek für Entwickler. Im wesentlichen kann man damit Linien, Dreiecke, Vierecke und Mehrecke (also Kreise, Texte und beliebeige Polygone) zeichnen. Und das ganze wahnsinnig performant und gleichzeitig plattformunabhängig. D.h. für Windows: keine GDI Odyssee und auch keine GDI+ DLL-Hölle.

Die derzeit aktuelle Version ist Cairo 1.10 vom 25. September 2010. Das Ziel ist ein Kompilat in eine einzige DLL (die man einfach zusammen mit der Anwendungs-Exe weitergibt) unter Visual Studio 2010. Nun wäre die Geschichte kein Krampf, wenn es sich bei Cairo nicht vorrangig um ein Linux-Projekt handeln würde. Die Windows- Unterstützung ist also allenfalls rudimentär.

1. Doch fangen wir von vorne an: Benötigt wird natürlich erstmal der Cairo-Quelltext. Ebenfalls herunterzuladen ist das aktuelle Pixman-Paket. Darin sind die absoluten Low-Level Routinen für Cairo zu finden. Weiterhin bestehen Abhängigkeiten zur zlib (aktuell v1.2.5) und zur libpng (aktuell v1.4.4). Während sich letztere beiden mit einer Visual Studio-Solution bauen lassen, sind bei Pixman und Cairo nur Makefiles mitgeliefert. Die sind allerdings zu kompliziert für Microsofts NMake, so dass man sich am besten MSYS mit einem richtigen Make installiert. Tja. Nur dass die MSYS-Leute ihr System in einzelne Archive verpackt deployen. Anstelle sich 500 Einzel-Archive herunterzuladen und zu entpacken, empfehle ich das MozillaBuild-Paket. Da kriegt man zwar noch einiges mehr, aber wenigstens läuft das ganze dann und scheitert nicht an einer fehlenden DLL.

2. ZLib bauen ist recht einfach über die Solution im Contrib-Ordner. Wir wählen die statische Variante (zlibstat) in der Releasekonfiguration. In den Projekteigenschaften sicherstellen, dass die Codegenerierung auf Multithreaded (MT, wir wollen keine Abhängigkeiten in die Microsoft CRT!) eingestellt ist und los gehts. Die libpng liefert eine VS2010-Solution mit, die ist aber doof konfigiert. Also die 7.1er wählen und upgraden. Release-Konfiguration wählen, das Verzeichnis der aktuellen zlib als zusaätzliches Includeverzeichnis angeben, Codegenerierung auf MT umstellen und in den Präprozessor-Direktiven des Compilers "ZLIB_WINAPI" hinzufügen, denn wir wollen die zlib später nicht als externe DLL sondern direkt in Cairo.

3. Pixman bauen. Hier kommt das erste Mal unser neu erworbenes Make aus dem MSYS-Package zum Einsatz. Zumindest wenn das Makefile.win32 schon perfekt wäre. Ein Änderung ist noch nötig, da wir die MS-CRT ja nicht als Abhängigkeit haben wollen: in Zeile 21 zu den CFLAGS ist wiederum der Schalter -MT einzufügen. Dann gehts auch los: start-msvc10.bat von MozillaBuild starten, in der erscheinenden bash zum pixman navigieren und "make -f Makefile.win32 CFG=release" führt zum Glück.

4. Cairo fit machen. In der bash zu Cairo/src navigieren und "make -f Makefile.win32 CFG=release" eingeben. Was nun kommt sind Fehlermeldungen. Tjo. Das Makefile für Windows ist ein nicht gepflegter ungetesteter Trümmerhaufen. Zunächst einmal fehlt die Datei cairo-features.h. Diese sollte in einem Make-Lauf erstellt werden. Die passende Regel wird aber offenbar nie angestoßen. Etwas Suche in den Sourcen offenbart wie sie aussehen sollte (am besten einfach kopieren und einfügen):

#ifndef CAIRO_FEATURES_H
#define CAIRO_FEATURES_H 1

#define CAIRO_HAS_WIN32_SURFACE 1
#define CAIRO_HAS_WIN32_FONT 1
#define CAIRO_HAS_PNG_FUNCTIONS 1
#define CAIRO_HAS_PS_SURFACE 1
#define CAIRO_HAS_PDF_SURFACE 1
#define CAIRO_HAS_SVG_SURFACE 1
#define CAIRO_HAS_IMAGE_SURFACE 1
#define CAIRO_HAS_RECORDING_SURFACE 1
#define CAIRO_HAS_USER_FONT 1
#define CAIRO_HAS_INTERPRETER 1

#endif

5. Reparatur und Anpassung der Makefiles. Src/Makefile.sources ist nicht nur für NMake zu kompliziert sondern auch für MSYS zu proprietär: Im Notepad öffnen und suchen und ersetzen nach if mit ifdef. build/Makefile.win32.common öffnen und in Zeile 20 die MS_MDFLAGS von -MD nach -MT umstellen (beim Debug analog auf -MTd aber ich erstelle hier nur das Release). Im folgenden sind zwischen Zeile 25 und 37 einige Pfade hart codiert. Diese sind an die tatsächlichen Gegebenheiten anzupassen. Insbesondere haben sämtliche Abhängigkeiten bei mir eine Versionsnummer im Pfadnamen. In Zeile 40 zu den DEFAULT_CFLAGS noch die Option -DZLIB_WINAPI anhängen, weil die zlib ja statisch in die DLL soll.

6. Patchen der Sourcen für den VC++-Compiler, da dieser keine Implementierung von lround in math.h kennt. In cairoint.h die Zeile 955 so erweitern, dass dort #if DISABLE_SOME_FLOATING_POINT || defined(_MSC_VER) steht. In cairo-misc.c in Zeile 486 dieselbe Erweiterung vornehmen.

make -f Makefile.win32 dynamic CFG=release

7. Et voila. Eine cairo.dll von knapp 1 MByte ohne extravangante Abhängigkeiten aber mit der Fähigkeit PNGs und PDFs zu erzeugen. Hoffentlich wird das mit der nächsten Version etwas einfacher.