User:Jdorje/crosscompile
From Freeciv
I started out with the overall goal to be able to cross-compile for windows the programs I'm working on. This would let me develop them suitably. I'm working on Debian unstable so I use the mingw32 packages.
I've done some cross-compiling in the past, but rather haphazardly. The end result is that libraries are distributed all over the place and don't interoperate very well. So I decided to start over from scratch, logging everything I did and following a consistent strategy.
Contents |
[edit] Background
The first problem is a consistent strategy is hard to choose. There are several questions that have to be decided.
1. Where to install compiled libraries and executables? In the beginning I had no special prefix, leading to /usr/i586-mingw32msvc/ being used as my prefix (I think this is what the compiler defaults to). The problem with this is that libraries I compiled get installed alongside the libraries provided by mingw32. I either need to switch to root to install them or relax the restrictions on writing to this directory. Later I tried using /usr/local/i586-mingw32msvc/ as the prefix. The problem with this is it is not normally a default directory for includes or libs, and some packages don't look there by default (particularly in autoconf checks). My problems here were inconsistent. Maybe a more experienced cross-compiler would do something different, but I ended up keeping my prefix as /usr/i586-mingw32msvc/.
2. Static or shared libs? I'm not sure what exactly the term "dll" means. Libraries I've compiled get the suffixes .la (a text file containing information about the binaries in the library), .a (static library), .dll.a (I think this is the same as .a) and .dll (which I think is a "true" dll, the shared version). I'm not concerned about size of the final binaries and I don't want to have to worry about distributing libraries. Ideally all libraries would be static and the binaries I'd end up with would require no extra libraries to be included. But I'm not sure if this is reasonable. I have noticed that some packages (GTK and GLib packages in particular) have a special-case that disables static libraries when compiling on windows, claiming it is impossible (which, at least in my case, is wrong). In the end, I decided to add --disable-shared on to all compilations and leave the rest up to configure.
[edit] My tools
* autoconf 2.59 * automake 1.9.4 * libtool 1.5.6
In many cases I had to edit the underlying auto* files to fix things properly. After this I had to run:
* cat m4/*.m4 > acinclude.m4 (only if m4/*.m4 exists) * libtoolize * aclocal * automake * autoconf
I didn't include the generated files in my patches.
Finally I had a script, compile-win32 that did the work of remembering all the parameters I had to pass to configure. ----- Compiling.
I started with a script "compile-win32" for compiling that passes the appropriate parameters to configure. Since I've already done a fair amount of cross-compilation this script is pretty refined.
I also decided to import everything into CVS before I started compiling it. This would make it easier to get a patch that fixed any problems I ran into. I wanted to fix problems at the source rather than just introduce workarounds.
One other note is the GNU win32 collection at http://sourceforge.net/projects/gnuwin32. I have mixed feelings about this. On the one hand it seems like they are doing sort of the same job I am. However it seems they are compiling directly on windows (not cross-compiling) and are targeting their compilations for windows (making it hard for me to use their compiled binaries). I don't think using modified source code is a particularly good idea. Tools that use automake and autoconf should cross-compile out of the box, without the need for patches. But whether I'll use them or not remains to be seen.
[edit] zlib
Although I said I'd do libiconv first, when I ran into problems there I side-tracked onto libz.
Libz is ugly because it doesn't use the auto* tools. So I didn't really trust it to compile correctly. I compiled libz-1.2.2 from http://www.zlib.net/ and from GNUwin32. However only the latter compiled directly. It built only the static lib.
- CC=i586-mingw32msvc-gcc ./configure --prefix=/usr/i586-mingw32msvc/
- make
- make install
...and I was done.
[edit] libiconv
I went to http://www.gnu.org/software/libiconv/ and downloaded the latest release, 1.9.1. GnuWin32 had an older version so I didn't bother with that.
Linking to iconv statically could be a problem. The binary is no problem of course, but iconv relies on transliteration catalogs and these are not included in the binary AFAIK. In other words the library has shared data. But I guess in the worst case this stuff could be included in any binary distribution.
libiconv has a windows (djgpp) readme. I believe djgpp is basically a gcc environment for windows. This won't help me much (but it does say that iconv compiles out-of-the-box, which is what I remember).
Unfortunately it wasn't quite as easy as I'd remembered. There were a few undefined symbols requiring source code changes. To do it properly meant bootstrap changes as well. I ended up having to apply the iconv patch (http://freeciv.org/~jdorje/crosscompile/libiconv-1.9.1.diff), and then rerunning the auto* tools (see "tools" above).
- patch -s -p0 < libiconv-1.9.1.diff
- cat m4/*.m4 > acinclude.m4
- aclocal
- automake
- autoconf
- compile-win32
- make install
[edit] gettext
The next thing to install is gettext. Gettext is really a monster: although all I really wanted was a few functions in libintl, I have to compile the whole gettext package which contains huge amounts of other stuff and takes forever to compile. Then when it fails to compile I have to tweak something and restart compilation from scratch (I'm not kidding). And of course it doesn't compile out of the box. (BTW: gnuwin32 has a libintl package but I found it unusable because it has practically no bootstrap code.)
[edit] 0.14.1
However after a huge amount of wasted time I end up with a simple patch. Download gettext-0.14.1 from GNU, take the http://freeciv.org/~jdorje/crosscompile/gettext-0.14.1.diff patch, then run
- patch -s -p0 < gettext-0.14.1.diff
- aclocal
- automake
- autoconf
- compile-win32
- make install
[edit] 0.14.5
As of gettext-1.14.5, gettext compiles directly out of the box.
[edit] libpng
In libpng 1.2.8 there is a configure-based and a Makefile-based tarball. Naturally I went with the configure-based one, libpng-1.2.8-config.tar.gz.
And it worked right out of the box! I almost don't believe it (since I don't think any test programs were compiled alongside, I'll hold my breath until I compile a program that uses it).
- compile-win32
- make install
[edit] Freeciv (windows client)
Next I tried to compile the Freeciv server and "windows native" client. This uses all of the libraries above. I took freeciv-2.0.0_beta6.tar.bz2 from freeciv.org.
I ran into a few problems, which are solved or worked around by the freeciv patch, http://freeciv.org/~jdorje/crosscompile/freeciv-2.0.0_beta6.diff (hopefully these will be included by the time 2.0.0 is released).
- patch -s -p0 < freeciv-2.0.0_beta6.diff
- aclocal
- autoheader
- automake
- autoconf
- compile-win32 --enable-client=win32 --disable-esd (if this doesn't work, try adding --disable-nls)
However I still had a problem running the client. This was only solved when I did
- export FREECIV_PATH=""
because apparently my path had been set, and used unix-style : separators instead of windows-style ; separators.
At this point I could run the client under wine. I took this nice screenshot: freeciv-win32.png (which shows gettext in action too).
To run the client, I ran either "wine client/civclient.exe" or I could "make install" and then run "wine civclient.exe".
[edit] Popt
Now on to more libraries. Popt is used by some other programs I want to compile, so I went straight to this. gnuwin32 has a popt 1.8, but my initial compile with that didn't look promising. So I used popt 1.7 from ftp://ftp.rpm.org/pub/rpm/dist/rpm-4.1.x/. I remembered it being a bit problematic, but actually there were just two little problems (of course finding them was the hard part). I ended up with the http://freeciv.org/~jdorje/crosscompile/popt-1.7.diff patch and the following commands:
- patch -s -p0 < popt-1.7.diff
- ./autogen.sh
- compile-win32
- make install
However later on I ran into problems because popt must link against libintl (gettext). libpopt.la lists libintl and libiconv as dependencies, but linking against libpopt with simply -lpopt doesn't seem to work. One must also include -lintl and (because libintl depends on libiconv) -liconv. I can only guess that this is a bug in my mingw that prevents .la dependencies from being handled properly.
[edit] pthread
It would be nice to compile pthreads for windows. There is such a library, at http://sources.redhat.com/pthreads-win32/. However there is no auto* support and I couldn't figure out any way to compile them. This library isn't crucial for me so I just skipped it.
[edit] expat
I knew I'd be needing Expat soon, so I decided to go ahead and compile it. I got Expat 1.95.8 from http://expat.sf.net/. It worked right out of the box:
- compile-win32
- make install
[edit] libggz
Next I wanted to compile GGZ. The first lib here is libggz. I got the CVS version of libggz (soon to be 0.0.10) and compiled it.
- ./autogen.sh --disable-threading
- compile-win32 --disable-threading
- make install
Libggz is a library I program so as you may expect it compiles right out of the box ;-). However without pthreads I needed the --disable-threading configure parameter. (Note, autogen.sh is needed because the development version doesn't have a configure included. With a tarball this step could just be skipped. It's also easy to change compile-win32 to run autogen.sh instead of configure to speed up configuration.)
[edit] ggz-client-libs
ggz-client-libs is also supposed to work out of the box. Again I used the CVS version.
- ./autogen.sh
- compile-win32
- make install
Again autogen.sh is necessary to generate the configure and Makefile.in files (see libggz, above).
[edit] ggz utils
ggz-utils will more or less work out of the box. Unfortunately the utils aren't very useful to most users so this is mostly just a sanity check of the libraries above. Compiling the cmd-client lets me make sure everything's linking okay, and running it lets me connect to a GGZ server and test out ggzcore.
I took the utils module from GGZ's cvs. Unfortunately the GGZ library bootstrap code is a little problematic so I had to patch it with http://freeciv.org/~jdorje/crosscompile/ggz.m4.diff. Hopefully this can be fixed soon and this patch will no longer be needed.
- patch -s -p0 < ggz.m4.diff
- ./autogen.sh --disable-metaserv
- compile-win32 --disable-metaserv
- make install
As before I had to run autogen.sh (see libggz, above). I had to disable the metaserver since it requires pthreads which I (still) don't have. The make install part is optional - all I'm really interested in is ggz-cmd.exe which I can run under wine.
- wine ggz-cmd.exe live.ggzgamingzone.org jdorje $passwd announce "Windows!" Unfortunately the 'announce' command requires admin permissions on the server so most people can't do it.
[edit] SDL
I figured I'd compile libsdl. I download SDL-1.2.8.tar.gz from http://libsdl.org/.
- aclocal
- autoheader
- automake
- autoconf
- compile_win32
- make install
It went off without a hitch. I was worried because SDL configuration is usually done via sdl-config, and I thought I'd get an sdl-config.exe rather than an sdl-config that would run on my machine. However these fears were baseless since sdl-config is a shell script.
One problem I did run into later was that linking didn't work correctly. For instance although SDL_image lists libSDL as a dependency, programs that are compiled and linked to SDL_image fail because of undefined symbols that are supposed to come from SDL.
[edit] SDL_image
Next up was SDL_image, used my most SDL programs. I downloaded SDL_image-1.2.4 from http://libsdl.org/.
- touch INSTALL NEWS AUTHORS ChangeLog
- ./autogen.sh
- compile_win32
- make install
[edit] Freetype
I downloaded Freetype-2.1.9 from http://freetype.sf.net/. This one was particularly easy.
- compile_win32
- make install
[edit] SDL_ttf
And now for SDL_ttf, also needed for many SDL programs. I download SDL_ttf-2.0.7 from http://libsdl.org/. These libraries designed for portability are actually portable!
- ./autogen.sh
- compile_win32
- make install
[edit] glib
Now is where it gets hard. Real hard. I had earlier managed to compile all of the above programs (many of which are prerequesites for glib and gtk), but after extended frustration trying to get glib to work I gave up and started work on this documentation project.
So now I try again. I downloaded glib-2.6.1 from http://gtk.org/. The first thing I tried was simply running compile-win32 on it. Note that compile-win32 already sets glib_cv_stack_grows=no, which is needed to bypass a check that configure does by running a program (AC_TRY_RUN obviously won't work when cross-compiling). Maybe other values will need to be set as well. This particular value tells glib which direction the stack grows, and for x86 machines should be "no".
After this, I get another rather stupid problem:
- make[4]: Entering directory `/home/jdorje/src/win32/glib-2.6.1/glib'
- cd .. && /bin/sh ./config.status glib/glib.rc
- config.status: creating glib/glib.rc
- ../build/win32/lt-compile-resource glib.rc glib-win32res.lo
- Using zero as build number
- 16864.rc:1:20: winver.h: No such file or directory
- windres: 16864.rc:8: syntax error
winver.h is in /usr/i586-mingw32msvc/include/. glib.rc has "#include " in it. Yet for some reason the file is not found.
After working around that problem, I hit a seemingly insolvable linking problem. Libraries that link to other libraries give undefined reference errors. And here I am stuck. All I have so far is http://freeciv.org/~jdorje/crosscompile/glib-2.6.1.diff.
[edit] libpixman
Just for kicks I wanted to cross-compile cairo. I had to cross-compile libpixman first. I got the latest pixman CVS (from http://cairographis.org/) and simply compiled it.
- compile-win32
- make install
No problems!
- Note: as of cairo 1.0; pixman is included directly with cairo.
[edit] cairo
Again I'm working with the latest CVS version of cairo. After installing libpixman I just tried running my compile-win32 script. At first I had problems because it attempted to compile the xlib, freetype, and PNG backends (present on my system but not cross-compiled). I solved these by changing PKG_CONFIG_PATH in my compile-win32 script to PKG_CONFIG_LIBDIR, so it wouldn't check for system libraries. I also used the http://freeciv.org/~jdorje/crosscompile/cairo.diff patch, which fixed a few bootstrap and win32-specific bugs.
- compile-win32
- make install
Note that the freetype and PNG backends should compile on windows if you have the appropriate libraries installed (which I didn't at the time). Cross-compiling these isn't that hard; see above.
