Introduction

In this document I will describe how to make a distribution independent QGIS application bundle. The idea is to make something that can be unzipped and exectuted in a user's home directory - it wont need root permissions since it doesnt go into /usr. Also the idea is not to have to make a separate RPM/DEB file for all of the 1000's of GNU/Linux distros out there. In order to achieve this we follow an approach similar to Mac OSX application bundles - we package all the dependencies into the bundle. You should try to follow this procedure on the oldest linux system you can get your hands on since glibc is backwards but not forward compatible. This means if you for example build on a glibc 2.4 based system, the bundle won't work on older glibc2.3 based systems. I'm going to run through this tutorial using dapper which is glibc2.3 based.

Preparing your system

I assume you have the gcc tools available on your system to compile c++ apps, and also that you have svn and cvs clients. I also assume you have read and write perms in /opt. Here are the commands to get the above if you dont have them:

 sudo apt-get install build-essential
 sudo apt-get install subversion cvs cmake

First lets create a working directory:

 mkdir /opt/qgis_linux_bundle

Now we are going to download and build a bunch of stuff in opt...

 cd /opt
 wget http://geos.refractions.net/geos-2.2.3.tar.bz2
 wget http://www.gdal.org/dl/gdal-1.4.0.tar.gz
 wget http://ufpr.dl.sourceforge.net/sourceforge/expat/expat-2.0.0.tar.gz
 wget http://grass.itc.it/grass62/source/grass-6.2.1.tar.gz
 wget ftp://ftp.trolltech.com/qt/source/qt-x11-opensource-src-4.2.2.tar.gz
 wget ftp://ftp.gnu.org/gnu/gsl/gsl-1.8.tar.gz
 wget ftp://ftp.remotesensing.org/proj/proj-4.5.0.tar.gz 
 wget http://www.sqlite.org/sqlite-3.3.10.tar.gz

Build Expat

 tar xfz expat-2.0.0.tar.gz
 cd expat-2.0.0
 ./configure --prefix=/opt/qgis_linux_bundle/usr
 make
 make install
 cd ..

Build GEOS

 tar xfj geos-2.2.3.tar.bz2
 cd geos-2.2.3
 ./configure --prefix=/opt/qgis_linux_bundle/usr
 make
 make install
 cd ..

Build GDAL

 sudo apt-get build-dep libgdal1c2a 
 tar xfz gdal-1.4.0.tar.gz
 cd gdal-1.4.0
 ./configure --prefix=/opt/qgis_linux_bundle/usr --with-geos=/opt/qgis_linux_bundle/usr/bin/geos- config
 make
 sudo make install
 cd ..

We need to use sudo for the last step since gdal tries to install python stuff into /usr which needs root privs.

Build Qt4.2.2

 tar xfz qt-x11-opensource-src-4.2.2.tar.gz
 cd qt-x11-opensource-src-4.2.2
 ./configure -prefix /opt/qis_linux_bundle/usr/ -nomake examples 
 make 
 make install
 cd ..

Build GSL

 tar xfz gsl-1.8.tar.gz
 cd gsl-1.8
 ./configure --prefix /opt/qis_linux_bundle/usr/
 make
 make install
 cd ..

Build proj4

 tar xfz proj-4.5.0.tar.gz
 cd proj-4.5.0
 ./configure --prefix /opt/qis_linux_bundle/usr/
 make
 make install
 cd ..

Build SQLITE

 tar xfz sqlite-3.3.10.tar.gz
 cd sqlite-3.3.10
 ./configure --prefix /opt/qis_linux_bundle/usr/
 make
 make install
 cd ..

Build GRASS

TODO_ Describe grass and gdal-grass support here

Install cmake

Note: Only needed for QGIS > 0.8.x

This doesnt go into the bundle dir but is needed to build QGIS, openModeller lib and openModeller Desktop

 sudo apt-get install cmake

Install QGIS

I assume you already have a checked out copy of QGIS sources

 cd /opt
 svn co https://svn.qgis.org/repos/qgis/trunk/qgis qgis
 cd qgis
 mkdir build
 cd build
 cmake -DGDAL_CONFIG=/opt/omg_linux_bundle/usr/bin/gdal-config \
      -DGSL_CONFIG=/opt/omg_linux_bundle/usr/bin/gsl-config \
      -DSQLITE3_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \
      -DSQLITE3_LIBRARY=/opt/omg_linux_bundle/usr/lib/libsqlite3.so \
      -DPROJ_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \
      -DPROJ_LIBRARY=/opt/omg_linux_bundle/usr/lib/libproj.so \
      -DQT_QMAKE_EXECUTABLE=/opt/omg_linux_bundle/usr/bin/qmake \
      -DCMAKE_INSTALL_PREFIX=/opt/omg_linux_bundle/usr/ \
      -DGEOS_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \
      -DGEOS_LIBRARY=/opt/omg_linux_bundle/usr/lib/libgeos.so \
      -DPEDANTIC=OFF \
      ..
 make install

Build openModeller

This is an optional step for those wanting openModeller inside the bundle (==me!).

 cd /opt
 svn co https://openmodeller.svn.sourceforge.net/svnroot/openmodeller/trunk/openmodeller   openmodeller
 cd openmodeller
 mkdir build
 cd build
 cmake -DGDAL_CONFIG=/opt/omg_linux_bundle/usr/bin/gdal-config \
      -DGSL_CONFIG=/opt/omg_linux_bundle/usr/bin/gsl-config \
      -DSQLITE3_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \
      -DSQLITE3_LIBRARY=/opt/omg_linux_bundle/usr/lib/libsqlite3.so \
      -DPROJ_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \
      -DPROJ_LIBRARY=/opt/omg_linux_bundle/usr/lib/libproj.so \
      -DQT_QMAKE_EXECUTABLE=/opt/omg_linux_bundle/usr/bin/qmake \
      -DCMAKE_INSTALL_PREFIX=/opt/omg_linux_bundle/usr/ \
      -DGEOS_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \
      -DGEOS_LIBRARY=/opt/omg_linux_bundle/usr/lib/libgeos.so \
      -DPEDANTIC=OFF \
      ..
 make install

Install openModeller Desktop

 cd /opt
 svn co https://openmodeller.svn.sourceforge.net/svnroot/openmodeller/trunk /openModellerDesktop  openModellerDesktop
 cd openModellerDesktop
 mkdir build
 cd build
 cmake -DGDAL_CONFIG=/opt/omg_linux_bundle/usr/bin/gdal-config \
      -DGSL_CONFIG=/opt/omg_linux_bundle/usr/bin/gsl-config \
      -DSQLITE3_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \
      -DSQLITE3_LIBRARY=/opt/omg_linux_bundle/usr/lib/libsqlite3.so \
      -DPROJ_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \
      -DPROJ_LIBRARY=/opt/omg_linux_bundle/usr/lib/libproj.so \
      -DQT_QMAKE_EXECUTABLE=/opt/omg_linux_bundle/usr/bin/qmake \
      -DCMAKE_INSTALL_PREFIX=/opt/omg_linux_bundle/usr/ \
      -DGEOS_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \
      -DGEOS_LIBRARY=/opt/omg_linux_bundle/usr/lib/libgeos.so \
      -DQGIS_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/qgis/ \
      -DQGIS_LIBRARY="/opt/omg_linux_bundle/usr/lib/libqgis_core.so;/opt/omg_linux_bundle/usr/lib /libqgis_gui.so" \
      -DOM_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/openModeller \
      -DOM_LIBRARY=/opt/omg_linux_bundle/usr/lib/libopenmodeller.so \
      -DWITH_QGIS=ON \
      -DQGIS_FOUND=ON \
      -DPEDANTIC=OFF \
      ..
 make install

Note See hack below if you run into errors finding libQtSvg.so.4

If you get this:

 /usr/bin/ld: warning: libQtSvg.so.4, needed by /opt/omg_linux_bundle/usr/lib/libqgis_core.so, not  found (try using -rpath or -rpath-link)
 /opt/omg_linux_bundle/usr/lib/libqgis_core.so: undefined reference to  `QSvgRenderer::QSvgRenderer(QObject*)'
 /opt/omg_linux_bundle/usr/lib/libqgis_core.so: undefined reference to  `QSvgRenderer::~QSvgRenderer()'
 /opt/omg_linux_bundle/usr/lib/libqgis_core.so: undefined reference to `QSvgRenderer::render(QPainter*)'
 /opt/omg_linux_bundle/usr/lib/libqgis_core.so: undefined reference to `QSvgRenderer::load(QString  const&)'
 collect2: ld returned 1 exit status
 make[2]: *** [src/gui/CMakeFiles/CMakeRelink.dir/openModellerDesktop] Error 1
 make[1]: *** [src/gui/CMakeFiles/openModellerDesktop.dir/preinstall] Error 2

You can make the following hack before running make install:

 export LD_LIBRARY_PATH=/opt/omg_linux_bundle/usr/lib/

TODO Fix build process so above is not needed

Testing and copying over missing deps

Ok now we are ready to do some testing. First put a script like the one below into the top of the bundle dir (I called it qgis.sh).

 #!/bin/bash
 export LD_LIBRARY_PATH=`pwd`/usr/lib:`pwd`/usr/local/lib:`pwd`/usr/lib/qgis
 export PATH=`pwd`/usr/bin:`pwd`/usr/local/bin:$PATH
 export GISBASE=`pwd`/usr/grass-6.2.1
 qgis &

Save it and make it executable:

 chmod a+x qgis.sh

Live CD

Ok now is a good time to pull out your live CD - Im going to use an ubuntu dapper live CD. Pop it in the drive and reboot. Mount the partition with your original /opt somewhere on your rebooted livecd:

 sudo mount /dev/hda7 /media/

So now my dapper partition is mounted in my livecd under /media

Now we try to run qgis. Missing library errors will appear and we will resolve them one at a time. I provide my resolution list here though it may not be what you need since it depends what libs are on your livecd. For this reason I recommend you use the most basic and oldest live cd you can get your hands on to test properly.

 cd /media/opt/qgis_linux_bundle
 ./qgis.sh

You will get a message like:

 qgis: error while loading shared libraries: libpq.so.4: cannot open shared object file: No such file or  directory

So copy in that lib:

 sudo cp -d /media/usr/lib/libpq.so* .

Then try to run qgis.sh again, deal with the error bu copying over the appropriate lib and so on until all missing libs are resolved and the application starts successfully. Here is my final copy list:

 sudo cp -d /media/usr/lib/libpq.so* .
 sudo cp -d /media/usr/lib/libodbc.so* .
 sudo cp -d /media/usr/lib/libodbcinst.so* .
 sudo cp -d /media/usr/lib/libmfhdf.so* .
 sudo cp -d /media/usr/lib/libdf.so* .
 sudo cp -d /media/usr/lib/libungif.so* .
 sudo cp -d /media/usr/lib/libnetcdf.so* .
 sudo cp -d /media/usr/lib/libcfitsio.so* .
 sudo cp -d /media/usr/lib/libltdl.so* .
 sudo cp -d /media/dapper/usr/lib/libjasper-1.701.so.1* .
 sudo cp -d /media/dapper/usr/lib/libtiff.so* .
 sudo cp -d /media/dapper/usr/lib/libssl.so* .
 sudo cp -d /media/dapper/usr/lib/libcrypt.so* .
 sudo cp -d /media/dapper/usr/lib/libpython2.4.so* .
 sudo cp -d /media/dapper/usr/lib/libkrb5.so.3* .
 sudo cp -d /media/dapper/usr/lib/libk5crypto.so.3* .
 sudo cp -d /media/dapper/usr/lib/libkrb5support.so.* .
 sudo cp -d /media/dapper/usr/lib/libstdc++.so.6* .
 sudo cp -d /media/dapper/usr/lib/libpng12.so* .
 sudo cp -d /media/dapper/usr/lib/libcrypto.so* .
 sudo cp -d /media/dapper/lib/libgcc_s.so.1 .

Take the bundle on a diet

Before we redistribute the bundle, it should go on a diet since there is a lot of stuff in there not needed by users at runtime. At the same time we dont want to trash our original since we need that stuff in there if we want to update it.

Before I started I looked at the size of the dir:

 du -sh qgis_linux_bundle/
 426M    qgis_linux_bundle/

So lets first make a copy and then go ahead and get out the pruning shears....

 cp qgis_linux_bundle qgis0.8-bundle
 cd qgis0.8-bundle/usr

Heres what I took out (remember we are in the usr dir of our bundle now):

 rm -rf include/ mkspecs translations q3porting.xml phrasebooks man info doc
 rm -rf lib/*debug*
 rm -rf lib/*.a
 rm -rf lib/*.la
 rm -rf lib/openmodeller/*.la
 rm -rf lib/openmodeller/*.a
 rm -rf lib/qgis/*.a
 rm -rf lib/qgis/*.la
 rm -rf bin/*.debug

Lets see how much space it consumes now....

 du -sh qgis0.8-bundle/
 150M    qgis0.8-bundle/

Right so that looks much better...lets make a nice installer for it now....

Creating a Installl Wizard using BitRock

http://bitrock.com produce a crossplatform qt4 based installer.