26 October 2011

Building GTK2 for MyPaint Windows

This post explain more detailed Windows port of MyPaint situation. I hope my english is understandable :)


MyPaint, the package

  • In windows mypaint use py2exe for bootstrapping and bundling with minor change in favor mypaint's builtin logging.
  • Mypaint is currently targeted only for win32, win64 is in experimental stage
  • Mypaint consist of a small portion of C++ library (which is why it need to be compiled) and the rest is in pure python. Mypaint require pygtk (with numpy support), numpy, GTK and optionally a particular version of psyco (a python accelerator)
  • Mypaint is squeezed! I kind of proud with this :) I have made mypaint stay around 8MB since version 0.7. All executable is packed with UPX at brute level. Furthermore brushes preview images have been pngcrush'ed.
  • Mypaint installer use NSIS with solid lzma compression. I believe this should be changed to msi

Building minimal set of patched GTK

   Mypaint use GTK for cross platform GUI library, as tablet interface and for importing images through gdk-pixbuf. As far a I know mypaint didn't employ any complex/fancy text operation thus jettisoning freetype, fontconfig and libexpat/libxml dependencies will squeeze more.

The minimal dependencies:
  • GTK
  • GLib+Libintl which part of Gettext
  • Pango
  • Cairo+Pixman
  • ATK
For your information the build environment in this blog is not derived from official build. Skip this step if you want to get it from official. To compile them we need MSYS+MinGW with msys-perl too. The choice of gcc is up to you, I personally use many version but mostly rely on either TDM's GCC 4.3 or Equation's GCC 4.6.
I'll not talk about it here, please refer to MinGW documentation.

Consideration of the Windows' Way
    It seems safe for me to say that the idea of centralized GTK runtime is obsolete. Almost every Windows GTK apps bundling its own runtime now. So packager has some freedom on how to build it.

Static or Dynamic?
    When a library is an orphan (not depend on other but required by only one library) this will be better if being build as static lib. For ex. pixman. In windows fewer dlls is always better even if possible as a single executable to avoid DLL hell. This is of course the opposite of linux since windows lack of dll versioning even when it has (SxS) it also has drawbacks.

As modules or not?
    For built-in modules (GTK, GDK-Pixbuf, Glib and Pango have it) which often depend on text (configuration) files they should be included in main dll (static link). Maintaining the correctness of those config files using provided *-query.exe command line tool is painful. Therefor better sacrifice a little loading time for compactness.
    However for non built-in modules such as svg loader or glib networking we still require those config files. And this how we do the right but strange way (I once ask Tor in irc but he just said "that's a bit complicated to explain" :)) set the correct value for PREFIX by reading readme.win32 in GTK+ source package. That is for.ex: HEX=`echo gdk-pixbuf_2.24.0-1_win32 | md5sum | cut -d' ' -f1` then in your configure line use --PREFIX=/c/GTK/$HEX. If we don't do this way GTK will complain whenever we move around our apps location. For example if I build svg loader (to make mypaint load SVG file of my CAD drawing) then loaders.cache (formerly gdk-pixbuf.loaders) should mention:
"c:/GTK/24657c578dad0b54d4855b1780ade31a/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.dll"
instead of the correct path to libpixbufloader-svg.dll

Compiler's flags
    Personally I favor small size over negligible performance boost. I am not fancied by long complex optimization flags which I often found silent brokenness during runtime.
export PATH+=":/c/GTK/bin"
export CFLAGS="-Os -mtune=pentium3
-I/c/GTK/include"
export LDFLAGS="
-L/c/GTK/lib -Wl,-s"
export PKG_CONFIG_PATH="c:\\GTK\\lib\\pkgconfig"


Compiling Glib:

    Glib require intl which is part of BIG Gettext package which require iconv which is available in two flavor: the regular gnuiconv or winiconv (I choose the latter cause smaller and native). Gettext also required to build localisation files (those .mo file). So grab all gettext and zlib packages here.
    Glib is the core dependency for many GTK related libraries therefore I choose to use CFLAGS "-O2" where otherwise I use "-Os". Wait.. there is one funny problem before we start, pkg-config! this configurator need Glib as well as Glib need pkg-config, luckily someone already made the static msys version here http://ingar.satgnu.net/devenv/mingw32/files/msys-pkg-config-0.23-static.zip (put in msys\bin)
    Extract Gettext to c:\GTK, extract Glib to let say d:\sources then launch msys terminal and go there (cd /d/sources/glib-x.x.x). Type:
"configure --prefix=/c/GTK [enter]" then "make -j2 install [enter]" then "make -j2 check [enter]" if configure failed we could read config.log and if make check report failed test(s), be alarmed...

Compiling Cairo:

    Cairo require pixman which is an orphaned dependency. Pixman has optimization of CPU instructions (MMX and SSE2 in x86) that will autodetected during configure, note that you could always see all configuration's options by typing "configure --help [Enter]". So be careful when targeting your audience otherwise MyPaint won't run at all. Let say our painters use at least an old athlon / PIII. This way we should disable sse2 optimization. For pixman use: "configure --enable-static --disable-shared --disable-sse2 --prefix=/C/GTK". Cairo is required for rendering by GTK and Pango, as we don't need GObject Introspection or other fancy features we can use: "configure --disable-gobject --disable-interpreter --disable-pthread --disable-ft --disable-fc --prefix=/C/GTK"
    "Make" procedure is same as Glib above. Compile pixman first and then cairo

Compiling Pango:

    Pango handle text, glyph and stuff. As I said earlier we will avoid using freetype so if you somehow had it in c:\GTK then you'll need to rename c:\GTK\lib\pkgconfig\freetype2.pc because no option to manually disabling it but it will compile just happily.
    Pango font selection is governed by etc\pango\pango.alias which if missing (special case in windows) will be handled internally which embedded in pango-utils.c, its configuration (search for "It sucks to use the same GulimChe") somewhat obsolete  (as per 2.28.4), targeted for Windows 2000? or early XP? if somehow this cost you problem (say your native language not displayed properly despite Windows support it) you may change it by adding the appropriate font-name. It's always better to embed than relying on external file. Note: for thai language support there is libdatrie and libthai dependencies.
    To compile it use "configure --with-included-modules --prefix=/c/GTK"

Compiling ATK:

    ATK, don't know what it has to do with mypaint, but it's required by GTK. Use configure --prefix=/c/GTK and make as usual.

Compiling GDK-Pixbuf:

    GDK-Pixbuf do image import support and and other bitmap operation this package formerly part of GTK. With the recent release it will by default choose gdiplus as backend (native windows) to import images, please avoid! it is very slow when opening hi-res images instead use the internal one and several external image coders. Mypaint currently support png and jpeg through this mechanism, so we need libjpeg and libpng.
    As per 2.24.0 version we use double configure first with "configure --without-gdiplus --with-included-loaders=ani,icns,pcx,ras,tga,png,pnm,qtif,wbmp,xbm,xpm,bmp,gif,ico,jpeg --without-libtiff --prefix=/c/$HEX" then make as usual, after "make check" completed do another configure with "configure --without-gdiplus --with-included-loaders=ani,icns,pcx,ras,tga,png,pnm,qtif,wbmp,xbm,xpm,bmp,gif,ico,jpeg --without-libtiff --prefix=/c/GTK" and "make -j2 install" without check. Once finished copy all files except *.la files (linking helper) in C:\$hex to C:\GTK and overwrite later you may delete C:\$hex. This way whenever mypaint need new image loader like tiff or svg we could add them as modules and repair loaders.cache as noted before.

Compiling GTK:

     GTK+ is GUI library for mypaint. Version >=2.24.8 is the only choice for mypaint 1.0 and later

Icons issue (an ugly hack for missing non-standard gtk icons) this also renew gtk default icons with gnome's newest icon theme:

download this icon set and extract to gtk\stock-icons
if in the future we want to renew again don't forget to delete gtk\gtkbuiltincache.h file

    Once all above done use: "configure --with-included-immodules --prefix=/c/GTK" and make as usual.

That's for GTK2! next will be how to build pygtk with numpy support using mingw...

Notes:
What about 64-bit?
In most case it just a matter of switching mingw32 with mingw-w64
If you're running cross-compiler don't forget to add LDFLAGS -D_WIN64
What about GTK3?
Mostly same procedure, but we need gobject introspection to make it works with python
How to re-link dll quickly?
Say we rebuild pixman to support sse2, to force cairo updated delete file libcairo.la then "make".

No comments:

Post a Comment