#pragma section-numbers on 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 linux<>. <> == 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. == 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). === Create the Debian system === 1. Install debootstrap {{{ tanaka@linux> sudo apt-get install debootstrap}}} 1. 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}}} 1. (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}}} === 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 }}} {{{ (gstreamer-mingw)root@linux# apt-get update }}} 1. Install packages * Ubuntu ''hardy'': {{{ (gstreamer-mingw)root@linux# apt-get install mingw32 dpkg-dev pkg-config wget libglib2.0-dev language-pack-en tzdata unzip libtool automake autoconf m4 gettext cvs flex bison stow wine git-core subversion}}} * Debian ''etch'': {{{ (gstreamer-mingw)root@linux# apt-get install mingw32 mingw32-binutils dpkg-dev pkg-config wget libglib2.0-dev bzip2 less tzdata unzip libtool automake autoconf m4 gettext cvs flex bison stow wine git-core subversion locales-all }}} 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]]. === 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}}} 1. 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}}} 1. 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 }}} === 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 }}} 1. 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)}}} == Building 3rd party win32 repository == === 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 }}} === Install precompiled Win32 binaries === {{{ tanaka@linux> cd /x/stow }}} Download fromhttp://www.gtk.org/download-windows.htmland install the following: ==== 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}}} ==== 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}}} ==== 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 }}} ==== Directx headers ==== * Install headers {{{ cd /tmp wget http://www.lysator.liu.se/~peda/directx-headers/directx-headers-0.03.tar.gz tar -C /x/stow -zxvf /tmp/directx-headers-0.03.tar.gz cd /x/stow stow directx-headers-0.03}}} * Fix small header compilation error Patch will fail unless the following is copied as-is. (!) This change is trivial enough to modify by hand {{{ cd /x/stow/directx-headers-0.03/include patch < 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}}} ==== 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}}} ==== 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 }}} 1. Configure {i} Zlib does not use automake/libtool (!) We can create and use a cross-compile libtool script doing the following: {{{ cat > configure.ac < 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 }}} ==== 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 }}} 1. Configure {{{ cd libdvdcss-1.2.9 PKG_CONFIG_PATH=/x/lib/pkgconfig ./configure --prefix=/x --host=i586-mingw32msvc --enable-shared }}} 1. Force creation of a DLL using our libtool hack {{{ sed -i 's,build_libtool_libs=no,build_libtool_libs=yes,' libtool make }}} 1. Install {{{ make install DESTDIR=/tmp/libdvdcss-1.2.9-dist mv /tmp/libdvdcss-1.2.9-dist/x /x/stow/libdvdcss-1.2.9 }}} 1. crete ''libdvdcss.dll'': {{{ cd /x/stow/libdvdcss-1.2.9/bin ln -s libdvdcss-2.dll libdvdcss.dll }}} 1. stow {{{ cd /x/stow stow libdvdcss-1.2.9 }}} == Building gstreamer == {i} If you want gstreamer's net features, you would need to set WindowsXP compilation compatibility. Put: {{{ export CFLAGS='-mthreads -D_WIN32_WINNT=0x0501 -DWINVER=0x0501' }}} before running the ''configure'' script under the chroot environment 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: * Get source {{{ mkdir -p ~/src/gstreamer-dev cd ~/src/gstreamer-dev cvs -d :pserver:anoncvs@anoncvs.freedesktop.org:/cvs/gstreamer co gstreamer cvs -d :pserver:anoncvs@anoncvs.freedesktop.org:/cvs/gstreamer co gst-plugins-base cvs -d :pserver:anoncvs@anoncvs.freedesktop.org:/cvs/gstreamer co gst-plugins-good cvs -d :pserver:anoncvs@anoncvs.freedesktop.org:/cvs/gstreamer co gst-plugins-bad cvs -d :pserver:anoncvs@anoncvs.freedesktop.org:/cvs/gstreamer co gst-plugins-ugly }}} * Generate the configure script {{{ cd ~/src/gstreamer-dev/ (cd gstreamer && NOCONFIGURE=1 ./autogen.sh) (cd gst-plugins-base && NOCONFIGURE=1 ./autogen.sh) (cd gst-plugins-good && NOCONFIGURE=1 ./autogen.sh) (cd gst-plugins-bad && NOCONFIGURE=1 ./autogen.sh) (cd gst-plugins-ugly && NOCONFIGURE=1 ./autogen.sh)}}} === 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: * configure {{{ cd ~/src/gstreamer-dev/gstreamer PKG_CONFIG_PATH=/x/lib/pkgconfig ./configure --prefix=/x --host=i586-mingw32msvc }}} * build {{{ make }}} * install {{{ ver=`date +%Y%m%d` name=gstreamer rm -rf /tmp/${name}-${ver}-dist make DESTDIR=/tmp/${name}-${ver}-dist install (cd /x/stow && stow -D ${name}-*) rm -rf /x/stow/${name}-${ver} mv /tmp/${name}-${ver}-dist/x /x/stow/${name}-${ver} cd /x/stow/ stow ${name}-${ver} }}} === gst-plugins-base === {i} compile and install 3rd party libogg, libvorbis if you want these plugins to be installed. (!) Under 'gstreamer-mingw' chroot: * configure {{{ cd ~/src/gstreamer-dev/gst-plugins-base PKG_CONFIG_PATH=/x/lib/pkgconfig ./configure --prefix=/x --host=i586-mingw32msvc }}} * build {{{ make }}} * install {{{ ver=`date +%Y%m%d` make install DESTDIR=/tmp/gst-plugins-base-${ver}-dist mv /tmp/gst-plugins-base-${ver}-dist/x /x/stow/gst-plugins-base-${ver} cd /x/stow/ stow gst-plugins-base-${ver} }}} === gst-plugins-good === {i} you will need to install the directx headers to compile the directvideosink and directaudiosink. (!) Under 'gstreamer-mingw' chroot: * configure {{{ cd ~/src/gstreamer-dev/gst-plugins-good PKG_CONFIG_PATH=/x/lib/pkgconfig ./configure --prefix=/x --host=i586-mingw32msvc }}} * build {{{ make ERROR_CFLAGS='-Wall -Wdeclaration-after-statement -fno-strict-aliasing' }}} * install {{{ ver=`date +%Y%m%d` make ERROR_CFLAGS='-Wall -Wdeclaration-after-statement -fno-strict-aliasing' install DESTDIR=/tmp/gst-plugins-good-${ver}-dist mv /tmp/gst-plugins-good-${ver}-dist/x /x/stow/gst-plugins-good-${ver} cd /x/stow/ stow gst-plugins-good-${ver} }}} === gst-plugins-bad === (!) Under 'gstreamer-mingw' chroot: * configure {{{ cd ~/src/gstreamer-dev/gst-plugins-bad PKG_CONFIG_PATH=/x/lib/pkgconfig ./configure --prefix=/x --host=i586-mingw32msvc }}} * build {{{ make ERROR_CFLAGS='-Wall -Wdeclaration-after-statement -fno-strict-aliasing'}}} * instal {{{ ver=`date +%Y%m%d` make ERROR_CFLAGS='-Wall -Wdeclaration-after-statement -fno-strict-aliasing' install DESTDIR=/tmp/gst-plugins-bad-${ver}-dist mv /tmp/gst-plugins-bad-${ver}-dist/x /x/stow/gst-plugins-bad-${ver} cd /x/stow/ stow gst-plugins-bad-${ver} }}} === 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: * configure {{{ cd ~/src/gstreamer-dev/gst-plugins-ugly PKG_CONFIG_PATH=/x/lib/pkgconfig ./configure --prefix=/x --host=i586-mingw32msvc }}} * build {{{ make ERROR_CFLAGS='-Wall -Wdeclaration-after-statement -fno-strict-aliasing'}}} * install {{{ ver=`date +%Y%m%d` make ERROR_CFLAGS='-Wall -Wdeclaration-after-statement -fno-strict-aliasing' install DESTDIR=/tmp/gst-plugins-ugly-${ver}-dist mv /tmp/gst-plugins-ugly-${ver}-dist/x /x/stow/gst-plugins-ugly-${ver} cd /x/stow/ stow gst-plugins-ugly-${ver} }}} == 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. === 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 }}} 1. 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' }}} 1. 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 }}} 1. 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 }}} 1. 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} }}} === 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. === a52 === I had to re-ran manually the last ''libtool --tag=CC --mode=link'' command with ''-a52'' appended. == Testing == === Using wine === (!) Do this on your real linux machine. Install wine and try to run some simple pipelines: * Install the wine package {{{ sudo apt-get install wine }}} * Run a pipeline {{{ cd /x/bin wine ./gst-launch-0.10.exe fakesrc ! fakesink wine ./gst-launch-0.10.exe audiotestsrc ! directsoundsink wine ./gst-launch-0.10.exe videotestsrc ! directdrawsink }}} === 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: * log onto your windows machine: Map \\10.0.0.1\tanaka to drive X: * Run a command shell: {{{ C:\> X: X:\bin>gst-launch-0.10.exe --gst-plugin-path=x:/lib/gstreamer-0.10 fakesrc ! fakesink X:\bin>gst-launch-0.10.exe --gst-plugin-path=x:/lib/gstreamer-0.10 videotestsrc ! directdrawsink }}} Or if you have MSYS: {{{ $ cd /x/bin $ gst-launch-0.10.exe --gst-plugin-path=x:/lib/gstreamer-0.10 fakesrc ! fakesink }}} 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 }}}