Building Windows Binary On Linux (Cross compilation with MinGW)

Step by step compilation of GRASS and QGIS for Windows on Linux.

Building compiler and libraries

Warning: works only with GCC 3.x, problems were reported for GCC 4.x

Download scripts

Download and following scripts and put them in your PATH:

Warning: gcc must be configured with --enable-sjlj-exceptions

The scripts are slightly modified scripts from http://www.libsdl.org/extras/win32/cross/README.txt

Create directory

Create a new directory for example:

cd /home/user/
 mkdir win

Set WIN

Set environment variable WIN to the directory created in previous step, for example:

export WIN=/home/user/win
export TARGET=i586-mingw32msvc

I recommend to put this into your shell rc file (e.g. .bashrc)

Build Compiler

Run the script build-cross.sh, it should download and compile MinGW compiler, binutils and Win32 API.

XDR library

Download XDR library xdr-4.0-mingw2.tar.gz to $WIN/source and run

 cd $WIN/source

 tar xfz xdr-4.0-mingw2.tar.gz

 cd xdr-4.0-mingw2

 winconfigure --prefix=$WIN/i586-mingw32msvc

 winmake install

TODO: Use DLL. Currently if DLL is used db drivers do not work because of '\n' conversion (text mode expected). Find out how to force xdrlib to expect binary mode when compiled as DLL.

     # $WIN/i586-mingw32msvc/bin/g++ --shared -o xdr.dll \

     #              -Wl,--out-implib=libxdr.dll.a \

     #              -Wl,--export-all-symbols \

     #              -Wl,--enable-auto-import \

     #              -Wl,--whole-archive libxdr.a \

     #              -Wl,--no-whole-archive -lwsock32 -liberty -lmingw32



     # $WIN/i586-mingw32msvc/bin/strip xdr.dll

     # cp xdr.dll $WIN/i586-mingw32msvc/bin/

     # cp libxdr.dll.a $WIN/i586-mingw32msvc/lib

     # rm -f $WIN/i586-mingw32msvc/lib/libxdr.a

Note: XDR is extracted from SunRPC 4.0 library and modified for compilation on MinGW

ZLIB

Download zlib http://www.zlib.net/zlib-1.2.3.tar.gz to $WIN/source and run

 cd $WIN/source

 tar xfz zlib-1.2.3.tar.gz

 cd zlib-1.2.3

Note: zlib does not use autoconf, so it is impossible to run

 PREFIX=$WIN

 TARGET=i586-mingw32msvc

 export PATH="$PREFIX/bin:$PREFIX/$TARGET/bin:$PATH"

 ./configure --prefix=$WIN/$TARGET

  make install


  $WIN/i586-mingw32msvc/bin/g++ --shared -o z.dll \
                -Wl,--out-implib=libz.dll.a \
                -Wl,--export-all-symbols \
                -Wl,--enable-auto-import \
                -Wl,--whole-archive libz.a \
                -Wl,--no-whole-archive

     $WIN/i586-mingw32msvc/bin/strip z.dll

     cp z.dll $WIN/i586-mingw32msvc/bin/

     cp libz.dll.a $WIN/i586-mingw32msvc/lib

     rm -f $WIN/i586-mingw32msvc/lib/libz.a

PROJ.4

Download proj.4 ftp://ftp.remotesensing.org/proj/proj-4.4.9.tar.gz to $WIN/source and run

 cd $WIN/source

 tar xfz proj-4.4.9.tar.gz

 cd proj-4.4.9

  winconfigure --prefix=$WIN/i586-mingw32msvc

  winmake install

    $WIN/i586-mingw32msvc/bin/g++ --shared -o proj.dll \
                -Wl,--out-implib=libproj.dll.a \
                -Wl,--export-all-symbols \
                -Wl,--enable-auto-import \
                -Wl,--whole-archive src/.libs/libproj.a \
                -Wl,--no-whole-archive -lmingw32

    $WIN/i586-mingw32msvc/bin/strip proj.dll

    cp proj.dll $WIN/i586-mingw32msvc/bin/

    cp libproj.dll.a $WIN/i586-mingw32msvc/lib

    rm -f $WIN/i586-mingw32msvc/lib/libproj.a

    rm -f $WIN/i586-mingw32msvc/lib/libproj.la

GEOS

Download geos http://geos.refractions.net/geos-2.1.4.tar.bz2 to $WIN/source and run

    cd $WIN/source

    bunzip2 geos-2.1.4.tar.bz2

    tar xf geos-2.1.4.tar

    cd geos-2.1.4

    winconfigure --prefix=$WIN/i586-mingw32msvc

    winmake install

    $WIN/i586-mingw32msvc/bin/g++ --shared -o geos.dll \
                    -Wl,--out-implib=libgeos.dll.a \
                    -Wl,--export-all-symbols \
                    -Wl,--enable-auto-import \
                    -Wl,--whole-archive ./source/geom/.libs/libgeos.a \
                    -Wl,--no-whole-archive -lmingw32

    $WIN/i586-mingw32msvc/bin/strip geos.dll

    cp geos.dll $WIN/i586-mingw32msvc/bin/

    cp libgeos.dll.a $WIN/i586-mingw32msvc/lib

    rm -f $WIN/i586-mingw32msvc/lib/libgeos.a

    rm -f $WIN/i586-mingw32msvc/lib/libgeos.la

Create symbolic link:

    cd $WIN/i586-mingw32msvc/bin/

    ln -s i586-mingw32msvc-geos-config geos-config

GSL-library

Download the GSL-library into $WIN/source and extract it

    cd $WIN/source
    wget ftp://ftp.gnu.org/gnu/gsl/gsl-1.8.tar.gz
    tar xvfz gsl-1.8.tar.gz
    cd gsl-1.8

Configure GSL using winconfigure

   winconfigure --prefix=$WIN/i586-mingw32msvc
   winmake
   winmake install

expat-library

Download the expat-library into $WIN/source and extract it

    wget http://switch.dl.sourceforge.net/sourceforge/expat/expat-2.0.0.tar.gz
    tar xvfz expat-2.0.0.tar.gz
    cd expat-2.0.0

Configure and install expat

   ~/bin/winconfigure \
   --prefix=$WIN/i586-mingw32msvc

   ~/bin/winmake
   ~/bin/winmake install

Postgres

Download postgresql-8.1.3-1-binaries-no-installer.zip (http://www.postgresql.org/ftp/binary/v8.1.3/win32/) to $WIN/source

    cd $WIN/source

    unzip postgresql-8.1.3-1-binaries-no-installer.zip

    cd $WIN/source/pgsql

    cp $WIN/source/pgsql/bin/*.dll $WIN/i586-mingw32msvc/bin

    cp $WIN/source/pgsql/lib/libpq.a $WIN/i586-mingw32msvc/lib

    cp $WIN/source/pgsql/include/libpq-fe.h $WIN/i586-mingw32msvc/include

    cp $WIN/source/pgsql/include/postgres_ext.h $WIN/i586-mingw32msvc/include

GDAL

Download GDAL http://www.gdal.org/dl/gdal-1.3.2.tar.gz to $WIN/source

unpack GDAL:

     cd $WIN/source

     tar xfz gdal-1.3.2.tar.gz

     cd gdal-1.3.2

Configure without almost everything, for me it worked with:

     winconfigure \
        --prefix=$WIN/i586-mingw32msvc \
        --without-unix_stdio_64 \
        --without-python \
        --with-libtiff=internal \
        --with-geotiff=internal \
        --without-ogdi \
        --without-xerces \
        --without-hdf4 \
        --without-grass \
        --without-netcdf \
        --without-jpeg \
        --without-pg \
        --without-libtool

   winmake install

Create DLL and import library:

$WIN/i586-mingw32msvc/bin/g++ --shared -o gdal.dll \
                -Wl,--out-implib=libgdal.dll.a \
                -Wl,--export-all-symbols \
                -Wl,--enable-auto-import \
                -Wl,--whole-archive libgdal.a \
                -Wl,--no-whole-archive -lgeos -lz -lmingw32

$WIN/i586-mingw32msvc/bin/strip gdal.dll
cp gdal.dll $WIN/i586-mingw32msvc/bin/
cp libgdal.dll.a $WIN/i586-mingw32msvc/lib
rm $WIN/i586-mingw32msvc/lib/libgdal.a

Modify CONFIG_LIBS in gdal-config:

cd $WIN/i586-mingw32msvc/bin/
mv gdal-config gdal-config.orig
cat gdal-config.orig  \
        | sed 's/CONFIG_LIBS=.*/CONFIG_LIBS="-lgdal -lgeos -lz"/' \
        > gdal-config
chmod u+x gdal-config

After GRASS is built you will find further instructions on how to compile GRASS support into your GDAL.

SQLite

Download SQLite http://www.sqlite.org/sqlite-3.2.8.tar.gz to $WIN/source and run

      cd $WIN/source
      tar xfz sqlite-3.2.8.tar.gz
      cd sqlite-3.2.8

Note: SQLite is using for example its own parser (lemon) which must be compiled first for Linux

modify Makefile.linux-gcc: TOP = ../sqlite-3.2.8

    make -f Makefile.linux-gcc lemon keywordhash.h
    cp Makefile.linux-gcc Makefile.mingw-gcc

modify Makefile.mingw-gcc (BCC,TCC,AR,RANLIB):

      BCC = i586-mingw32msvc-gcc -g -O2
      TCC = i586-mingw32msvc-gcc -O6
      AR = i586-mingw32msvc-ar cr
      RANLIB = i586-mingw32msvc-ranlib

delete tclsqlite.o from LIBOBJ in main.mk

 winmake -f Makefile.mingw-gcc libsqlite3.a
 $WIN/i586-mingw32msvc/bin/g++ --shared -o sqlite3.dll \
                    -Wl,--out-implib=libsqlite3.dll.a \
                    -Wl,--export-all-symbols \
                    -Wl,--enable-auto-import \
                    -Wl,--whole-archive libsqlite3.a \
                    -Wl,--no-whole-archive -lmingw32

    $WIN/i586-mingw32msvc/bin/strip sqlite3.dll
    cp sqlite3.dll $WIN/i586-mingw32msvc/bin/
    cp libsqlite3.dll.a $WIN/i586-mingw32msvc/lib
    cp sqlite3.h $WIN/i586-mingw32msvc/include

MSYS

MSYS is used as shell for GRASS.

Download MSYS-1.0*.exe (e.g. MSYS-1.0.11-2004.04.30-1.exe) and install it on Windows

   wget http://switch.dl.sourceforge.net/sourceforge/mingw/MSYS-1.0.11-2004.04.30-1.exe

Warning: GRASS shell, msys.bat and rxvt.exe in path with spaces somehow cannot be started by QProcess. GRASS modules with space in path can be started without problem.

GRASS compilation

Download GRASS CVS HEAD to $WIN/source/grass6:

export CVSROOT=:pserver:grass-guest@intevation.de:/home/grass/grassrepository
cvs login
#password: "grass" (without quotes)
cvs -z3 checkout grass6

cd $WIN/source/grass6
configure using winconfigure, for me it works with:
winconfigure \
        --prefix=$WIN/i586-mingw32msvc \
        --target=i586-mingw32msvc \
        --without-jpeg \
        --without-tiff \
        --without-png \
        --without-tcltk \
        --without-postgres \
        --without-mysql \
        --without-sqlite \
        --without-opengl \
        --without-odbc \
        --without-fftw \
        --without-blas \
        --without-lapack \
        --without-motif \
        --without-freetype \
        --without-glw \
        --without-nls \
        --without-readline \
        --without-opendwg \
        --without-curses \
        --without-x

winmake
winmake install

Copy grass6/dist.$ARCH/docs/html from Linux version to Windows version

Get somewhere (e.g. http://proj.maptools.org/) NAD27 grid shift files (conus,hawaii,ntv1_can.dat etc.) and copy them to grass/etc/nad

GDAL GRASS support

After compilation of GRASS return to the GDAL directory and compile in GRASS support:

   cd $WIN/source/gdal-1.3.1
   ~/bin/winconfigure \
   --prefix=$WIN/i586-mingw32msvc \
   --with-grass=$WIN/i586-mingw32msvc/grass-6.1.cvs \
   --without-unix_stdio_64 \
   --without-python \
   --with-libtiff=internal \
   --with-geotiff=internal \
   --without-ogdi \
   --without-xerces \
   --without-hdf4 \
   --without-netcdf \
   --without-jpeg \
   --without-pg \
   --without-libtool

Remove '-lgrass_vask' from GDALmake.opt:

mv GDALmake.opt GDALmake.opt.orig
cat GDALmake.opt.orig | sed 's/-lgrass_vask//' > GDALmake.opt

Compile and install. For dll linking add also grass libs, e.g.:

winmake install

$WIN/i586-mingw32msvc/bin/g++ --shared -o gdal.dll \
                -Wl,--out-implib=libgdal.dll.a \
                -Wl,--export-all-symbols \
                -Wl,--enable-auto-import \
                -Wl,--whole-archive libgdal.a \
                -Wl,--no-whole-archive -lgeos -lz -lmingw32 \
             -L $WIN/i586-mingw32msvc/grass-6.1.cvs/lib \
             -lgrass_vect -lgrass_dig2 -lgrass_dgl -lgrass_rtree \
             -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase \
             -lgrass_I -lgrass_gproj  -lgrass_gmath -lgrass_gis \
             -lgrass_datetime -lz

$WIN/i586-mingw32msvc/bin/strip gdal.dll
cp gdal.dll $WIN/i586-mingw32msvc/bin/
cp libgdal.dll.a $WIN/i586-mingw32msvc/lib

Go to apps/ and add to gdal_translate.cpp and gdalinfo.c :

        #ifdef WIN32
        #include <stdlib.h> /*  _fmode */
        #include <fcntl.h> /*  _O_BINARY */
        #undef _fmode
        int _fmode = _O_BINARY;
        #endif

and recompile the applications:

winmake clean; winmake

Modify again CONFIG_LIBS in gdal-config:

cd $WIN/i586-mingw32msvc/bin/
mv gdal-config gdal-config.orig
cat gdal-config.orig  \
        | sed 's/CONFIG_LIBS=.*/CONFIG_LIBS="-lgdal -lgeos -lz"/' \
        > gdal-config
chmod u+x gdal-config

After that winconfigure in QGIS-dir works OK.

Running GRASS on Windows

Wine

It is possible to run GRASS for Windows on Linux using Wine http://www.winehq.com/ You have to add the path to your GRASS lib and bin directory into PATH variable defined in your .wine/system.reg

Windows

Start GRASS shell is not yet available. To start/run GRASS, so it is necessary to create GISRC file and set variables.

  1. create GISRC file, for example if you have GRASS mapset in

         C:\gdata\spearfish\user1

         GISDBASE: C:\gdata\
         LOCATION_NAME: spearfish
         MAPSET: gisrc
  1. Create batch file to start GRASS in this mapset
    • (if GRASS is installed in C:\grass) C:\gdata\spearfish\user1\grass.bat:

         set PATH=C:\grass\bin;C:\grass\lib;%PATH%
         set GISRC=C:\gdata\spearfish\user1\gisrc
         set GISBASE=C:\grass
         command.com

Now you can click on grass.bat and it opens shell where you can run GRASS commands. To enable command line history scrolling, run 'doskey' within the command.com terminal.

Quantum GIS compilation

Qt for Windows

Download qt-win-opensource-4.1.0-mingw.exe and run it on Windows or in Wine and extract Qt to $WIN/qt-4.1.0 (or move it there after extraction). In "MinGW Installation" tab leave the default option "Find MinGW" in "c:\MinGW". It will tell you that there is a problem with MinGW and if you want to continue, click on "Yes". The installer will extract Qt package.

Qt for Linux

Download qt-x11-opensource-src-4.1.0.tar.gz and compile it according to included instructions. You will need some Linux Qt binaries for cross-compilation (qmake, uic, moc, etc.).

Compilation of Quantum GIS

Download QGIS SVN HEAD source to $WIN/source/qgis_head

  cd WIN/source/qgis_head
  export PREFIX=$WIN
  export TARGET=i586-mingw32msvc
  export PATH="$PREFIX/bin:$PREFIX/$TARGET/bin:$PATH"

Set PATH and LD_LIBRARY_PATH to qt4 binaries for Linux, e.g.:

  export PATH=/home/usr1/qt-4.1.0/bin:$PATH
  export LD_LIBRARY_PATH=/home/usr1/qt-4.1.0/lib:$LD_LIBRARY_PATH
./autogen.sh \
        --prefix=$WIN/i586-mingw32msvc \
        --target=$TARGET \
        --host=$TARGET \
        --build=i386-linux \
        --with-qtdir=$WIN/qt-4.1.0 \
        --with-projdir=$WIN/i586-mingw32msvc \
        --with-gdal=$WIN/i586-mingw32msvc/bin/gdal-config \
        --with-geos=$WIN/i586-mingw32msvc/bin/geos-config \
        --with-sqlite3=$WIN/i586-mingw32msvc \
        --with-grass=$WIN/i586-mingw32msvc/grass-6.1.cvs \
        --without-postgresql

(Don't forget --without-postgresql, otherwise it will add Linux include paths!)

Note: I could build --with-postgresql and the correct libs were linked, when following the steps from Postgresql-Installation above. (SH)

  winmake -f Makefile.win
  winmake -f Makefile.win install
  winmake -f Makefile.win cpgrass  # Copy grass to qgis directory
  winmake -f Makefile.win cplibs   # Copy DLL libs to qgis directory

Form the directory where MSYS was installed on Windows copy

      m.ico msys.bat msys.ico bin/ etc/

to msys directory in the directory where qgis was installed ($prefix/msys) (MSYS is only necessary for GRASS Shell)

Strip and copy gdal_translate and gdalinfo to QGIS $prefix/qgis

Warning: Sometimes linking fails and runs OK if you run winmake second time?!

The resources/images etc. are installed to

  $WIN/i586-mingw32msvc/share/qgis

and plugins/providers are installed to

  $WIN/i586-mingw32msvc/lib/qgis

and qgis.exe is installed to

  $WIN/i586-mingw32msvc/bin

When running, qgis.exe will look for the resources and plugins in

  ./share/qgis and ./lib/qgis

If you want to run qgis.exe from $WIN/i586-mingw32msvc/bin you have to make symbolic links

  ln -s $WIN/i586-mingw32msvc/bin/share $WIN/i586-mingw32msvc/share/
  ln -s $WIN/i586-mingw32msvc/bin/lib $WIN/i586-mingw32msvc/lib/

Note: Makefile.win runs strip on output executable because otherwise the otput files are very big (e.g. qgis.exe has 62M before strip and 5,6M striped)

Note: 'g++ -shared -o xxx.dll xxx.a' creates DLL but it seems to be 'empty' (does not work) => linking objects instead of archives

Note: Sometimes happens that for example src/plugins/grass/.libs/grassplugin.dll is almost empty, in that case delete the file and recompile.

Get somewhere (e.g. http://proj.maptools.org/) NAD27 grid shift files (conus,hawaii,ntv1_can.dat etc.) and copy them to qgis/share/proj

Building Plugins

In order to build all plugins for Windows, you need to make sure a Makefile.win is included in the src/plugins/<plugin-name>-folder.

The SPIT and Grid Maker standalone binaries do not build and are not included in the makefiles.

If the plugins build but are not recognized by QGIS, you can do the following from the src/plugins dir:

find ./ -name "*.dll"|xargs rm
winmake -f Makefile.win install

For some reason the intial creation of the dll's seems to build incompatible binaries.

Making package

  winmake -f Makefile.win pkg

Running Quantum GIS on Windows

To see the QGIS output printed to stdout/stderr on Windows I recommend to write a small batch file, for example qgis-run.bat:

  c:\qgis\qgis.exe
  PAUSE

and run it instead of qgis.exe. It will open command.com and leave it open after qgis.exe exit.

Warning: In Wine, qgis.exe can freeze in qgisapp.cpp in QgsProviderRegistry::instance(plib) if there is no provider/plugin available in <prefix>/lib/qgis

Optional libraries for GRASS

Download PDCurses (substitutes ncurses) http://switch.dl.sourceforge.net/sourceforge/pdcurses/pdc27_ming_w32.zip

   mkdir $WIN/binaries

     cd $WIN/binaries
     mkdir pdcurses27
     cd pdcurses27/
     unzip ../pdc27_ming_w32.zip
     cp -p *.h $WIN/i586-mingw32msvc/include/
     cp -p *.a $WIN/i586-mingw32msvc/lib/

Note: For compilation of GRASS with curses edit in grass6/include/Make/Platform.make:

            COMPATLIB = <full_path_to_i586-mingw32msvc/lib>/pdcurses.a

This needs to be fixed in configure.in of GRASS.

BuildingWindowsBinaryOnLinux (last edited 2006-09-22 19:05:28 by RadimBlazek)