Linux hosted mingw w64 C,C++ and Java cross compiler

Hi everyone !

As i said in my previous article, i want to share with you about the steps to get a fully working w64-mingw32 gcc and gcj 4.6.0 toolchain. I’ll try to be as accurate as possible. Despite of all my efforts, I didn’t manage to get the multilib compiler to build, so I will only describe the steps to get an i686 compiler. Most of the content of this post is based upon mingw w64 instructions, but as I didn’t manage to get it fully compiling following theses instructions, that’s why I’m writing this post.

The times given in this article are thoses obtained with an Intel Xeon CPU X5560 @ 2.80GHz.
The gcc version used was:
gcc version 4.1.2 20080704 (Red Hat 4.1.2-48).

Pre-requisites

  • Native working gcc/gcj installed (at least 4.1), for i686 architecture
  • Environment variables:
    • $work = directory where to work (for example, $HOME/mingw)
    • $prefix = directory where to install the cross compiler (for example, $work/root)
    • $CFLAGS = optimization flags (for example “-march=core2 -mtune=core2 -O2 -pipe”, see Safe CFLAGS for how to define them),
  • Directories:
    • mkdir -p $work/sources $work/tarballs $work/builds $prefix

Sources

Retrieve the following sources in the directory $work/tarballs:

  1. binutils 2.21.51
  2. gcc 4.6.1 20110401: core, g++, java, fix for libjava build error, fix for boehm-gc dll exports, fix for gcj spec file
  3. mingw-w64-trunk-r4105-20110404
  4. ecj 4.5
  5. ppl 11.2, cloog 0.16.2
  6. mpfr 3.0.1, gmp 5.0.1, mpc 0.9

Once everything is retrieved, check that files you downloaded are valid using provided sha1sums.txt (download it to $work/tarballs) and the following command:

# cd $work/tarballs
# sha1sum -c sha1sums.txt
binutils-2.21.51.tar.bz2: OK
cloog-0.16.2.tar.gz: OK
ecj-4.5.jar: OK
gcc-4.6.1-20110401-fix-boehm-gc-dll-export.patch: OK
gcc-4.6.1-20110401-fix-gcj-spec-file.patch: OK
gcc-4.6.1-20110401-fix-libjava-reflect-build-error.patch: OK
gcc-core-4.6-20110401.tar.bz2: OK
gcc-g++-4.6-20110401.tar.bz2: OK
gcc-java-4.6-20110401.tar.bz2: OK
gmp-5.0.1.tar.bz2: OK
mingw-w64-trunk-r4105-20110404.tbz2: OK
mpc-0.9.tar.gz: OK
mpfr-3.0.1.tar.bz2: OK
ppl-0.11.2.tar.bz2: OK

Builds and installation

Note: I advise you to make a tarball of the $prefix directory between each step, just in case something goes wrong on one step

  1. (time: 1m33.932s)

    cd $work/sources
    tar xjpf ../tarballs/gmp-5.0.1.tar.bz2
    cd $work/builds
    mkdir gmp
    cd gmp
    ../../sources/gmp-5.0.1/configure \
      --prefix=$prefix \
      --enable-cxx \
      CPPFLAGS=-fexceptions ABI=32
    make && make install

  2. (time: 1m00.580s)

    cd $work/sources
    tar xjpf ../tarballs/mpfr-3.0.1.tar.bz2
    cd $work/builds
    mkdir mpfr && cd mpfr
    ../../sources/mpfr-3.0.1/configure \
      --prefix=$prefix \
      --with-gmp=$prefix \
      --enable-thread-safe
    make && make install

  3. (time: 0m19.947s)

    cd $work/sources
    tar xzpf ../tarballs/mpc-0.9.tar.gz
    cd $work/builds
    mkdir mpc && cd mpc
    ../../sources/mpc-0.9/configure \
      --prefix=$prefix \
      --with-gmp=$prefix \
      --with-mpfr=$prefix \
      EGREP=egrep LD=ld CPP=cpp CC=gcc
    make && make install

  4. (time: 10m27.848s)

    cd $work/sources
    tar xjpf ../tarballs/ppl-0.11.2.tar.bz2
    cd $work/builds
    mkdir ppl && cd ppl
    ../../sources/ppl-0.11.2/configure \
      --prefix=$prefix \
      --with-gmp-prefix=$prefix \
      --disable-watchdog \
      --disable-ppl_lcdd \
      --disable-ppl_lpsol \
      --disable-ppl_pips \
      --enable-interfaces=c,c++ \
      EGREP=egrep FGREP=fgrep LD=ld CPP=cpp CC=gcc
    make && make install

  5. (time: 0m54.661s)

    cd $work/sources
    tar xzpf ../tarballs/cloog-0.16.2.tar.gz
    cd $work/builds
    mkdir cloog && cd cloog
    ../../sources/cloog-0.16.2/configure \
      --prefix=$prefix \
      --with-gmp-prefix=$prefix
    make && make install

  6. (time: 2m17.511s)

    cd $work/sources
    tar xjpf ../tarballs/binutils-2.21.51.tar.bz2
    cd $work/builds
    mkdir binutils && cd binutils
    ../../sources/binutils-2.21.51/configure \
      --prefix=$prefix \
      --with-{mpfr,mpc,gmp,ppl,cloog}=$prefix \
      --enable-cloog-backend=isl \
      --disable-lto \
      --disable-multilib \
      --disable-shared \
      --target=i686-w64-mingw32 \
      --with-sysroot=$prefix
    make && make install

  7. (time: 0m01.728s)

    cd $work/sources
    tar xjpf ../tarballs/mingw-w64-trunk-r4105-20110404.tbz2
    cd $work/builds
    mkdir mingw-headers && cd mingw-headers
    ../../sources/mingw-w64/mingw-w64-headers/configure \
      --prefix=$prefix \
      --enable-sdk=all \
      --enable-secure-api \
      --host=i686-w64-mingw32
    make install
    ln -s i686-w64-mingw32 $prefix/mingw

  8. (time: 7m21.474s)

    cd $work/sources
    tar xjpf ../tarballs/gcc-core-4.6-20110401.tar.bz2
    tar xjpf ../tarballs/gcc-g++-4.6-20110401.tar.bz2
    tar xjpf ../tarballs/gcc-java-4.6-20110401.tar.bz2
    patch -p1 -d gcc-4.6-20110401 -i $work/tarballs/gcc-4.6.1-20110401-fix-libjava-reflect-build-error.patch
    patch -p1 -d gcc-4.6-20110401 -i $work/tarballs/gcc-4.6.1-20110401-fix-boehm-gc-dll-export.patch
    patch -p1 -d gcc-4.6-20110401 -i $work/tarballs/gcc-4.6.1-20110401-fix-gcj-spec-file.patch
    cp $work/tarballs/ecj-4.5.jar $work/sources/gcc-4.6-20110401/ecj.jar
    cd $work/builds
    mkdir gcc && cd gcc
    ../../sources/gcc-4.6-20110401/configure \
      --prefix=$prefix \
      --with-sysroot=$prefix \
      --disable-multilib \
      --with-{mpfr,mpc,gmp,ppl,cloog}=$prefix \
      --enable-cloog-backend=isl \
      --disable-shared \
      --enable-threads=win32 \
      --disable-tls \
      --disable-__cxa_atexit \
      --enable-languages=c,c++,java \
      --enable-libssp \
      --disable-win32-registry \
      --disable-nls \
      --disable-lto \
      --enable-libgcj \
      --enable-sjlj-exceptions \
      --target=i686-w64-mingw32 \
      --build=$(gcc -v 2>&1 | grep Target | cut -f 2 -d ' ')
    make all-gcc && make install-gcc
    
  9. export PATH=$PATH:$prefix/bin
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$prefix/lib

  10. (time: 1m21.083s)

    cd $work/builds
    mkdir mingw-crt && cd mingw-crt
    ../../sources/mingw-w64/mingw-w64-crt/configure \
      --host=i686-w64-mingw32 \
      --prefix=$prefix \
      --with-sysroot=$prefix
    make && make install

  11. (time: 21m43.436s)

    cd $work/builds/gcc
    build=$(gcc -v 2>&1 | grep Target | cut -f 2 -d ' ')
    ln -s $(which gcc) "$prefix/bin/${build}-gcc"
    ln -s $(which gcj) "$prefix/bin/${build}-gcj"
    make && make install
    rm -f "$prefix/bin/${build}-gcc" "$prefix/bin/${build}-gcc"

    This step will fail to compile because of gcj and errors in jni.cc, i will write a patch to fix the problem soon, so stay tuned.
    Anyway, you will still be able to perform the make install even if it fails at the end, the C and C++ compilers will work as expected.

The end

You are now able to compile windows C/C++ programs using almost all the Windows API without problem. To use the cross compiler, compile your programs using i686-w64-mingw32-gcc instead of gcc to generate EXE files.
Here is the output of correctly builded toolchain:

# i686-w64-mingw32-gcc -v
Using built-in specs.
COLLECT_GCC=i686-w64-mingw32-gcc
COLLECT_LTO_WRAPPER=/home/users_csee/parizet/mingw32/root/bin/../libexec/gcc/i686-w64-mingw32/4.6.1/lto-wrapper
Target: i686-w64-mingw32
Configured with: ../../sources/gcc-4.6-20110401/configure --prefix=/users_csee/parizet/mingw32/root --with-sysroot=/users_csee/parizet/mingw32/root --disable-multilib --with-mpfr=/users_csee/parizet/mingw32/root --with-mpc=/users_csee/parizet/mingw32/root --with-gmp=/users_csee/parizet/mingw32/root --with-ppl=/users_csee/parizet/mingw32/root --with-cloog=/users_csee/parizet/mingw32/root --enable-cloog-backend=isl --enable-shared=libgcc,libstc++,libffi,zlib --enable-threads=win32 --enable-tls --disable-__cxa_atexit --enable-languages=c,c++,java --enable-libssp --disable-win32-registry --disable-nls --enable-lto --enable-libgcj --enable-sjlj-exceptions --target=i686-w64-mingw32 --build=i386-redhat-linux
Thread model: win32
gcc version 4.6.1 20110401 (prerelease) (GCC)
# i686-w64-mingw32-g++ -v
Using built-in specs.
COLLECT_GCC=i686-w64-mingw32-g++
COLLECT_LTO_WRAPPER=/home/users_csee/parizet/mingw32/root/bin/../libexec/gcc/i686-w64-mingw32/4.6.1/lto-wrapper
Target: i686-w64-mingw32
Configured with: ../../sources/gcc-4.6-20110401/configure --prefix=/users_csee/parizet/mingw32/root --with-sysroot=/users_csee/parizet/mingw32/root --disable-multilib --with-mpfr=/users_csee/parizet/mingw32/root --with-mpc=/users_csee/parizet/mingw32/root --with-gmp=/users_csee/parizet/mingw32/root --with-ppl=/users_csee/parizet/mingw32/root --with-cloog=/users_csee/parizet/mingw32/root --enable-cloog-backend=isl --enable-shared=libgcc,libstc++,libffi,zlib --enable-threads=win32 --enable-tls --disable-__cxa_atexit --enable-languages=c,c++,java --enable-libssp --disable-win32-registry --disable-nls --enable-lto --enable-libgcj --enable-sjlj-exceptions --target=i686-w64-mingw32 --build=i386-redhat-linux
Thread model: win32
gcc version 4.6.1 20110401 (prerelease) (GCC)
# i686-w64-mingw32-gcj -v
Using built-in specs.
Reading specs from /home/users_csee/parizet/mingw32/root/bin/../lib/gcc/i686-w64-mingw32/4.6.1/../../../../i686-w64-mingw32/lib/libgcj.spec
rename spec startfile to startfileorig
rename spec lib to liborig
COLLECT_GCC=i686-w64-mingw32-gcj
COLLECT_LTO_WRAPPER=/home/users_csee/parizet/mingw32/root/bin/../libexec/gcc/i686-w64-mingw32/4.6.1/lto-wrapper
Target: i686-w64-mingw32
Configured with: ../../sources/gcc-4.6-20110401/configure --prefix=/users_csee/parizet/mingw32/root --with-sysroot=/users_csee/parizet/mingw32/root --disable-multilib --with-mpfr=/users_csee/parizet/mingw32/root --with-mpc=/users_csee/parizet/mingw32/root --with-gmp=/users_csee/parizet/mingw32/root --with-ppl=/users_csee/parizet/mingw32/root --with-cloog=/users_csee/parizet/mingw32/root --enable-cloog-backend=isl --enable-shared=libgcc,libstc++,libffi,zlib --enable-threads=win32 --enable-tls --disable-__cxa_atexit --enable-languages=c,c++,java --enable-libssp --disable-win32-registry --disable-nls --enable-lto --enable-libgcj --enable-sjlj-exceptions --target=i686-w64-mingw32 --build=i386-redhat-linux
Thread model: win32
gcc version 4.6.1 20110401 (prerelease) (GCC)

In a future post, i will explain how to debug binaries compiled with your brand new cross-gcc compiler.

  1. Actually, at the end of this tutorial, you’ll notice that compiling java programs does not work because of undefined references to boehm gc functions. I’m currently writing a script to automatically build the toolchain, so be patient. I’m updating this post too while trying to get it fully working.

Leave a Comment