Cross-compiling to Cygwin

Building a cross-compiler

Here be dragons

Building a cross-compiler is not often tested. You will likely encounter problems following these instructions, and require an in-depth understanding of what you are doing in order to fix those problems. These instructions are meant to be a template to be completed with your own understanding, rather than a recipe to be followed blindly. Reports to the mailing list that you followed these instructions, got an error message and are now stuck, will be ignored with harsh, uncaring indifference.

Note

Even once you have built your cross-compiler, there are a whole new class of problems that can happen when cross-compiling that are simply not an issue when building on the target. For example: you will need to somehow make the dependencies of your program available to the cross-compiler; hardly anything uses HOST_EXEEXT correctly, etc.

You will want to read carefully the GCC installation guide.

These instructions will assume you have chosen a suitable working directory, e.g. ~/cygwin/

To build a minimal cross-toolchain, we need to build binutils (for the cross-assembler and cross-linker) and GCC (for the cross-compiler).

Obtaining binutils and GCC source

binutils and GCC releases that are known to work for Cygwin are distributed with source code by the Cygwin project. These may contain patches against the stock upstream release required to build or function correctly on Cygwin, therefore, it is highly recommended that you obtain the binutils and GCC sources from the Cygwin mirror network.

Follow these steps to download Cygwin sources:

  1. Create a directory to store the binutils and GCC sources in, such as ~/cygwin/src/

  2. The URL listed for your nearest mirror site should take you to the cygwin/ directory on the mirror

  3. Download the following files from cygwin/release/, saving them to ~/cygwin/src/.

    • binutils/binutils-2.20.51-2-src.tar.bz2

    • gcc4/gcc4-4.5.0-1-src.tar.bz2

user@crosshost ~ $ mkdir -p ~/cygwin/src
user@crosshost ~ $ cd ~/cygwin/src
user@crosshost ~/cygwin/src $ wget $YOUR_MIRROR/release/binutils/binutils-2.20.51-2-src.tar.bz2
user@crosshost ~/cygwin/src $ wget $YOUR_MIRROR/release/gcc4/gcc4-4.5.0-1-src.tar.bz2

Currently GCC is provided as cygport package. You will want to examine closely the .cygport file contained in the source package which shows how GCC is configured and built natively.

You will want to read carefully the cygwin-specific READMEs installed by the corresponding binary packages into /usr/share/doc/Cygwin/, which contain important information and build instructions

Obtaining Cygwin headers and libraries

The usual technique for building GCC cross-compilers is to:

  1. build binutils

  2. build a bootstrap compiler (--without-headers --enable-languages=c) that will only be used to build the C runtime library.

  3. use the bootstrap compiler to build the C runtime library.

  4. rebuild the final compiler, including internal libraries that need the target-specific C runtime library in order to be compiled properly.

Unfortunately, this technique cannot be applied building a cross-compiler for Cygwin, not least due to the use of C++ code in winsup/.

The simplest method of escaping from this chicken-and-egg situation is to make the Cygwin headers and libraries available at the time of building the cross-compiler, by installing them from the Cygwin binary packages containing those headers and libraries.

Headers and libraries from the following packages are required:

  • cygwin (needed for building libgcc)
  • win32api (needed for building libgcc)
  • iconv (needed for building libstdc++)
user@crosshost ~/cygwin/src $ wget $YOUR_MIRROR/release/cygwin/cygwin-1.7.7-1.tar.bz2
user@crosshost ~/cygwin/src $ wget $YOUR_MIRROR/release/w32api/w32api-3.15-1.tar.bz2
user@crosshost ~/cygwin/src $ wget $YOUR_MIRROR/release/libiconv/libiconv-1.13-10.tar.bz2
user@crosshost ~/cygwin/src $ cd ~/cygwin
user@crosshost ~/cygwin $ tar xjf src/cygwin-1.7.7-1.tar.bz2 usr/include usr/lib
user@crosshost ~/cygwin $ tar xjf src/w32api-3.15-1.tar.bz2 usr/include usr/lib
user@crosshost ~/cygwin $ tar xjf src/libiconv-1.13-10.tar.bz2 usr/include usr/lib
user@crosshost ~/cygwin $ ln -s ../usr/include/ i686-pc-cygwin/include
user@crosshost ~/cygwin $ ln -s ../usr/lib/ i686-pc-cygwin/lib

Alternatively, these headers and libraries can be obtained by copying the contents of the /usr/lib directory and /usr/include directory of a Cygwin host, to the ~/cygwin/i686-pc-cygwin directory on your build host. Ensure the method you use to copy these files preserves symlinks.

Building binutils

  1. Change the current directory to the ~/cygwin/src directory:

    user@crosshost ~/cygwin $ cd ~/cygwin/src/
    
  2. Extract the binutils archive:

    user@crosshost ~/cygwin/src $ tar jxf binutils-2.20.51-2-src.tar.bz2
    
  3. Create a ~/cygwin/build/binutils-2.20.51-2/ directory and change the current directory to that directory:

    user@crosshost ~/cygwin/src $ mkdir -p ~/cygwin/build/binutils-2.20.51-2
    user@crosshost ~/cygwin/src $ cd -p ~/cygwin/build/binutils-2.20.51-2
    
  4. Configure binutils:

    user@crosshost ~/cygwin/build/binutils-2.20.51-2/build $ ../../src/binutils-2.20.51-2/configure --prefix=/home/user/cygwin --target=i686-pc-cygwin 2>&1 | tee configure.log
    
    • The Cygwin binutils source tarball doesn't seem to record the configuration used to build the Cygwin binary package.

  5. Build binutils:

    user@crosshost ~/cygwin/build/binutils-2.20.51-2/build $ make all 2>&1 | tee all.log
    
  6. Install binutils:

    user@crosshost ~/cygwin/build/binutils-2.20.51-2/build $ make install 2>&1 | tee install.log
    
  7. Modify the PATH environment variable to include the directories that the binutils executables were installed in, so they are available when we build GCC:

    user@crosshost ~/cygwin/build/binutils-2.20.51-2/build $ export PATH=~/cygwin/bin:$PATH
    

Building GCC

  1. Change the current directory to the ~/cygwin/src/ directory:

    user@crosshost ~ $ cd ~/cygwin/src
    
  2. Extract the GCC archive, then extract the upstream GCC source archive and apply the patches it contains :

    user@crosshost ~/cygwin/src $ tar jxf gcc4-4.5.0-1-src.tar.bz2
    user@crosshost ~/cygwin/src $ tar jxf gcc-4.5.0.tar.bz2
    user@crosshost ~/cygwin/src $ (patching and autoreconf commands omitted)
    
    • Where the patches touch the configuration mechanism, you need to regenerate the files generated by autotools. autoreconf doesn't work, I don't know why, so you need to invoke the correct autotools in the correct directories. The cygport file provides an example of how to do this.

    • GCC is picky about the exact versions of the autotools in use, so you need to make the versions it requires available.

    • For bonus points, use cygport prep to extract the source and apply the patches.

  3. Create a ~/cygwin/build/gcc-4.5.0-1/ directory and change the current directory to that directory:

    user@crosshost ~/cygwin/src $ mkdir ~/cygwin/build/gcc-4.5.0
    user@crosshost ~/cygwin/src $ cd ~/cygwin/build/gcc-4.5.0
    
    • It's highly recommended that GCC be built into a separate directory from the sources which does not reside within the source tree. Building GCC in the source directory is generally untested, and building into a subdirectory of the source directory is unsupported.

  4. Configure GCC:

    user@crosshost ~/cygwin/build/gcc-4.5.0 $ ../../src/gcc-4.5.0/configure --prefix=/home/user/cygwin --target=i686-pc-cygwin \
    --disable-bootstrap --enable-version-specific-runtime-libs --enable-static --enable-shared --enable-shared-libgcc \
    --disable-__cxa_atexit --disable-sjlj-exceptions --enable-languages=c,c++ --disable-symvers --enable-threads=posix \
    2>&1 | tee configure.log
    
    • Use the same configure options as used in the cygport file or reported by gcc -v

  5. Build GCC:

    user@crosshost ~/cygwin/build/gcc-4.5.0-1 $ make all 2>&1 | tee all.log
    
  6. Install GCC:

    user@crosshost ~/cygwin/build/gcc-4.5.0-1 $ make install 2>&1 | install.log
    

Building binutils and GCC is now complete. Test your cross-compiler by checking that a 'hello world' program can be successfully compiled on your build host and run on your Cygwin target host.

This mailing list thread discusses some of the issues with building a cross-compiler, and provides an example script. It also discusses cross-compiling the Cygwin DLL itself.