<!> A simpler method for cross compiling is described in Win32_Cross_Compiling_With_Mingw.

This document provides instructions for building native win32 gstreamer binaries. Specifically, it describes a method of using the MinGW cross compiler in chroot environment under debian linux1.

1. Motivation

Building native win32 binaries can be acheived from the comfort of your Linux box by using the mingw cross compiler. I've found, however, that some of the autoconf macros will pick-up native Linux headers/libraries installed under /usr/local or /usr. By creating a gstreamer-cross-build chroot environment it is possible to prevent this kind of mix-up and obliterate the need to pass lots of --disable-xxx to the configure script for Here are instructions on how to cross-compile gstreamer on a Debian/Linux using the MinGW cross-compiler to create win32 binaries.

2. Creating a chroot environment

(!) You need to decide either to install mingw 3.4.5 compatible (such as debian etch) or the newer mingw32 4.2.1 (Ubuntu hardy) based system. You may also want to install both. See below.

/!\ The dvdreadsrc plugin compiled with mingw32 4.2.1 did not work for me (TalShalif), while the same compiled with mingw 3.4.5 worked fine (you can even copy the one you compiled on 3.4.5 to 4.2.1 and see either it will work for you too).

2.1. Create the Debian system

  1. Install debootstrap
    tanaka@linux> sudo apt-get install debootstrap
  2. Create root file system
    • Ubuntu hardy (mingw32 4.2.1)

      tanaka@linux> sudo debootstrap hardy mingw-chroot
    • Debian etch (mingw32 3.4.5)

      tanaka@linux> sudo debootstrap etch mingw-chroot
  3. (optional) Add shell chroot ID to avoid confusion
    root@linux> sudo chroot mingw-chroot
    root@linux# echo "gstreamer-mingw" > /etc/debian_chroot
    root@linux# exit

2.2. Install required packages on chroot system

tanaka@linux> sudo chroot mingw-chroot
  1. Update /etc/apt/source.list
    • Ubuntu hardy:

      # Binary
      deb hardy main restricted universe multiverse
      deb hardy-updates main restricted universe multiverse
      deb hardy-security main restricted universe multiverse
    • Debian etch: {{{deb http://ftp.us.debian.org/debian etch main contrib non-free

deb http://ftp.us.debian.org/debian etch-proposed-updates main contrib non-free }}}

<!> After completing the above steps, you may find it simpler to continue your compilation using David Schleef's script, as described in Win32_Cross_Compiling_With_Mingw.

2.3. Move standard headers, libs, binutils out of the way

You don't want any of gstreamer's autoconfig macros to pick-up libraries nor headers installed on the system (i.e. /usr/lib, /usr/include):

  1. Move headers out of the way
    (gstreamer-mingw)root@linux# mkdir /usr/include/tmp && mv /usr/include/* /usr/include/tmp
  2. Move away link libraries
    (gstreamer-mingw)root@linux# mkdir /usr/lib/tmp && mv /usr/lib/*.{a,so} /usr/lib/tmp
    Against the standard practice of libxx.so.n, some runtime libraries are named libxx-n.n.so. Put them back:
    (gstreamer-mingw)root@linux# mv /usr/lib/tmp/*[0-9]*.so /usr/lib
    But, but.. except for glib libraries named libgxxx-2.0.so, which need to be moved away again:
    (gstreamer-mingw)root@linux# mv /usr/lib/libg*-2.0.so /usr/lib/tmp
  3. Replace native binutils executables with links to mingw tools
    cd /usr/bin
    mkdir tmp
    mv gcc ar ranlib as ld cc cpp tmp
    for i in gcc ar ranlib as ld cc cpp; do \
      ln -s i586-mingw32msvc-$i $i; \
    done
    ln -s i586-mingw32msvc-dlltool dlltool
    ln -s i586-mingw32msvc-dllwrap dllwrap

2.4. Setup normal user environment inside chroot

Now you would want to be able to access your gstreamer development tree and/or home directory as a normal user from inside the chroot environment:

  1. Mount host home directory
    tanaka@linux> sudo mount --bind /home mingw-chroot/home    
  2. Add/Synchronize linux host => chroot host user ID Assuming your real user name is 'tanaka' and your uid on the Linux host is 1000:

    (gstreamer-mingw)root@linux# useradd -d /home/tanaka -s /bin/bash -u 1000 tanaka
    Now you can log into your chroot system as user 'tanaka' thusly:
    tanaka@linux> sudo chroot mingw-chroot su - tanaka
    (gstreamer-mingw)tanaka@linux:~$ id
    => uid=1000(tanaka) gid=1000(tanaka) groups=1000(tanaka)

3. Building 3rd party win32 repository

3.1. Initializing stow repository

mkdir -p ~/win32/stow    

Make win32 repo available as /x on both the chroot environment as well as the real host. This will enable mapping ~tanaka/win32 to drive x: on a real windows machine.

tanaka@linux> sudo ln -s ~/win32 /x
(gstreamer-mingw)root@linux# ln -s ~tanaka/win32 /x

3.2. Install precompiled Win32 binaries

tanaka@linux> cd /x/stow

Download fromhttp://www.gtk.org/download-windows.htmland install the following:

3.2.1. Glib

cd /tmp
wget http://ftp.gnome.org/pub/gnome/binaries/win32/glib/2.16/glib-2.16.5.zip
wget http://ftp.gnome.org/pub/gnome/binaries/win32/glib/2.16/glib-dev-2.16.5.zip
mkdir -p /x/stow/glib-2.16.5
cd /x/stow/glib-2.16.5
unzip /tmp/glib-2.16.5.zip
unzip /tmp/glib-dev-2.16.5.zip
find -name "*\.pc" | xargs sed -i 's,^prefix=.*$,prefix=/x,'
cd /x/stow
stow glib-2.16.5

3.2.2. Iconv

cd /tmp
wget http://www.gimp.org/~tml/gimp/win32/libiconv-1.9.1.bin.woe32.zip
mkdir -p /x/stow/libiconv-1.9.1
cd /x/stow/libiconv-1.9.1
unzip /tmp/libiconv-1.9.1.bin.woe32.zip
cd /x/stow
stow libiconv-1.9.1

3.2.3. Gettext

cd /tmp/
wget http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/gettext-runtime-0.17-1.zip
wget http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/gettext-runtime-dev-0.17-1.zip
mkdir /x/stow/gettext-runtime-0.17-1
cd /x/stow/gettext-runtime-0.17-1
unzip /tmp/gettext-runtime-0.17-1.zip
unzip /tmp/gettext-runtime-dev-0.17-1.zip
cd /x/stow
stow gettext-runtime-0.17-1

3.2.4. Directx headers

3.3. Compile other 3rd party packages

{i} It probably won't hurt (?) to add -mthreads to CFLAGS of all compilations. Also, some net functions (e.g. getaddrinfo()) are only available if you set WindowsXP compilation compatibility:

export CFLAGS='-mthreads -D_WIN32_WINNT=0x0501 -DWINVER=0x0501'

3.3.1. Liboil

<!> There is a linking error compiling one of the examples. Use the '-k' flag to force compilation

cd /tmp
wget http://liboil.freedesktop.org/download/liboil-0.3.15.tar.gz
tar zxvf liboil-0.3.15.tar.gz
cd liboil-0.3.15
./configure --prefix=/x --host=i586-mingw32msvc
make -k
rm -rf /tmp/liboil-0.3.15-dist
make -k install DESTDIR=/tmp/liboil-0.3.15-dist
(cd /x/stow && stow -D liboil-0.3.15)
rm -rf /x/stow/liboil-0.3.15
mv /tmp/liboil-0.3.15-dist/x /x/stow/liboil-0.3.15
cd /x/stow
stow liboil-0.3.15

3.3.2. Libxml2

cd /tmp
wget ftp://xmlsoft.org/libxml2/libxml2-2.6.31.tar.gz
tar zxvf libxml2-2.6.31.tar.gz
cd libxml-2.6.31
./configure --prefix=/x --host=i586-mingw32msvc
make
make install DESTDIR=/tmp/libxml2-2.6.31-dist
mv /tmp/libxml2-2.6.31-dist/x /x/stow/libxml2-2.6.31
cd /x/stow/
stow libxml2-2.6.31

3.3.3. Zlib

  1. Get source
    cd /tmp
    wget http://www.gzip.org/zlib/zlib-1.2.3.tar.gz
    tar zxvf zlib-1.2.3.tar.gz
    cd zlib-1.2.3
  2. Configure

    {i} Zlib does not use automake/libtool

    (!) We can create and use a cross-compile libtool script doing the following:

    cat > configure.ac <<EOF
    AC_INIT(zlib, 1.2.3)
    
    AC_LIBTOOL_WIN32_DLL
    AC_PROG_LIBTOOL
    EOF
    libtoolize
    aclocal
    autoconf
    touch install.sh
    ./configure --prefix=/x --host=i586-mingw32msvc
  3. build

    The above would have craeted a libtool script which we will use to build zlib:

    for i in adler32 compress crc32 deflate gzio infback inffast inflate inftrees trees uncompr zutil; do \
      ./libtool --mode=compile --tag=CC i586-mingw32msvc-gcc -O3 -Wall -mthreads -c -o $i.lo $i.c; \
    done
    ./libtool --tag=CC --mode=link i586-mingw32msvc-gcc -version-info 1 -mthreads -o libz.la -rpath /x/lib -module  -no-undefined *.lo
  4. install Manually install required files:
    mkdir -p /x/stow/zlib-1.2.3/{bin,lib,include}
    ./libtool --mode=install /usr/bin/install -c  libz.la /x/stow/zlib-1.2.3/lib/libz.la
    (cd /x/stow/zlib-1.2.3/bin && ln -s ../lib/*.dll .)
    cp zlib.h zconf.h /x/stow/zlib-1.2.3/include
    cd /x/stow
    stow zlib-1.2.3

3.3.4. Libpng

cd /tmp
wget http://prdownloads.sourceforge.net/libpng/libpng-1.2.29.tar.bz2
tar jxvf libpng-1.2.29.tar.bz2
cd libpng-1.2.29
LDFLAGS=-L/x/lib CFLAGS=-I/x/include PKG_CONFIG_PATH=/x/lib/pkgconfig ./configure --prefix=/x --host=i586-mingw32msvc
make
make -k install DESTDIR=/tmp/libpng-1.2.29-dist
mv /tmp/libpng-1.2.29-dist/x/ /x/stow/libpng-1.2.29
cd /x/stow/
stow libpng-1.2.29

3.3.5. Libogg

/!\ Could not compile under mingw 3.4.5

cd /tmp
wget http://downloads.xiph.org/releases/ogg/libogg-1.1.3.tar.gz
tar zxvf libogg-1.1.3.tar.gz
cd libogg-1.1.3
./configure --prefix=/x --host=i586-mingw32msvc
make
make  install DESTDIR=/tmp/libogg-1.1.3-dist
mv /tmp/libogg-1.1.3-dist/x /x/stow/libogg-1.1.3
cd /x/stow
stow libogg-1.1.3

3.3.6. Libvorbis

cd /tmp
wget http://downloads.xiph.org/releases/vorbis/libvorbis-1.2.0.tar.gz
cd libvorbis-1.2.0
PKG_CONFIG_PATH=/x/lib/pkgconfig ./configure --prefix=/x --host=i586-mingw32msvc
make LDFLAGS='-L/x/lib -logg' -k
make LDFLAGS='-L/x/lib -logg' -k install DESTDIR=/tmp/libvorbis-1.2.0-dist
mv /tmp/libvorbis-1.2.0-dist/x /x/stow/libvorbis-1.2.0
cd /x/stow
stow libvorbis-1.2.0

3.3.7. a52dec

3.3.8. mpeg2dec

cd /tmp/
wget http://libmpeg2.sourceforge.net/files/libmpeg2-0.5.1.tar.gz
tar zxvf libmpeg2-0.5.1.tar.gz
cd libmpeg2-0.5.1
PKG_CONFIG_PATH=/x/lib/pkgconfig ./configure --prefix=/x --host=i586-mingw32msvc  --enable-shared
make
make install DESTDIR=/tmp/libmpeg2-0.5.1-dist
mv /tmp/libmpeg2-0.5.1-dist/x /x/stow/libmpeg2-0.5.1
cd /x/stow/
stow libmpeg2-0.5.1

3.3.9. Libdvdread/Libdvdnav

/!\ There are some problems compiling/linking against libdvdread on mingw32 4.2.1 (TalShalif).

{i} libdvdnav contains a copy of libdvdread. The latest libdvdnav from mplayer seems to include also all the latest dvdread patches. It also does not hard-code dependancy on libdvdcss.

<!> use make -k due to link error in an unused library

cd /tmp
wget http://www7.mplayerhq.hu/MPlayer/releases/dvdnav/libdvdnav-4.1.2.tar.gz
tar zxvf libdvdnav-4.1.2.tar.gz
cd libdvdnav-4.1.2
./autogen.sh noconfig
PKG_CONFIG_PATH=/x/lib/pkgconfig ./configure --prefix=/x --host=i586-mingw32msvc
make -k
make -k install DESTDIR=/tmp/libdvdnav-4.1.2-dist
mv /tmp/libdvdnav-4.1.2-dist/x /x/stow/libdvdnav-4.1.2
cd /x/stow
stow libdvdnav-4.1.2

3.3.10. Libdvdcss

{i} There is no compilation-time dependancy on libdvdcss. However, libdvdread looks for a runtime DLL libdvdcss.dll in order to read encrypted DVDs

  1. Download and upack code
    cd /tmp
    wget http://download.videolan.org/pub/libdvdcss/1.2.9/libdvdcss-1.2.9.tar.bz2
    tar jxvf libdvdcss-1.2.9.tar.bz2
  2. Configure
    cd libdvdcss-1.2.9
    PKG_CONFIG_PATH=/x/lib/pkgconfig ./configure --prefix=/x --host=i586-mingw32msvc  --enable-shared
  3. Force creation of a DLL using our libtool hack
    sed -i 's,build_libtool_libs=no,build_libtool_libs=yes,' libtool
    make
  4. Install
    make install DESTDIR=/tmp/libdvdcss-1.2.9-dist
    mv /tmp/libdvdcss-1.2.9-dist/x /x/stow/libdvdcss-1.2.9
  5. crete libdvdcss.dll:

    cd /x/stow/libdvdcss-1.2.9/bin
    ln -s libdvdcss-2.dll libdvdcss.dll
  6. stow
    cd /x/stow
    stow libdvdcss-1.2.9

4. Building gstreamer

{i} If you want gstreamer's net features, you would need to set WindowsXP compilation compatibility. Put:

<!> The chroot environment should really be used only to cross-compile gstreamer. Develop and manage your gstreamer sources under your home directory and chroot into 'gstreamer-mingw' only to run 'configure' and 'make' to build and install. If you have not done so already, on the linux host, get the gstreamer source and generate the configuration script under each component. For example:

4.1. gstreamer

(!) gstreamer and gst-* have -Werror in CFLAGS, so some win32-specific compilation warnings will cause make to fail. You can try running make ERROR_CFLAGS="-Wall -Wdeclaration-after-statement -fno-strict-aliasing" to ignore such warnings.

(!) Under 'gstreamer-mingw' chroot:

4.2. gst-plugins-base

{i} compile and install 3rd party libogg, libvorbis if you want these plugins to be installed.

(!) Under 'gstreamer-mingw' chroot:

4.3. gst-plugins-good

{i} you will need to install the directx headers to compile the directvideosink and directaudiosink.

(!) Under 'gstreamer-mingw' chroot:

4.4. gst-plugins-bad

(!) Under 'gstreamer-mingw' chroot:

4.5. gst-plugins-ugly

/!\ The dvdreadsrc plugin compiled with mingw32 4.2.1 did not work for me (TalShalif), while the same compiled with mingw 3.4.5 worked fine (you can even copy the one you compiled on 3.4.5 to 4.2.1 and see either it will work for you too).

(!) Under 'gstreamer-mingw' chroot:

5. Plugin specific build problems

(!) You can try to disable plugins which break your build with --disable-xx - run ./configure --help for more details

{i} Some plugins will not be built for reasons such as faulty shared library dependancy detection. You can always go directly to the plugin sub-directory and run make there to build that particular plugin. You will need to manually copy the result DLL file to /x/stow/gst-plugins-xxx-vvv/lib/gstreamer-0.10 and run stow --restow on gst-plugins-xxx-vvv. Look at the directdraw/directsound example below - you may or may not need to use the forcedll-libtool hack.

5.1. directdraw, directsound

libtool refuses to create the plugin DLLs for directdraw and directsound - both under gst-plugins-good. I have managed to force-create those using the following (the following example is for directdraw, but the same methodology applies to directsound):

  1. The following changes to ltmain.sh will force libtool to at least go through the steps of making the DLLs:
    cd ~/src/gstreamer-dev/gst-plugins-good
    sed 's,build_libtool_libs=no,build_libtool_libs=yes,' < libtool > forcedll-libtool
  2. rebuild directdraw usgin forcedll-libtool
    cd ~/src/gstreamer-dev/gst-plugins-good/sys/directdraw
    make clean
    make ERROR_CFLAGS='-Wall -Wdeclaration-after-statement -fno-strict-aliasing'
  3. re-ran manually the last libtool link phase replacing ../../libtool with ../../forcedll-libtool: e.g.
    /bin/bash ../../libtool --tag=CC --mode=link i586-mingw32msvc-gcc  -g -O2   -o libgstdirectdrawsink.la -rpath /x/lib/gstreamer-0.10 -module -avoid-version -export-symbols-regex '^_*gst_plugin_desc$' -no-undefined libgstdirectdrawsink_la-gstdirectdrawsink.lo libgstdirectdrawsink_la-gstdirectdrawplugin.lo -lddraw -ldxguid -lgdi32 -L/x/lib -lgstbase-0.10 -lgstreamer-0.10 -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lxml2 -lglib-2.0 -lintl   -L/x/lib -lgstreamer-0.10 -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lxml2 -lglib-2.0 -lintl   -lgstvideo-0.10 -lgstinterfaces-0.10
    with:
    /bin/bash ../../forcedll-libtool --tag=CC --mode=link i586-mingw32msvc-gcc  -g -O2   -o libgstdirectdrawsink.la -rpath /x/lib/gstreamer-0.10 -module -avoid-version -export-symbols-regex '^_*gst_plugin_desc$' -no-undefined libgstdirectdrawsink_la-gstdirectdrawsink.lo libgstdirectdrawsink_la-gstdirectdrawplugin.lo -lddraw -ldxguid -lgdi32 -L/x/lib -lgstbase-0.10 -lgstreamer-0.10 -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lxml2 -lglib-2.0 -lintl   -L/x/lib -lgstreamer-0.10 -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lxml2 -lglib-2.0 -lintl   -lgstvideo-0.10 -lgstinterfaces-0.10
  4. Ran manually the final from the above output gcc link command appending the missing library libtool complains it can not find (-ldxguid in directdraw's case): e.g. replace:
    i586-mingw32msvc-gcc -shared .libs/libgstdirectdrawsink.dll.def  .libs/libgstdirectdrawsink_la-gstdirectdrawsink.o .libs/libgstdirectdrawsink_la-gstdirectdrawplugin.o  -lddraw -lgdi32 -L/x/lib /x/lib/libgstbase-0.10.dll.a /x/lib/libgstreamer-0.10.dll.a -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 /x/lib/libxml2.dll.a -lglib-2.0 -lintl /x/lib/libgstvideo-0.10.dll.a /x/lib/libgstinterfaces-0.10.dll.a  -o .libs/libgstdirectdrawsink.dll -Wl,--enable-auto-image-base -Xlinker --out-implib -Xlinker .libs/libgstdirectdrawsink.dll.a
    with:
    i586-mingw32msvc-gcc -shared .libs/libgstdirectdrawsink.dll.def  .libs/libgstdirectdrawsink_la-gstdirectdrawsink.o .libs/libgstdirectdrawsink_la-gstdirectdrawplugin.o  -lddraw -lgdi32 -L/x/lib /x/lib/libgstbase-0.10.dll.a /x/lib/libgstreamer-0.10.dll.a -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 /x/lib/libxml2.dll.a -lglib-2.0 -lintl /x/lib/libgstvideo-0.10.dll.a /x/lib/libgstinterfaces-0.10.dll.a  -o .libs/libgstdirectdrawsink.dll -Wl,--enable-auto-image-base -Xlinker --out-implib -Xlinker .libs/libgstdirectdrawsink.dll.a -ldxguid
  5. Copy DLL to plugin directory
    cp .libs/*.dll /x/stow/gst-plugins-good-${ver}/lib/gstreamer-0.10
    cd /x/stow
    stow --restow gst-plugins-good-${ver}

5.2. dvdread

configure disabled this plugin due to libdvdread detection failure. When manually compiling this plugin I had to re-ran manually the last libtool --tag=CC --mode=link command with -dvdread appended.

5.3. a52

I had to re-ran manually the last libtool --tag=CC --mode=link command with -a52 appended.

6. Testing

6.1. Using wine

(!) Do this on your real linux machine.

Install wine and try to run some simple pipelines:

6.2. On a real MS Windows machine

(!) you need to configure samba with user home directory accsess on your linux machine.

Suposing your Linux machine IP address is 10.0.0.1:

Other pipelines to try:

x:/bin/gst-launch-0.10.exe --gst-plugin-path=x:/lib/gstreamer-0.10 dvdreadsrc device=e: ! queue ! dvddemux name=demux .current_video ! queue ! mpeg2dec ! ffmpegcolorspace ! directdrawsink demux.current_audio ! queue ! a52dec ! audioconvert ! directsoundsink
  1. I am running Ubuntu 8.04.1 (1)