Cross Compiling for Win32

From NJH-Wiki

Jump to: navigation, search
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:

  1. base cross compiling environment (compiler, binutils, libc, w32api, ...)
  2. portable libraries (zlib, SDL, Fltk, ...)
  3. 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:

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

See also

Personal tools