Cross Compiling

Cross compiling is the act of the building source code on one system, the build host, into executables or libraries to be run on a different host, the native host. The build host and the native host may differ in operating system and/or processor type. Cross compiling is done for several reasons:

Cross compiling is much trickier than building on the native host. There are a whole new class of problems that can happen when cross compiling that are simply not an issue when building on Cygwin. You should be familiar with building Cygwin/X on Cygwin, as described in the Section called Native Compiling, before attempting to cross compile Cygwin/X.

Obtaining binutils and gcc Source

binutils and gcc source code releases that are known to compile on Cygwin and distributed by the Cygwin project. Therefore, it is highly recommended that you obtain the binutils and gcc sources from the Cygwin mirror network.

Follow these steps to download Cygwin/X binaries:

  1. Create a directory to store the binutils and gcc sources in, such as /home/my_login/cygwin/src/

  2. Visit the Cygwin mirrors page to find your closest mirror

  3. The ftp url for your mirror site should take you to the cygwin/ directory on the mirror

  4. Change current ftp directory to cygwin/release/.

  5. Download the following files from cygwin/release/, saving them to /home/my_login/cygwin/src/ The compressed file size appears after each file in the list below.

    Downloading with a Web Browser: Some web browsers automatically decompress saved files when you use the left mouse button to follow the link to a file; bunzip2 will report, "Data integrity error when decompressing.", when attempting to decompress a file that has been decompressed by your web browser. Prevent your files from being automatically decompressed by clicking the right mouse button on a file link and choosing a command such as Save Target As... or Save Link As... from the context sensitive menu. Better yet, download your files with a stand alone ftp client.

    • binutils/binutils-20030901-1-src.tar.bz2 (10.5 MiB; required, necessary to build gcc and Cygwin/X)

    • gcc/gcc-3.3.1-1-src.tar.bz2 (21.9 MiB; required, necessary to build Cygwin/X)

Obtaining Cygwin Headers and Libs

The simplest method of building a cross compiler for Cygwin requires that you have the Cygwin headers and libraries available at the time of building the cross compiler. Cygwin headers and libraries are installed when Cygwin is installed, so the headers and libraries can be obtained from an existing Cygwin installation.

Don't simply copy the headers and libraries: Some of the headers and libraries are symbolic links to other headers or libraries. Copying these files using a program that is not aware of Cygwin's symlink emulation will result in some of the header and library files being broken. The method described below will preserve the symbolic links used by the header and library files.

  1. Launch your Cygwin environment, using either the icon on your Desktop, the icon in your Start Menu, or by running cygwin.bat from your Cygwin directory (e.g. c:\cygwin); you should see a window like the following:

    
Username@CygwinHost ~
    $ 
    
  2. Change the current directory to Cygwin root directory:

    
Username@CygwinHost ~
    $ cd /
    
    Username@CygwinHost /
    $ 
    
  3. Create an archive of the contents of the /lib directory:

    
Username@CygwinHost /
    $ tar czf cygwin-lib.tgz lib/
    
    Username@CygwinHost /
    $ 
    
  4. Change the current directory to the usr directory in your Cygwin root directory:

    
Username@CygwinHost /
    $ cd /usr
    
    Username@CygwinHost /usr
    $ 
    
  5. Create an archive of the contents of the /usr/include directory:

    
Username@CygwinHost /usr
    $ tar czf cygwin-include.tgz include/
    
    Username@CygwinHost /usr
    $ 
    
  6. Transfer cygwin-lib.tgz and cygwin-include.tgz to your build host using any method that you have available (e.g. ftp, samba, diskette, etc.). Save the files in the /home/my_login/cygwin/i686-pc-cygwin/ directory.

  7. Open a shell on your cross compiling build host; you should see a window like the following:

    
[harold@CrossHost harold]$
    
  8. Change the current directory to the /home/my_login/cygwin/i686-pc-cygwin/ directory in your build host root directory:

    
[harold@CrossHost harold]$ cd /home/my_login/cygwin/i686-pc-cygwin/
    
    [harold@CrossHost /home/my_login/cygwin/i686-pc-cygwin/]$
    
  9. Extract the cygwin-lib.tgz and cygwin-include.tgz archives:

    
[harold@CrossHost /home/my_login/cygwin/i686-pc-cygwin/]$ tar xzf cygwin-lib.tgz
    
    [harold@CrossHost /home/my_login/cygwin/i686-pc-cygwin/]$ tar xzf cygwin-include.tgz
    
  10. Obtaining Cygwin headers and libs is now complete.

Building binutils and gcc

  1. Open a shell on your cross compiling build host; you should see a window like the following:

    
[harold@CrossHost harold]$
    
  2. Change the current directory to the /home/my_login/cygwin/src/ directory in your build host root directory:

    
[harold@CrossHost harold]$ cd /home/my_login/cygwin/src/
    
    [harold@CrossHost src]$
    
  3. Extract the binutils-20030901-1-src.tar.bz2 and gcc-3.3.1-1-src.tar.bz2 archives:

    
[harold@CrossHost src]$ bunzip2 binutils-20030901-1-src.tar.bz2
    
    [harold@CrossHost src]$ tar xf binutils-20030901-1-src.tar
    
    [harold@CrossHost src]$ bunzip2 gcc-3.3.1-1-src.tar.bz2
    
    [harold@CrossHost src]$ tar xf gcc-3.3.1-1-src.tar
    
  4. Change the current directory to the /home/my_login/cygwin/src/binutils-20030901-1 directory:

    
[harold@CrossHost src]$ cd binutils-20030901-1
    
    [harold@CrossHost binutils-20030901-1]$ 
    
    
  5. Create a build directory and change the current directory to that directory:

    
[harold@CrossHost binutils-20030901-1]$ mkdir build
    
    [harold@CrossHost binutils-20030901-1]$ cd build
    
    [harold@CrossHost build]$
    
  6. Configure binutils:

    
[harold@CrossHost build]$ ../configure 
    --prefix=/home/my_login/cygwin --exec-prefix=/home/my_login/cygwin 
    --target=i686-pc-cygwin --host=i686-pc-linux > configure.log 2>&1
    
    [harold@CrossHost build]$
    
  7. Build binutils:

    
[harold@CrossHost build]$ make all > all.log 2>&1
    
    [harold@CrossHost build]$
    
  8. Install binutils:

    
[harold@CrossHost build]$ make install > install.log 2>&1
    
    [harold@CrossHost build]$
    
  9. Modify the PATH environment variable to include the directories that the binutils executables were installed in:

    
[harold@CrossHost build]$ 
    PATH=$PATH:/home/my_login/cygwin/bin:/home/my_login/cygwin/i686-pc-cygwin/bin
    
    [harold@CrossHost build]$ 
    
  10. Change the current directory to the /home/my_login/cygwin/src/gcc-3.3.1-1 directory:

    
[harold@CrossHost build]$ cd ../../gcc-3.3.1-1
    
    [harold@CrossHost gcc-3.3.1-1]$ 
    
  11. Create a build directory and change the current directory to that directory:

    
[harold@CrossHost gcc-3.3.1-1]$ mkdir build
    
    [harold@CrossHost gcc-3.3.1-1]$ cd build
    
    [harold@CrossHost build]$
    
  12. Configure gcc:

    
[harold@CrossHost build]$ ../configure 
    --prefix=/home/my_login/cygwin --exec-prefix=/home/my_login/cygwin 
    --target=i686-pc-cygwin --host=i686-pc-linux 
    --enable-haifa > configure.log 2>&1
    
    [harold@CrossHost build]$
    
  13. Build gcc:

    
[harold@CrossHost build]$ make all > all.log 2>&1
    
    [harold@CrossHost build]$
    
  14. Install gcc:

    
[harold@CrossHost build]$ make install > install.log 2>&1
    
    [harold@CrossHost build]$
    
  15. Building binutils and gcc is now complete.

Creating Links for binutils and gcc

Links to the executables in /home/my_login/cygwin/bin must be created in the /home/my_login/cygwin/i686-pc-cygwin/bin directory; these are required for the build system to find the build executables (e.g. gcc, cpp, etc.). Each of the build executables in /home/my_login/cygwin/bin is prefixed with i686-pc-cygwin (e.g. i686-pc-cygwin-cpp) whereas the build system expects the executables to have no prefix (e.g. cpp).

Creating links to the build executables and dropping the prefix from the name of each build executables link is done by a script that was provided by the XFree86 cross-compiling community and slightly modified by Alexander Gottwald. The text of this script is below, save it in a file on your cross compiling host called cross-links.sh. Note that the location of the script does not matter, since it contains a reference to the location of the build tools in the CYGROOT variable.


#!/bin/bash

#
# This stuff is required for the Cross Compile Environment.
#
CYGROOT=/home/my_login/cygwin
TARGET=i686-pc-cygwin
mkdir -p $CYGROOT/$TARGET/bin
cd $CYGROOT/$TARGET/bin

for i in ../../bin/*; do
    if [ $i !=  ${i/$TARGET-/} ]; then
         ln -s $i ${i/.*$TARGET-/}
    fi
done

ln -s gcc cc

Finally, run the cross-links.sh script. There should now be several links in the /home/my_login/cygwin/i686-pc-cygwin/bin directory.

Building Cygwin/X

Building the source code when cross compiling X Window System is nearly identical to the process described below in the Section called Native Compiling of the Native Compiling section. One divergence from the aforementioned instructions is that you will be using a bash shell on your cross compiling host, rather than on your native Cygwin host; other divergences follow.

  1. lndir should generally already be installed if your build host already has the X Window System installed. If you do not have lndir, you can build it for your build host by following the instructions in the Section called Building and Installing lndir.

  2. When building the entire tree, you must pass CROSSCOMPILEDIR to make to cause the build system to build for the target, Cygwin, platform:

    
[harold@CrossHost std]$ make World 
    CROSSCOMPILEDIR="/home/my_login/cygwin/i686-pc-cygwin/bin" > World.log 2>&1
    
    [harold@CrossHost std]$
    
  3. When rebuilding individual directories of the tree after doing a build of the entire tree, you can simply issue the make command:

    
[harold@CrossHost std]$ cd programs/Xserver
    
    [harold@CrossHost Xserver]$ make XWin.exe > XWin.log 2>&1
    
    [harold@CrossHost Xserver]$
    
  4. When building a debug version of the entire tree, use makeg, which should generally already be installed, and pass CROSSCOMPILEDIR to makeg to cause the build system to build for the target, Cygwin, platform:

    
[harold@CrossHost debug]$ makeg World 
    CROSSCOMPILEDIR="/home/my_login/cygwin/i686-pc-cygwin/bin" > World.log 2>&1
    
    [harold@CrossHost debug]$
    
  5. When rebuilding individual directories of the tree after doing a build of the entire tree, you can simply issue the makeg command:

    
[harold@CrossHost std]$ cd programs/Xserver
    
    [harold@CrossHost Xserver]$ makeg XWin.exe
    CROSSCOMPILEDIR="/home/my_login/cygwin/i686-pc-cygwin/bin" > XWin.log 2>&1
    
    [harold@CrossHost Xserver]$
    
  6. When installing a standard build of the entire tree, you must pass DESTDIR and CROSSCOMPILEDIR to make to install the target platform build into /stagingdir and to cause the build system to build a few remaining programs for the target, Cygwin, platform:

    Tip: Never run make install install.man on your host platform without the DESTDIR parameter, as that will cause the Cygwin build of X Window System to be installed over top of your local X Window System installation, which would completely destroy your host system's X Window System installation.

    
[harold@CrossHost std]$ make install install.man 
    DESTDIR=/stagingdir 
    CROSSCOMPILEDIR="/home/my_login/cygwin/i686-pc-cygwin/bin" > install.log 2>&1
    
    [harold@CrossHost std]$
    
  7. When installing a debug build of the entire tree, you must pass DESTDIR and CROSSCOMPILEDIR to makeg to install the target platform build into /stagingdir and to cause the build system to build debug versions of a few remaining programs for the target, Cygwin, platform:

    Tip: Never run makeg install install.man on your host platform without the DESTDIR parameter, as that will cause the Cygwin debug build of X Window System to be installed over top of your local X Window System installation, which would completely destroy your host system's X Window System installation.

    
[harold@CrossHost debug]$ makeg install install.man 
    DESTDIR=/stagingdir 
    CROSSCOMPILEDIR="/home/my_login/cygwin/i686-pc-cygwin/bin" > install.log 2>&1
    
    [harold@CrossHost debug]$