[ Beneath the Waves ]

DaVinci's Shadow Build Process - Cross-Compiling For Windows on Linux

article by Ben Lincoln

 

This article describes the process of assembling a build environment for DaVinci's Shadow on a 64-bit Linux system that will compile 64-bit and 32-bit Microsoft Windows® executables. This is how I build the Windows® version for distribution with The Mirror's Surface Breaks. You probably don't need to do this - nearly everyone will be perfectly happy with just downloading the precompiled version - but if you do (or want to), here is how.

Some notes:

Build Environment Setup - Introduction

Following the instructions here should give you a cross-compile build environment that includes the same optional components as the basic build environment described in the DaVinci's Shadow Build Process - Linux article.

Due to the amount of effort involved, this process has only been tested on openSUSE 11.3.

The bulk of the work here should only need to be performed once. I suggest doing it on a VM which is used primarily for this cross-compilation.

To install some other prerequisites, you should follow all of the steps to build the Linux version of DaVinci's Shadow first. Then, install the development packages for GNU GMP, MPFR, and MPC using the package manager for your distribution. For example, on OpenSUSE, run sudo -E zypper install gmp-devel mpfr-devel mpc-devel.

The rest of this process involves building a lot of things from source code. You can either download the build environment package at the bottom of this page (which is the method I recommend), or download the components individually elsewhere. If you want to track them down yourself, you will need the source code for:

You will also need the source code for these libraries which DaVinci's Shadow uses:

Obviously, if you use a different version of any component, you may run into problems.

Although MinGW-w64 is capable of creating a compiler that can build both 32-bit and 64-bit Windows executables and libraries, I split this into a distinct compiler for each. This is because of the relatively large number of shared components that need to be built - I didn't want the 32- and 64-bit versions stepping on each others' toes, and having a distinct directory structure for each seemed like the way to go. If you don't need 32-bit support, you can skip that section entirely. If you only want 32-bit support for some reason, you'll have to muddle your way through, because these instructions assume that the 64-bit section is already done by that time.

For the most part, this is actually a pretty smooth process, as long as you follow these instructions exactly. The only real complication (other than if you deviate by even a millimeter from the instructions, which will lead to your being immediately put down by snipers and sliced into tiny cubes by laser beams) is with HDF5, because it is most definitely not designed to be cross-compiled. You will need access to a Windows® system for a couple of intermediate steps while building that. Everything else can be done within the cross-compile environment on Linux.

Build Environment Setup - Unpacking

These instructions assume you are using the build environment package from the bottom of this page. If you are not, you'll need to read between the lines and substitute the locations of the packages you downloaded via other means.

In this section, you will:

  1. Unpack the main build environment package (creating the directory ds291prereq).
  2. Move the actual cross-compiler components up to the next-highest-level directory.
  3. Unpack all of the archives that were in the package.
  4. Duplicate the prerequisite directory so that the 64-bit and 32-bit versions are isolated from each other (because not all of the components support running configure from a location other than their main directory).

If you're only going to be building the 64-bit or 32-bit version (but not both), you can skip the step about duplicating the prerequisites.

Here are the commands I used to accomplish these tasks on my openSUSE 11.3 system:

tar -xjvf ds291prereq.tar.bz2

cd ds291prereq

mv binutils-2.22.tar.bz2 ../

mv gcc-4.6.2.tar.bz2 ../

mv mingw-w64-v2.0.1.tar.gz ../

for a in `ls -1 *.tar.bz2`; do tar -xjvf $a; done

for a in `ls -1 *.tar.gz`; do tar -xzvf $a; done

tar -xvf regex-20090805.tar.xz --use-compress-program=xz

cd ..

tar -xjvf binutils-2.22.tar.bz2

tar -xjvf gcc-4.6.2.tar.bz2

tar -xzvf mingw-w64-v2.0.1.tar.gz

mv ds291prereq ds291prereq64

cp -r ds291prereq64 ds291prereq32

Build Environment Setup - 64-bit Cross-Compiler

In this section, you will:

  1. Set up the combination of Binutils, GCC, and MinGW-w64 as a dedicated 64-bit Windows® cross-compiler.
  2. Create an alternate directory structure for shared components and the final product to go to (to avoid conflicts with native components on the system).

It is supposedly possible to have a cross-compiler and not use an alternate directory structure, but I wouldn't recommend it.

These are the commands I used:

sudo mkdir /cross

sudo mkdir /cross/win64

sudo chown -R blincoln:root /cross

chmod -R g+w /cross

mkdir /cross/win64/usr

mkdir /cross/win64/usr/local

mkdir /cross/win64/usr/local/bin

mkdir /cross/win64/usr/local/include

mkdir /cross/win64/usr/local/lib

mkdir /cross/win64/usr/local/sbin

mkdir /cross/win64/usr/local/share

mkdir /cross/win64/usr/local/src

mkdir /cross/win64/usr/local/man

mkdir /cross/win64/usr/local/lib64

sudo -E zypper install gmp-devel mpfr-devel mpc-devel

cd binutils-2.22

mkdir build-win64

cd build-win64

../configure --target=x86_64-w64-mingw32 --enable-targets=x86_64-w64-mingw32,i686-w64-mingw32 --with-sysroot=/cross/win64/usr/local --prefix=/cross/win64/usr/local

make

make install

cd ../../mingw-w64-v2.0.1/mingw-w64-headers

mkdir build-win64

cd build-win64

../configure --host=x86_64-w64-mingw32 --prefix=/cross/win64/usr/local

make

make install

ln -s /cross/win64/usr/local/x86_64-w64-mingw32 /cross/win64/usr/local/mingw[1]

ln -s /cross/win64/usr/local/x86_64-w64-mingw32/lib /cross/win64/usr/local/x86_64-w64-mingw32/lib64

cd ../../../gcc-4.6.2

mkdir build-win64

cd build-win64

../configure --target=x86_64-w64-mingw32 --enable-targets=all --enable-languages=c,c++ --enable-shared --with-sysroot=/cross/win64/usr/local --prefix=/cross/win64/usr/local

make all-gcc

make install-gcc

export PATH="$PATH:/cross/win64/usr/local/bin:/cross/win64/usr/local/x86_64-w64-mingw32/bin"

cd ../../mingw-w64-v2.0.1/mingw-w64-crt

mkdir build-win64

cd build-win64

../configure --host=x86_64-w64-mingw32 --enable-lib32 --with-sysroot=/cross/win64/usr/local --prefix=/cross/win64/usr/local

make

make install

cd ../../../gcc-4.6.2

cd build-win64

../configure --target=x86_64-w64-mingw32 --enable-targets=all --enable-languages=c,c++,fortran --enable-shared --with-sysroot=/cross/win64/usr/local --prefix=/cross/win64/usr/local[2]

make

make install

exit[3]

IMPORTANT!

When using the 64-bit cross-compiler, you should set the following environment variables. Otherwise many, many build failures will occur.

export PATH="$PATH:/cross/win64/usr/local/bin:/cross/win64/usr/local/x86_64-w64-mingw32/bin"

export CC="/cross/win64/usr/local/bin/x86_64-w64-mingw32-gcc"

export CFLAGS="-I/cross/win64/usr/local/include -L/cross/win64/usr/local/lib"

export LD_LIBRARY_PATH=".:/cross/win64/usr/local/lib"

Build Environment Setup - 64-bit Prerequisite Components

In this section, you will compile the prerequisites needed for the build of DaVinci's Shadow later on. This requires a number of workarounds and hacks. Most of these are described in more loving detail in the older DaVinci's Shadow Build Process - Windows article if you're interested.

PDCurses

In PDCurses-3.4/pdcurses/terminfo.c, you'll need to make a small change to the source code. Locate this block:

int tputs(const char *str, int affcnt, int (*putfunc)(int))

{

PDC_LOG(("tputs() - called\n"));

return ERR;

}

Replace it with this:

/*

int tputs(const char *str, int affcnt, int (*putfunc)(int))

{

PDC_LOG(("tputs() - called\n"));

return ERR;

}

*/

int tputs(const char *str, int affcnt, int (*putfunc)(int))

{

PDC_LOG(("tputs() - called\n"));

while (*str)

{

putfunc (*str++);

}

return ERR;

}

You'll also need to make some changes to PDCurses-3.4/win32/mingwin32.mak:

Replace all occurrences of copy with cp, and all occurrences of del with rm.
In vi/vim, you can do this with :%s/copy/cp/g and :%s/del/rm/g

Change the line which reads:

CC = gcc

To:

CC = x86_64-w64-mingw32-gcc

Change the line which reads:

CFLAGS += -I$(PDCURSES_SRCDIR)

To:

CFLAGS += -I$(PDCURSES_SRCDIR) -I/cross/win64/usr/local/include -L/cross/win64/usr/local/lib

Now you can execute the makefile. It will break in a couple of places, so there are some manual fixes in the following commands:

cd PDCurses-3.4/win32/

make -f mingwin32.mak

x86_64-w64-mingw32-ranlib pdcurses.a

make -f mingwin32.mak

cp panel.a /cross/win64/usr/local/lib/libpanel.a

cp pdcurses.a /cross/win64/usr/local/lib/libcurses.a

cd ..

cp *.h /cross/win64/usr/local/include

cd ..

Readline 6.1

No special requirements here.

cd readline-6.1

mkdir build-win64

cd build-win64

../configure --host=x86_64-w64-mingw32 --prefix=/cross/win64/usr/local --with-curses

make

make install

cd ../..

ZLib 1.2.5

A few workarounds are necessary here because the configure script is so old.

Edit zlib-1.2.5/configure and add the following block of code just after the initial comments (or right at the beginning of the file):

CC=x86_64-w64-mingw32-gcc

CFLAGS="-I/cross/win64/usr/local/include -L/cross/win64/usr/local/lib"

The script will still break when you run it (several times, including during the make install), so you'll be doing some manual workaround commands like with the PDCurses build.

cd zlib-1.2.5

./configure --prefix=/cross/win64/usr/local --static --64

make

x86_64-w64-mingw32-ranlib libz.a

make

make install

cp *.h /cross/win64/usr/local/include

cd ..

SZip 2.1

I don't think this is even used in the final product, but it won't hurt to have it. There are no special steps.

cd szip-2.1

mkdir build-win64

cd build-win64

../configure --host=x86_64-w64-mingw32 --with-sysroot=/cross/win64/usr/local --prefix=/cross/win64/usr/local

make

make install

cd ../..

LibJPEG

No special steps.

cd jpeg-8c

mkdir build-win64

cd build-win64

../configure --host=x86_64-w64-mingw32 --with-sysroot=/cross/win64/usr/local --prefix=/cross/win64/usr/local

make

make install

cd ../..

CFITSIO

This library is a loose cannon that plays by its own rules, so you'll need to temporarily override one of the safety features of the compiler.

You'll also need to set up some symbolic links so that everything can find the files it generates.

cd cfitsio

export CFLAGSTSAVE="$CFLAGS"

export CFLAGS="$CFLAGS -Wl,-allow-multiple-definition"

./configure --host=x86_64-w64-mingw32 --prefix=/cross/win64/usr/local

make

make install

export CFLAGS="$CFLAGSTSAVE"

cd ..

bash

cd /cross/win64/usr/local/include

mkdir cfitsio

cd cfitsio

ln -s ../fitsio2.h fitsio2.h

ln -s ../fitsio.h fitsio.h

cd /cross/win64/usr/local/lib

mkdir cfitsio

cd cfitsio

ln -s ../libcfitsio.a libcfitsio.a

exit

LibPNG

No special steps.

cd libpng-1.2.46

mkdir build-win64

cd build-win64

../configure --host=x86_64-w64-mingw32 --prefix=/cross/win64/usr/local

make

make install

cd ../..

LibTIFF

No special steps.

cd tiff-3.9.5

mkdir build-win64

cd build-win64

../configure --host=x86_64-w64-mingw32 --with-sysroot=/cross/win64/usr/local --prefix=/cross/win64/usr/local

make

make install

cd ../..

Regex

No special steps (! Even though we're working with a version made for use on Windows®!).

cd regex-20090805

mkdir build-win64

cd build-win64

../configure --host=x86_64-w64-mingw32 --prefix=/cross/win64/usr/local

make

make install

cd ../..

HDF5

Uh oh. Here comes trouble.

First, make the following change to all of the following files in hdf5-1.8.8:

  1. Locate the line which begins with TEST_SCRIPT = (it will read something like TEST_SCRIPT = $(top_srcdir)/test/testerror.sh depending on which of the files you are editing). There will be one - and only one - of these lines in each of the indicated files.
  2. Delete everything on that line after the equals sign (including the space). That is, the line should end up reading TEST_SCRIPT = with no additional text on that line.
  3. Save the file and exit.

That change is to prevent the tests from being executed, because they will fail (Linux won't know what to do with the Windows® executables that are generated).

The next change is made for similar reasons - the configure script will fail if it realizes you're cross-compiling.

Edit hdf5-1.8.8/configure and locate the 2-3 copies of the as_fn_error () function, which will look like this:

as_fn_error ()

{

as_status=$1; test $as_status -eq 0 && as_status=1

if test "$4"; then

as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack

$as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4

fi

$as_echo "$as_me: error: $2" >&2

as_fn_exit $as_status

} # as_fn_error

What you want to do is comment out the as_fn_exit $as_status line, so that the whole thing looks like this:

as_fn_error ()

{

as_status=$1; test $as_status -eq 0 && as_status=1

if test "$4"; then

as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack

$as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4

fi

$as_echo "$as_me: error: $2" >&2

#as_fn_exit $as_status

} # as_fn_error

This is actually a really horrible hack, because it means if the configure script runs into any sort of error, it will continue running. But fixing it the right way would be a lot of work, and CFITSIO was such a bad influence on us that we're just going to go ahead and break all of the rules.

Save the file and exit.

Edit hdf5-1.8.8/src/H5private.h. Look for the line which reads:

#define HDmkdir(S,M) mkdir(S,M)

Change it to read:

#define HDmkdir(S,M) _mkdir(S)

Save the file and exit.

Edit hdf5-1.8.8/tools/h5ls/h5ls.c.

Look for this block:

#elif defined(H5_HAVE_GETCONSOLESCREENBUFFERINFO)

{

/* Win32 C */

CONSOLE_SCREEN_BUFFER_INFO scr;

GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &scr);

width = scr.srWindow.Right - scr.srWindow.Left + 1;

}

Replace it with this:

#elif defined(H5_HAVE_GETCONSOLESCREENBUFFERINFO)

{

/* Win32 C */

width = 80;

}

Now you're finally ready to build HDF5.

cd hdf5-1.8.8

mkdir build-win64

cd build-win64

../configure --host=x86_64-w64-mingw32 --prefix=/cross/win64/usr/local --with-zlib=/cross/win64/usr/local --enable-cxx --enable-shared=no

make

After some time, the build will fail with a message like:

/bin/sh: line 1: ./H5make_libsettings.exe: cannot execute binary file

This is because part of the HDF5 build process is to dynamically generate some source code, compile it, execute it, and capture the results to generate more source code. If someone isn't cross-compiling, this works reasonably well. What you'll need to do is to copy src/libhdf5.settings and src/H5make_libsettings.exe to a 64-bit Windows® system and run the executable from the command line like this:

H5make_libsettings.exe > H5lib_settings.c

...then copy the resulting H5lib_settings.c back to the hdf5-1.8.8/src directory on the Linux system.[4]

Once the .c file is copied back, run make again. After awhile, you will get another error similar to the first one:

/bin/sh: line 1: ./H5detect.exe: cannot execute binary file

This time, you'll need to copy src/libhdf5.settings and src/H5detect.exe to a 64-bit Windows® system and run the executable from the command line like this:

H5detect.exe > H5Tinit.c

...then copy the resulting H5Tinit.c back to the hdf5-1.8.8/src directory on the Linux system.

Run make again. You may need to go through this process several times.

Finally, once the build completes, you can install it...

make install

...and then fix an issue potentially introduced by a bad "feature" of recent versions of GCC.

The fix here is to edit the following files:

...and look for any lines that begin with dependency_libs= and also contain one or more equals signs in the path. For example:

dependency_libs=' -L=/lib =/cross/win64/usr/local/lib/libsz.la -lz'

These will break the DaVinci's Shadow build because they don't make any sense. Thanks, GCC developers!

If the path after the equals sign is complete (e.g. /cross/win64/usr/local/lib/libsz.la), just delete the equals sign. If it is not complete (IE it does not point to somewhere within the /cross directory structure, make it a complete path. So, using the example above, you should end up with:

dependency_libs=' -L/cross/win64/usr/local/lib /cross/win64/usr/local/lib/libsz.la -lz'

After updating all four files, you should have a working cross-compile environment for the 64-bit Windows® version of DaVinci's Shadow.

Remember to exit your shell session to clear the custom environment variables that were set if you want to do anything other than use the cross-compiler, and when you go to use it again, set all four of them again (they're earlier in these instructions).

64-bit Cross-Compile

Now would be a good time to make sure the cross-compile environment works.

Unpack dshadow-2.9.2.tar.bz2 somewhere, if you haven't already. What I typically do is something like this, so that I can compile it natively for Linux and for both 64-bit and 32-bit Windows on the same system:

tar -xjvf dshadow-2.9.2.tar.bz2

mv dshadow-2.9.2 dshadow-2.9.2-linux

cp -r dshadow-2.9.2-linux dshadow-2.9.2-win64

cp -r dshadow-2.9.2-linux dshadow-2.9.2-win32

If you have already unpacked it, and have rebuilt the configure script from configure.ac for some reason, you will need to manually apply a fix. Anyone who has not rebuilt the script can skip this step. The fix is the same as one of the ones used for HDF5, above: edit configure, and in any copies of the as_fn_error () function, comment out the as_fn_exit $as_status line. This has already been done in the version of configure included with the source code.

Actually compiling the software is pretty easy, although because it references CFITSIO you'll need to use the same workaround regarding redefined values as for that library.

Make sure you have set the four environment variables mentioned earlier in the instructions before proceeding!

cd into wherever you unpacked the archive (dshadow-2.9.2-win64 if you used my method). Then:

export CFLAGSTSAVE="$CFLAGS"

export CFLAGS="$CFLAGS -Wl,-allow-multiple-definition"

./configure --host=x86_64-w64-mingw32 --prefix=/cross/win64/usr/local --with-hdf5=/cross/win64/usr/local --with-cfitsio=/cross/win64/usr/local

make

make install

export CFLAGS="$CFLAGSTSAVE"

Assuming the build is successful, you will need to copy all of the following files to your Windows® system to use the result:

Build Environment Setup - 32-bit Cross-Compiler

Second verse/pretty similar to the first/but don't just skim over the directions or you'll probably break something.

In this section, you will:

  1. Set up the combination of Binutils, GCC, and MinGW-w64 as a dedicated 32-bit Windows® cross-compiler.
  2. Create an alternate directory structure for shared components and the final product to go to (to avoid conflicts with native components on the system and the 64-bit components from the previous section).

These are the commands I used:

mkdir /cross/win32

mkdir /cross/win32/usr

mkdir /cross/win32/usr/local

mkdir /cross/win32/usr/local/bin

mkdir /cross/win32/usr/local/include

mkdir /cross/win32/usr/local/lib

mkdir /cross/win32/usr/local/sbin

mkdir /cross/win32/usr/local/share

mkdir /cross/win32/usr/local/src

mkdir /cross/win32/usr/local/man

cd binutils-2.22

mkdir build-win32

cd build-win32

../configure --target=i686-w64-mingw32 --with-sysroot=/cross/win32/usr/local --prefix=/cross/win32/usr/local

make

make install

cd ../../mingw-w64-v2.0.1/mingw-w64-headers

mkdir build-win32

cd build-win32

../configure --host=i686-w64-mingw32 --prefix=/cross/win32/usr/local

make

make install

ln -s /cross/win32/usr/local/i686-w64-mingw32 /cross/win32/usr/local/mingw

ln -s /cross/win32/usr/local/i686-w64-mingw32/lib /cross/win32/usr/local/i686-w64-mingw32/lib64

cd ../../../gcc-4.6.2

mkdir build-win32

cd build-win32

../configure --target=i686-w64-mingw32 --enable-languages=c,c++ --enable-shared --with-sysroot=/cross/win32/usr/local --prefix=/cross/win32/usr/local --disable-multilib

make all-gcc

make install-gcc

export PATH="$PATH:/cross/win32/usr/local/bin:/cross/win32/usr/local/i686-w64-mingw32/bin"

cd ../../mingw-w64-v2.0.1/mingw-w64-crt

mkdir build-win32

cd build-win32

../configure --host=i686-w64-mingw32 --enable-lib32 --with-sysroot=/cross/win32/usr/local --prefix=/cross/win32/usr/local

make

make install

cd ../../../gcc-4.6.2

cd build-win32

../configure --target=i686-w64-mingw32 --enable-languages=c,c++,fortran --enable-shared --with-sysroot=/cross/win32/usr/local --prefix=/cross/win32/usr/local --disable-multilib[5]

make

make install

exit

IMPORTANT!

When using the 32-bit cross-compiler, you should set the following environment variables. Otherwise many, many build failures will occur.

export PATH="$PATH:/cross/win32/usr/local/bin:/cross/win32/usr/local/i686-w64-mingw32/bin"

export CC="/cross/win32/usr/local/bin/i686-w64-mingw32-gcc"

export CFLAGS="-I/cross/win32/usr/local/include -L/cross/win32/usr/local/lib"

export LD_LIBRARY_PATH=".:/cross/win32/usr/local/lib"

Build Environment Setup - 32-bit Prerequisite Components

In this section, you will compile the prerequisites needed for the build of DaVinci's Shadow later on. This requires nearly identical hacks and workarounds as in the 64-bit section, so if you are looking for an explanation of why certain things are done, please look there.

PDCurses

Copy the PDCurses-3.4/pdcurses/terminfo.c file that you made back in the 64-bit section into the corresponding directory for your 32-bit prerequisite source (~/ds291prereq32/PDCurses-3.4/pdcurses/, if you are following my directions exactly). If you are not building the 64-bit environment, just follow the directions in that section regarding this file.

You'll need to manually edit PDCurses-3.4/win32/mingwin32.mak whether you built the 64-bit environment or not, because the version for the 32-bit environment is different:

Replace all occurrences of copy with cp, and all occurrences of del with rm.
In vi/vim, you can do this with :%s/copy/cp/g and :%s/del/rm/g

Change the line which reads:

CC = gcc

To:

CC = i686-w64-mingw32-gcc

Change the line which reads:

CFLAGS += -I$(PDCURSES_SRCDIR)

To:

CFLAGS += -I$(PDCURSES_SRCDIR) -I/cross/win32/usr/local/include -L/cross/win32/usr/local/lib

Now you can execute the makefile. It will break in a couple of places, so there are some manual fixes in the following commands:

cd PDCurses-3.4/win32/

make -f mingwin32.mak

i686-w64-mingw32-ranlib pdcurses.a

make -f mingwin32.mak

cp panel.a /cross/win32/usr/local/lib/libpanel.a

cp pdcurses.a /cross/win32/usr/local/lib/libcurses.a

cd ..

cp *.h /cross/win32/usr/local/include

cd ..

Readline 6.1

No special requirements here.

cd readline-6.1

mkdir build-win32

cd build-win32

../configure --host=i686-w64-mingw32 --prefix=/cross/win32/usr/local --with-curses

make

make install

cd ../..

ZLib 1.2.5

A few workarounds are necessary here because the configure script is so old. These changes are not the same as for the 64-bit version, so don't just copy the file over.

Edit zlib-1.2.5/configure and add the following block of code just after the initial comments (or right at the beginning of the file):

CC=i686-w64-mingw32-gcc

CFLAGS="-I/cross/win32/usr/local/include -L/cross/win32/usr/local/lib"

The script will still break when you run it (several times, including during the make install), so you'll be doing some manual workaround commands like with the PDCurses build.

cd zlib-1.2.5

./configure --prefix=/cross/win32/usr/local --static

make

i686-w64-mingw32-ranlib libz.a

make

make install

cp *.h /cross/win32/usr/local/include

cd ..

SZip 2.1

I don't think this is even used in the final product, but it won't hurt to have it. There are no special steps.

cd szip-2.1

mkdir build-win32

cd build-win32

../configure --host=i686-w64-mingw32 --with-sysroot=/cross/win32/usr/local --prefix=/cross/win32/usr/local

make

make install

cd ../..

LibJPEG

No special steps.

cd jpeg-8c

mkdir build-win32

cd build-win32

../configure --host=i686-w64-mingw32 --with-sysroot=/cross/win32/usr/local --prefix=/cross/win32/usr/local

make

make install

cd ../..

CFITSIO

The workarounds here are pretty similar to those for the 64-bit version of this library.

cd cfitsio

export CFLAGSTSAVE="$CFLAGS"

export CFLAGS="$CFLAGS -Wl,-allow-multiple-definition"

./configure --host=i686-w64-mingw32 --prefix=/cross/win32/usr/local

make

make install

export CFLAGS="$CFLAGSTSAVE"

cd ..

bash

cd /cross/win32/usr/local/include

mkdir cfitsio

cd cfitsio

ln -s ../fitsio2.h fitsio2.h

ln -s ../fitsio.h fitsio.h

cd /cross/win32/usr/local/lib

mkdir cfitsio

cd cfitsio

ln -s ../libcfitsio.a libcfitsio.a

exit

LibPNG

No special steps.

cd libpng-1.2.46

mkdir build-win32

cd build-win32

../configure --host=i686-w64-mingw32 --prefix=/cross/win32/usr/local

make

make install

cd ../..

LibTIFF

No special steps.

cd tiff-3.9.5

mkdir build-win32

cd build-win32

../configure --host=i686-w64-mingw32 --with-sysroot=/cross/win32/usr/local --prefix=/cross/win32/usr/local

make

make install

cd ../..

Regex

No special steps.

cd regex-20090805

mkdir build-win32

cd build-win32

../configure --host=i686-w64-mingw32 --prefix=/cross/win32/usr/local

make

make install

cd ../..

HDF5

HDF5 is just as hard to cross-compile for 32-bit Windows® as it is for 64-bit, with one exception: if you really, really need to do this without access to an actual Windows® system, supposedly you can execute the 32-bit executables using WINE. I have not tried this, and do not recommend it, as it's probably more trouble than it's worth.

To save yourself some time, copy the following files that you modified in the 64-bit section into the directory structure for the 32-bit environment:

For example, if you followed my directions exactly and your 64-bit files are in ~/ds291prereq64, and your 32-bit files are in ~/ds291prereq32, you would copy ~/ds291prereq64/hdf5-1.8.8/test/Makefile.in to ~/ds291prereq32/hdf5-1.8.8/test/, etc.

If you didn't create the 64-bit build environment, go make the changes to those files that are described in that section.

The build process itself is very similar to the 64-bit version:

cd hdf5-1.8.8

mkdir build-win32

cd build-win32

../configure --host=i686-w64-mingw32 --prefix=/cross/win32/usr/local --with-zlib=/cross/win32/usr/local --enable-cxx --enable-shared=no

make

After some time, the build will fail with a message like:

/bin/sh: line 1: ./H5make_libsettings.exe: cannot execute binary file

Copy src/libhdf5.settings and src/H5make_libsettings.exe to a 32-bit or 64-bit Windows® system and run the executable from the command line like this:

H5make_libsettings.exe > H5lib_settings.c

...then copy the resulting H5lib_settings.c back to the hdf5-1.8.8/src directory on the Linux system.

Once the .c file is copied back, run make again. After awhile, you will get another error similar to the first one:

/bin/sh: line 1: ./H5detect.exe: cannot execute binary file

This time, you'll need to copy src/libhdf5.settings and src/H5detect.exe to a 32-bit or 64-bit Windows® system and run the executable from the command line like this:

H5detect.exe > H5Tinit.c

...then copy the resulting H5Tinit.c back to the hdf5-1.8.8/src directory on the Linux system.

Run make again. You may need to go through this process several times.

Finally, once the build completes, you can install it...

make install

...and then fix an issue potentially introduced by a bad "feature" of recent versions of GCC.

The fix here is to edit the following files:

...and look for any lines that begin with dependency_libs= and also contain one or more equals signs in the path. For example:

dependency_libs=' -L=/lib =/cross/win32/usr/local/lib/libsz.la -lz'

These will break the DaVinci's Shadow build because they don't make any sense. Thanks, GCC developers!

If the path after the equals sign is complete (e.g. /cross/win32/usr/local/lib/libsz.la), just delete the equals sign. If it is not complete (IE it does not point to somewhere within the /cross directory structure, make it a complete path. So, using the example above, you should end up with:

dependency_libs=' -L/cross/win32/usr/local/lib /cross/win32/usr/local/lib/libsz.la -lz'

After updating all four files, you should have a working cross-compile environment for the 32-bit Windows® version of DaVinci's Shadow.

Remember to exit your shell session to clear the custom environment variables that were set if you want to do anything other than use the cross-compiler, and when you go to use it again, set all four of them again (they're earlier in these instructions).

32-bit Cross-Compile

You should have a working 32-bit cross-compile environment somewhere now.

Unpack dshadow-2.9.2.tar.bz2 somewhere, if you haven't already. See my notes in the 64-bit section about how I keep the Linux, 32-bit cross-compile, and 64-bit cross-compile versions separate.

If you have already unpacked it, and have rebuilt the configure script from configure.ac for some reason, you will need to manually apply a fix. Anyone who has not rebuilt the script can skip this step. The fix is the same as one of the ones used for HDF5, above: edit configure, and in any copies of the as_fn_error () function, comment out the as_fn_exit $as_status line. This has already been done in the version of configure included with the source code.

Actually compiling the software is pretty easy, although because it references CFITSIO you'll need to use the same workaround regarding redefined values as for that library.

Make sure you have set the 32-bit four environment variables mentioned earlier in the instructions before proceeding! They are not the same as the 64-bit versions!

cd into wherever you unpacked the archive (dshadow-2.9.2-win32 if you used my method). Then:

export CFLAGSTSAVE="$CFLAGS"

export CFLAGS="$CFLAGS -Wl,-allow-multiple-definition"

./configure --host=i686-w64-mingw32 --prefix=/cross/win32/usr/local --with-hdf5=/cross/win32/usr/local --with-cfitsio=/cross/win32/usr/local

make

make install

export CFLAGS="$CFLAGSTSAVE"

Assuming the build is successful, you will need to copy all of the following files to your Windows® system to use the result:

Acknowledgements

These instructions are based (extremely loosely) on ASU's Building DaVinci for Windows page.

The existence of a Windows version of this utility is the result of the dedication of numerous open source developers. Even though I may complain about the lengths it's necessary to go to to get some of the packages to compile, it's a lot better than not having them at all.

 
Download
File Size Version Release Date Author
DaVinci's Shadow (Source Code) 41 MiB 2.9.2 2012-01-15 Numerous
This is the complete source code package for DaVinci's Shadow 2.9.2. If you are compiling DaVinci's Shadow, this is probably the file you want.
 
Download
File Size Version Release Date Author
DaVinci's Shadow Build Prerequisites 111 MiB 2.9.1 2012-01-14 Numerous
This package includes everything needed to create the cross-compile environment so someone can build DaVinci's Shadow on Linux for Windows®. If you're following the directions for compiling DaVinci's Shadow for any other platform, you won't be using all of the contents of this file.
 
Footnotes
1. The two ln commands are to work around an issue where MinGW expects a certain directory structure.
2. I had trouble getting Fortran support to compile unless I saved it for the last step. Fortran is needed for certain prerequisites (like CFITSIO) to build completely.
3. The exit at the end is to clear any customized environment variables, which can wreak havoc on later parts of this process.
4. If you are trying to build HDF5 with --enable-shared=yes for some reason, instead of using the .exe files in hdf5-1.8.8/src, you will need to use the ones in hdf5-1.8.8/src/.libs, and copy the resulting .c files back to hdf5-1.8.8/src/.libs. The .exe files will still be generated in the src directory, but executing them will produce no output, and the build will fail when you try to use the empty files.
5. This command was originally listed incorrectly as:
../configure --target=i686-w64-mingw32 --enable-targets=all --enable-languages=c,c++,fortran --enable-shared --with-sysroot=/cross/win32/usr/local --prefix=/cross/win32/usr/local
That command will result in an obscure error along the lines of "cannot compute suffix of object files", at least if you follow the rest of the commands the way I've documented them. The revised command is the one I actually used to build my cross-compile environment, but I copy/pasted the wrong version into these instructions when I originally posted them.
The biggest change between them (as far as I understand GCC) is the --disable-multilib flag. I don't need multilib for what I use the cross-compile environment for, so it doesn't impact me. If you do need it for some reason, and you manage to get things working without that flag, please let me know.
Thanks to Andy Gardner for pointing out that there was an issue!
 
[ Page Icon ]