Cross Compiling for Win32
From NJH-Wiki
- Author
- Volker Grabsch
Contents |
Introduction
This article aims to summarize the state of art about cross compiling for the Win32 platform (MS Windows 95/98/ME/NT/2000/XP).
Please have a look at the Win32 Cross Compiling Tutorial if you are new to the topic.
Cross compiling generally consists of three steps:
- base cross compiling environment (compiler, binutils, libc, w32api, ...)
- portable libraries (zlib, SDL, Fltk, ...)
- cross compiling your own packages
To compile any serious program, you'll have go through all these 3 steps.
My script to build a MinGW cross compiling environment automates step 1 and 2.
The introduction covers the theoretical background and the possibilities you generally have. The second chapter describes the practical part.
Base cross compiling environment
This one is said to be difficult, but in fact, it's relatively easy. You just need to download the MinGW packages w32api, mingw-runtime, binutils and gcc. Binutils and gcc have to be compiled, in that order, but the w32api and mingw-runtime binary packages can be used directly.
The only really needed ./configure option for binutils and gcc is
./configure \
--target="i386-mingw32msvc"
However, for gcc, I personally recommend to use at least the options:
./configure \
--target="i386-mingw32msvc" \
--enable-version-specific-runtime-libs \
--with-gcc \
--with-gnu-ld \
--with-gnu-as \
--without-x \
--enable-threads=win32 \
--disable-win32-registry \
--enable-sjlj-exceptions
There are also some scripts available that do the work for you:
- http://www.libsdl.org/extras/win32/cross/README.txt
- http://www.mingw.org/wiki/LinuxCrossMinGW
- http://www.profv.de/mingw_cross_env/
On Debian you have also the option to use the mingw32 Debian package.
The usual prefix of the cross compiling environment is:
i386-mingw32msvc
The Debian package uses the prefix:
i586-mingw32msvc
Portable Libraries
This step is easier, but a lot more hand work. Especially for win32, the quality of officially provided binary packages varies a lot!
There are some free software distributions (GnuWin32, Cygwin) which take lots of free software and compile them for win32. But none of them really cares about creating RPM or Debian packages for cross compilation.
In contrast, Debian takes care of cross compilation. But it doesn't suport cross compiled binary packages, because that would dramatically increase the number of packages they have to handle. Also, they don't officially support the win32 platform, but this may change in the future.
So you have three choices:
- Tweak and compile the libraries on your own
- The first one is what people usually do, and they sadly don't document which changes they had to perform on the sources.
- Use the binary packages provided by GnuWin32 or Cygwin
- This is a very good way to get started quickly. However, there are still packages you'll have to cross compile manually.
- Use my script to build a MinGW cross compiling environment
- This is also a very good way to get started quickly. You may want to study the script, because it shows how to adapt free libraries for win32 cross compilation.
- Tweak and cross compile Debian sources
- In the long run, this would be the best one. It requires a lot more initial work than "just getting it work", but ensures that the package will be maintained for a long time. Also, it benefits from the strict Debian policies, quality assurance and security team.
Debian
The Debian project provides native packages for a variety of platforms (hurd-i386, arm, ...). Debian also has mechanisms to convert them into cross compiling packages.
In addition, it allows you to create native packages for other platforms via cross compiling. Note that many older libraries aren't prepared for cross compiling, but no maintainer will reject a compatibility patch that fixes this problem. :-)
However, win32 is not an official Debian supported platform. You have to manually add this to the Debian architecture tables. The correct dpkg-architecture name is:
w32-i386
Afterwards, you are able to use the dpkg-cross tools to
- create native packages for the "w32-i386" platform
- convert them into cross compiling packages
Cygwin
The Cygwin project is another free software distribution, specialized for the win32 platform.
They have their own distribution system, and don't compile from Debian sources. So the Debian project does not benefit from their efforts and vice versa. That's very sad.
The Debian-Cygwin project tried to provide a way to use the Debian packaging system in a win32 environment. However, this project seems to be dead now.
GnuWin32
The GnuWin32 project is an addition to the MinGW project and provides a lot of free software packages including some libraries. This distribution is quite small compared to Cygwin, but their packages are very lightweight. Some important libraries such as SDL, smpeg, wxWindows and Fltk are missing.
They have good standards for binary packages, but only very loose standards for source packages. So the Debian project cannot benefit from their efforts.
A long time ago I was providing an inofficial APT respository of GnuWin32 binaries.
These Debian packages were dirty cross compiling packages I created from the "library development ZIP packages" of GnuWin32. They were a good start and saved some work, but eventually they were completely replaced by the MinGW cross compiling environment.
MinGWrep
The MinGW packages repository is older than GnuWin32, but has the same goal.
However, their last activity was in October 2001, so their packages are hopelessly outdated.
Cross compiling your own packages
Please have a look at the Win32 Cross Compiling Tutorial.
Debian cross compiling for w32-i386
Installing the necessary packages
You need a cross compiler (package mingw32) and some cross compiling tools (package dpkg-cross):
aptitude install mingw32 dpkg-cross
This cross compiling environment is located at:
/usr/i586-mingw32msvc
The cross prefix is:
i586-mingw32msvc-
Adding a custom architecture to dpkg-architecture
Append to /usr/share/dpkg/ostable this line:
w32 mingw32msvc mingw32[^-]*
Test the new entry:
dpkg-architecture -aw32-i386 | grep DEB_HOST
That should print:
DEB_HOST_ARCH=w32-i386 DEB_HOST_ARCH_OS=w32 DEB_HOST_ARCH_CPU=i386 DEB_HOST_GNU_CPU=i486 DEB_HOST_GNU_SYSTEM=mingw32msvc DEB_HOST_GNU_TYPE=i486-mingw32msvc
Note that these changes are not permanent. They'll disappear the next time you update the dpkg package.
Cross compiling
Before cross compiling anything, you should adjust the PATH to point into the cross compiling environment first, e.g.:
PATH=/usr/i586-mingw32msvc/bin:$PATH
Otherwise, the config scripts of some libraries (e.g. sdl-config) are not found. Dpkg-cross is an exception, because it manages the PATH itself.
Depending on the type of your source package, there are now several ways to compile it.
Makefile-only
If the source package doesn't have a ./configure script, this is the way to go.
You have to override some internal environment variables of make, by passing some extra parameters.
For the correct C compiler, linker, library archiver and resources converter you have to set:
CC=i586-mingw32msvc-gcc LD=i586-mingw32msvc-ld AR=i586-mingw32msvc-ar RC=i586-mingw32msvc-windres
Maybe you also have to adjust some more environment variables.
When compiling a library, you may want to install it in the cross compiling environment. In this case you have to specify a proper PREFIX to make install:
PREFIX=/usr/i586-mingw32msvc
That's it!
If you have any trouble, maybe you have to specify some more variables.
It is also possible that the provided Makefile does not consequently use these environment variables. In both case this would cause a native compiler tool to be called instead of the corresponding cross compiling tool, which guaratees chaos and trouble. In this case you'll have to edit the Makefile manually to make it use the mentioned variables instead of hard coded commands.
Example:
PATH=/usr/i586-mingw32msvc/bin:$PATH \
make CC=i586-mingw32msvc-gcc AR=i586-mingw32msvc-ar \
RC=i586-mingw32msvc-windres
make install PREFIX=/usr/i586-mingw32msvc
With ./configure
If the source package ships with a ./configure script, you only have to pass proper arguments. They are usually well-prepared for cross compiling.
The only thing you must do is specifying the "host" type:
--host=i586-mingw32msvc
To avoid warnings, you should also specify the "build" type, i.e. the architecture of your Debian system. This information can be retrieved with:
dpkg-architecture -qDEB_BUILD_GNU_TYPE
So you should add this ./configure argument:
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE`
When compiling a library, you may want to install it in the cross compiling environment. In this case you have to add a proper prefix parameter to ./configure:
--prefix=/usr/i586-mingw32msvc
That's it!
Example:
PATH=/usr/i586-mingw32msvc/bin:$PATH \
./configure --host=i586-mingw32msvc \
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
--prefix=/usr/i586-mingw32msvc
make
make install
Using dpkg-cross
This is the recommended way to cross compile a Debian source package.
At first, you must write into $HOME/.dpkg-cross/cross-compile or /etc/dpkg-cross/cross-compile:
crossprefix = i586-mingw32msvc- crossdir = /usr/i586-mingw32msvc
The dpkg-cross package contains a wrapper for dpkg-buildpackage which takes an extra option for the target architecture:
dpkg-buildpackage -aw32-i386 ...
Afterwards, you can transform this package into a cross compiling package:
dpkg-cross -aw32-i386 -b ...
Example:
dpkg-buildpackage -aw32-i386 -rfakeroot -us -uc cd .. dpkg-cross -aw32-i386 -b *_w32-i386.deb

