Building Distro Independent Linux Bundle
Version 1 (Redmine Admin, 11/23/2011 04:44 pm)
| 1 | 1 | ||
|---|---|---|---|
| 2 | 1 | h1. Introduction |
|
| 3 | 1 | ||
| 4 | 1 | 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. |
|
| 5 | 1 | ||
| 6 | 1 | ||
| 7 | 1 | h1. Preparing your system |
|
| 8 | 1 | ||
| 9 | 1 | 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: |
|
| 10 | 1 | ||
| 11 | 1 | <pre> |
|
| 12 | 1 | sudo apt-get install build-essential |
|
| 13 | 1 | sudo apt-get install subversion cvs cmake |
|
| 14 | 1 | </pre> |
|
| 15 | 1 | ||
| 16 | 1 | First lets create a working directory: |
|
| 17 | 1 | ||
| 18 | 1 | <pre> |
|
| 19 | 1 | mkdir /opt/qgis_linux_bundle |
|
| 20 | 1 | </pre> |
|
| 21 | 1 | ||
| 22 | 1 | Now we are going to download and build a bunch of stuff in opt... |
|
| 23 | 1 | ||
| 24 | 1 | <pre> |
|
| 25 | 1 | cd /opt |
|
| 26 | 1 | wget http://geos.refractions.net/geos-2.2.3.tar.bz2 |
|
| 27 | 1 | wget http://www.gdal.org/dl/gdal-1.4.0.tar.gz |
|
| 28 | 1 | wget http://ufpr.dl.sourceforge.net/sourceforge/expat/expat-2.0.0.tar.gz |
|
| 29 | 1 | wget http://grass.itc.it/grass62/source/grass-6.2.1.tar.gz |
|
| 30 | 1 | wget ftp://ftp.trolltech.com/qt/source/qt-x11-opensource-src-4.2.2.tar.gz |
|
| 31 | 1 | wget ftp://ftp.gnu.org/gnu/gsl/gsl-1.8.tar.gz |
|
| 32 | 1 | wget ftp://ftp.remotesensing.org/proj/proj-4.5.0.tar.gz |
|
| 33 | 1 | wget http://www.sqlite.org/sqlite-3.3.10.tar.gz |
|
| 34 | 1 | </pre> |
|
| 35 | 1 | ||
| 36 | 1 | ||
| 37 | 1 | h1. Build Expat |
|
| 38 | 1 | ||
| 39 | 1 | <pre> |
|
| 40 | 1 | tar xfz expat-2.0.0.tar.gz |
|
| 41 | 1 | cd expat-2.0.0 |
|
| 42 | 1 | ./configure --prefix=/opt/qgis_linux_bundle/usr |
|
| 43 | 1 | make |
|
| 44 | 1 | make install |
|
| 45 | 1 | cd .. |
|
| 46 | 1 | </pre> |
|
| 47 | 1 | ||
| 48 | 1 | ||
| 49 | 1 | h1. Build GEOS |
|
| 50 | 1 | ||
| 51 | 1 | <pre> |
|
| 52 | 1 | tar xfj geos-2.2.3.tar.bz2 |
|
| 53 | 1 | cd geos-2.2.3 |
|
| 54 | 1 | ./configure --prefix=/opt/qgis_linux_bundle/usr |
|
| 55 | 1 | make |
|
| 56 | 1 | make install |
|
| 57 | 1 | cd .. |
|
| 58 | 1 | </pre> |
|
| 59 | 1 | ||
| 60 | 1 | ||
| 61 | 1 | h1. Build GDAL |
|
| 62 | 1 | ||
| 63 | 1 | <pre> |
|
| 64 | 1 | sudo apt-get build-dep libgdal1c2a |
|
| 65 | 1 | tar xfz gdal-1.4.0.tar.gz |
|
| 66 | 1 | cd gdal-1.4.0 |
|
| 67 | 1 | ./configure --prefix=/opt/qgis_linux_bundle/usr --with-geos=/opt/qgis_linux_bundle/usr/bin/geos- config |
|
| 68 | 1 | make |
|
| 69 | 1 | sudo make install |
|
| 70 | 1 | cd .. |
|
| 71 | 1 | </pre> |
|
| 72 | 1 | ||
| 73 | 1 | We need to use sudo for the last step since gdal tries to install python stuff into /usr which needs root privs. |
|
| 74 | 1 | ||
| 75 | 1 | ||
| 76 | 1 | h1. Build Qt4.2.2 |
|
| 77 | 1 | ||
| 78 | 1 | <pre> |
|
| 79 | 1 | tar xfz qt-x11-opensource-src-4.2.2.tar.gz |
|
| 80 | 1 | cd qt-x11-opensource-src-4.2.2 |
|
| 81 | 1 | ./configure -prefix /opt/qis_linux_bundle/usr/ -nomake examples |
|
| 82 | 1 | make |
|
| 83 | 1 | make install |
|
| 84 | 1 | cd .. |
|
| 85 | 1 | </pre> |
|
| 86 | 1 | ||
| 87 | 1 | ||
| 88 | 1 | h1. Build GSL |
|
| 89 | 1 | ||
| 90 | 1 | <pre> |
|
| 91 | 1 | tar xfz gsl-1.8.tar.gz |
|
| 92 | 1 | cd gsl-1.8 |
|
| 93 | 1 | ./configure --prefix /opt/qis_linux_bundle/usr/ |
|
| 94 | 1 | make |
|
| 95 | 1 | make install |
|
| 96 | 1 | cd .. |
|
| 97 | 1 | </pre> |
|
| 98 | 1 | ||
| 99 | 1 | ||
| 100 | 1 | h1. Build proj4 |
|
| 101 | 1 | ||
| 102 | 1 | <pre> |
|
| 103 | 1 | tar xfz proj-4.5.0.tar.gz |
|
| 104 | 1 | cd proj-4.5.0 |
|
| 105 | 1 | ./configure --prefix /opt/qis_linux_bundle/usr/ |
|
| 106 | 1 | make |
|
| 107 | 1 | make install |
|
| 108 | 1 | cd .. |
|
| 109 | 1 | </pre> |
|
| 110 | 1 | ||
| 111 | 1 | ||
| 112 | 1 | h1. Build SQLITE |
|
| 113 | 1 | ||
| 114 | 1 | <pre> |
|
| 115 | 1 | tar xfz sqlite-3.3.10.tar.gz |
|
| 116 | 1 | cd sqlite-3.3.10 |
|
| 117 | 1 | ./configure --prefix /opt/qis_linux_bundle/usr/ |
|
| 118 | 1 | make |
|
| 119 | 1 | make install |
|
| 120 | 1 | cd .. |
|
| 121 | 1 | </pre> |
|
| 122 | 1 | ||
| 123 | 1 | ||
| 124 | 1 | h1. Build GRASS |
|
| 125 | 1 | ||
| 126 | 1 | *TODO_* Describe grass and gdal-grass support here |
|
| 127 | 1 | ||
| 128 | 1 | ||
| 129 | 1 | h1. Install cmake |
|
| 130 | 1 | ||
| 131 | 1 | *Note:* Only needed for QGIS > 0.8.x |
|
| 132 | 1 | ||
| 133 | 1 | This doesnt go into the bundle dir but is needed to build QGIS, openModeller lib and openModeller Desktop |
|
| 134 | 1 | ||
| 135 | 1 | <pre> |
|
| 136 | 1 | sudo apt-get install cmake |
|
| 137 | 1 | </pre> |
|
| 138 | 1 | ||
| 139 | 1 | ||
| 140 | 1 | h1. Install QGIS |
|
| 141 | 1 | ||
| 142 | 1 | I assume you already have a checked out copy of QGIS sources |
|
| 143 | 1 | ||
| 144 | 1 | <pre> |
|
| 145 | 1 | cd /opt |
|
| 146 | 1 | svn co https://svn.qgis.org/repos/qgis/trunk/qgis qgis |
|
| 147 | 1 | cd qgis |
|
| 148 | 1 | mkdir build |
|
| 149 | 1 | cd build |
|
| 150 | 1 | cmake -DGDAL_CONFIG=/opt/omg_linux_bundle/usr/bin/gdal-config \ |
|
| 151 | 1 | -DGSL_CONFIG=/opt/omg_linux_bundle/usr/bin/gsl-config \ |
|
| 152 | 1 | -DSQLITE3_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \ |
|
| 153 | 1 | -DSQLITE3_LIBRARY=/opt/omg_linux_bundle/usr/lib/libsqlite3.so \ |
|
| 154 | 1 | -DPROJ_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \ |
|
| 155 | 1 | -DPROJ_LIBRARY=/opt/omg_linux_bundle/usr/lib/libproj.so \ |
|
| 156 | 1 | -DQT_QMAKE_EXECUTABLE=/opt/omg_linux_bundle/usr/bin/qmake \ |
|
| 157 | 1 | -DCMAKE_INSTALL_PREFIX=/opt/omg_linux_bundle/usr/ \ |
|
| 158 | 1 | -DGEOS_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \ |
|
| 159 | 1 | -DGEOS_LIBRARY=/opt/omg_linux_bundle/usr/lib/libgeos.so \ |
|
| 160 | 1 | -DPEDANTIC=OFF \ |
|
| 161 | 1 | .. |
|
| 162 | 1 | make install |
|
| 163 | 1 | ||
| 164 | 1 | </pre> |
|
| 165 | 1 | ||
| 166 | 1 | h1. Build openModeller |
|
| 167 | 1 | ||
| 168 | 1 | This is an *optional* step for those wanting openModeller inside the bundle (==me!). |
|
| 169 | 1 | ||
| 170 | 1 | <pre> |
|
| 171 | 1 | cd /opt |
|
| 172 | 1 | svn co https://openmodeller.svn.sourceforge.net/svnroot/openmodeller/trunk/openmodeller openmodeller |
|
| 173 | 1 | cd openmodeller |
|
| 174 | 1 | mkdir build |
|
| 175 | 1 | cd build |
|
| 176 | 1 | cmake -DGDAL_CONFIG=/opt/omg_linux_bundle/usr/bin/gdal-config \ |
|
| 177 | 1 | -DGSL_CONFIG=/opt/omg_linux_bundle/usr/bin/gsl-config \ |
|
| 178 | 1 | -DSQLITE3_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \ |
|
| 179 | 1 | -DSQLITE3_LIBRARY=/opt/omg_linux_bundle/usr/lib/libsqlite3.so \ |
|
| 180 | 1 | -DPROJ_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \ |
|
| 181 | 1 | -DPROJ_LIBRARY=/opt/omg_linux_bundle/usr/lib/libproj.so \ |
|
| 182 | 1 | -DQT_QMAKE_EXECUTABLE=/opt/omg_linux_bundle/usr/bin/qmake \ |
|
| 183 | 1 | -DCMAKE_INSTALL_PREFIX=/opt/omg_linux_bundle/usr/ \ |
|
| 184 | 1 | -DGEOS_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \ |
|
| 185 | 1 | -DGEOS_LIBRARY=/opt/omg_linux_bundle/usr/lib/libgeos.so \ |
|
| 186 | 1 | -DPEDANTIC=OFF \ |
|
| 187 | 1 | .. |
|
| 188 | 1 | make install |
|
| 189 | 1 | </pre> |
|
| 190 | 1 | ||
| 191 | 1 | ||
| 192 | 1 | h1. Install openModeller Desktop |
|
| 193 | 1 | ||
| 194 | 1 | <pre> |
|
| 195 | 1 | cd /opt |
|
| 196 | 1 | svn co https://openmodeller.svn.sourceforge.net/svnroot/openmodeller/trunk /openModellerDesktop openModellerDesktop |
|
| 197 | 1 | cd openModellerDesktop |
|
| 198 | 1 | mkdir build |
|
| 199 | 1 | cd build |
|
| 200 | 1 | cmake -DGDAL_CONFIG=/opt/omg_linux_bundle/usr/bin/gdal-config \ |
|
| 201 | 1 | -DGSL_CONFIG=/opt/omg_linux_bundle/usr/bin/gsl-config \ |
|
| 202 | 1 | -DSQLITE3_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \ |
|
| 203 | 1 | -DSQLITE3_LIBRARY=/opt/omg_linux_bundle/usr/lib/libsqlite3.so \ |
|
| 204 | 1 | -DPROJ_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \ |
|
| 205 | 1 | -DPROJ_LIBRARY=/opt/omg_linux_bundle/usr/lib/libproj.so \ |
|
| 206 | 1 | -DQT_QMAKE_EXECUTABLE=/opt/omg_linux_bundle/usr/bin/qmake \ |
|
| 207 | 1 | -DCMAKE_INSTALL_PREFIX=/opt/omg_linux_bundle/usr/ \ |
|
| 208 | 1 | -DGEOS_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/ \ |
|
| 209 | 1 | -DGEOS_LIBRARY=/opt/omg_linux_bundle/usr/lib/libgeos.so \ |
|
| 210 | 1 | -DQGIS_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/qgis/ \ |
|
| 211 | 1 | -DQGIS_LIBRARY="/opt/omg_linux_bundle/usr/lib/libqgis_core.so;/opt/omg_linux_bundle/usr/lib /libqgis_gui.so" \ |
|
| 212 | 1 | -DOM_INCLUDE_DIR=/opt/omg_linux_bundle/usr/include/openModeller \ |
|
| 213 | 1 | -DOM_LIBRARY=/opt/omg_linux_bundle/usr/lib/libopenmodeller.so \ |
|
| 214 | 1 | -DWITH_QGIS=ON \ |
|
| 215 | 1 | -DQGIS_FOUND=ON \ |
|
| 216 | 1 | -DPEDANTIC=OFF \ |
|
| 217 | 1 | .. |
|
| 218 | 1 | make install |
|
| 219 | 1 | </pre> |
|
| 220 | 1 | ||
| 221 | 1 | *Note* See hack below if you run into errors finding libQtSvg.so.4 |
|
| 222 | 1 | ||
| 223 | 1 | If you get this: |
|
| 224 | 1 | ||
| 225 | 1 | <pre> |
|
| 226 | 1 | /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) |
|
| 227 | 1 | /opt/omg_linux_bundle/usr/lib/libqgis_core.so: undefined reference to `QSvgRenderer::QSvgRenderer(QObject*)' |
|
| 228 | 1 | /opt/omg_linux_bundle/usr/lib/libqgis_core.so: undefined reference to `QSvgRenderer::~QSvgRenderer()' |
|
| 229 | 1 | /opt/omg_linux_bundle/usr/lib/libqgis_core.so: undefined reference to `QSvgRenderer::render(QPainter*)' |
|
| 230 | 1 | /opt/omg_linux_bundle/usr/lib/libqgis_core.so: undefined reference to `QSvgRenderer::load(QString const&)' |
|
| 231 | 1 | collect2: ld returned 1 exit status |
|
| 232 | 1 | make[2]: *** [src/gui/CMakeFiles/CMakeRelink.dir/openModellerDesktop] Error 1 |
|
| 233 | 1 | make[1]: *** [src/gui/CMakeFiles/openModellerDesktop.dir/preinstall] Error 2 |
|
| 234 | 1 | </pre> |
|
| 235 | 1 | ||
| 236 | 1 | You can make the following hack before running make install: |
|
| 237 | 1 | ||
| 238 | 1 | <pre> |
|
| 239 | 1 | export LD_LIBRARY_PATH=/opt/omg_linux_bundle/usr/lib/ |
|
| 240 | 1 | </pre> |
|
| 241 | 1 | ||
| 242 | 1 | *TODO* Fix build process so above is not needed |
|
| 243 | 1 | ||
| 244 | 1 | ||
| 245 | 1 | h1. Testing and copying over missing deps |
|
| 246 | 1 | ||
| 247 | 1 | 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). |
|
| 248 | 1 | ||
| 249 | 1 | <pre> |
|
| 250 | 1 | #!/bin/bash |
|
| 251 | 1 | export LD_LIBRARY_PATH=`pwd`/usr/lib:`pwd`/usr/local/lib:`pwd`/usr/lib/qgis |
|
| 252 | 1 | export PATH=`pwd`/usr/bin:`pwd`/usr/local/bin:$PATH |
|
| 253 | 1 | export GISBASE=`pwd`/usr/grass-6.2.1 |
|
| 254 | 1 | qgis & |
|
| 255 | 1 | </pre> |
|
| 256 | 1 | ||
| 257 | 1 | Save it and make it executable: |
|
| 258 | 1 | ||
| 259 | 1 | <pre> |
|
| 260 | 1 | chmod a+x qgis.sh |
|
| 261 | 1 | </pre> |
|
| 262 | 1 | ||
| 263 | 1 | ||
| 264 | 1 | h2. Live CD |
|
| 265 | 1 | ||
| 266 | 1 | 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: |
|
| 267 | 1 | ||
| 268 | 1 | <pre> |
|
| 269 | 1 | sudo mount /dev/hda7 /media/ |
|
| 270 | 1 | </pre> |
|
| 271 | 1 | ||
| 272 | 1 | So now my dapper partition is mounted in my livecd under /media |
|
| 273 | 1 | ||
| 274 | 1 | 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. |
|
| 275 | 1 | ||
| 276 | 1 | <pre> |
|
| 277 | 1 | cd /media/opt/qgis_linux_bundle |
|
| 278 | 1 | ./qgis.sh |
|
| 279 | 1 | </pre> |
|
| 280 | 1 | ||
| 281 | 1 | You will get a message like: |
|
| 282 | 1 | ||
| 283 | 1 | <pre> |
|
| 284 | 1 | qgis: error while loading shared libraries: libpq.so.4: cannot open shared object file: No such file or directory |
|
| 285 | 1 | </pre> |
|
| 286 | 1 | ||
| 287 | 1 | So copy in that lib: |
|
| 288 | 1 | ||
| 289 | 1 | <pre> |
|
| 290 | 1 | sudo cp -d /media/usr/lib/libpq.so* . |
|
| 291 | 1 | </pre> |
|
| 292 | 1 | ||
| 293 | 1 | 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: |
|
| 294 | 1 | ||
| 295 | 1 | <pre> |
|
| 296 | 1 | sudo cp -d /media/usr/lib/libpq.so* . |
|
| 297 | 1 | sudo cp -d /media/usr/lib/libodbc.so* . |
|
| 298 | 1 | sudo cp -d /media/usr/lib/libodbcinst.so* . |
|
| 299 | 1 | sudo cp -d /media/usr/lib/libmfhdf.so* . |
|
| 300 | 1 | sudo cp -d /media/usr/lib/libdf.so* . |
|
| 301 | 1 | sudo cp -d /media/usr/lib/libungif.so* . |
|
| 302 | 1 | sudo cp -d /media/usr/lib/libnetcdf.so* . |
|
| 303 | 1 | sudo cp -d /media/usr/lib/libcfitsio.so* . |
|
| 304 | 1 | sudo cp -d /media/usr/lib/libltdl.so* . |
|
| 305 | 1 | sudo cp -d /media/dapper/usr/lib/libjasper-1.701.so.1* . |
|
| 306 | 1 | sudo cp -d /media/dapper/usr/lib/libtiff.so* . |
|
| 307 | 1 | sudo cp -d /media/dapper/usr/lib/libssl.so* . |
|
| 308 | 1 | sudo cp -d /media/dapper/usr/lib/libcrypt.so* . |
|
| 309 | 1 | sudo cp -d /media/dapper/usr/lib/libpython2.4.so* . |
|
| 310 | 1 | sudo cp -d /media/dapper/usr/lib/libkrb5.so.3* . |
|
| 311 | 1 | sudo cp -d /media/dapper/usr/lib/libk5crypto.so.3* . |
|
| 312 | 1 | sudo cp -d /media/dapper/usr/lib/libkrb5support.so.* . |
|
| 313 | 1 | sudo cp -d /media/dapper/usr/lib/libstdc++.so.6* . |
|
| 314 | 1 | sudo cp -d /media/dapper/usr/lib/libpng12.so* . |
|
| 315 | 1 | sudo cp -d /media/dapper/usr/lib/libcrypto.so* . |
|
| 316 | 1 | sudo cp -d /media/dapper/lib/libgcc_s.so.1 . |
|
| 317 | 1 | </pre> |
|
| 318 | 1 | ||
| 319 | 1 | ||
| 320 | 1 | h1. Take the bundle on a diet |
|
| 321 | 1 | ||
| 322 | 1 | 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. |
|
| 323 | 1 | ||
| 324 | 1 | Before I started I looked at the size of the dir: |
|
| 325 | 1 | ||
| 326 | 1 | <pre> |
|
| 327 | 1 | du -sh qgis_linux_bundle/ |
|
| 328 | 1 | 426M qgis_linux_bundle/ |
|
| 329 | 1 | </pre> |
|
| 330 | 1 | ||
| 331 | 1 | So lets first make a copy and then go ahead and get out the pruning shears.... |
|
| 332 | 1 | ||
| 333 | 1 | <pre> |
|
| 334 | 1 | cp qgis_linux_bundle qgis0.8-bundle |
|
| 335 | 1 | cd qgis0.8-bundle/usr |
|
| 336 | 1 | </pre> |
|
| 337 | 1 | ||
| 338 | 1 | Heres what I took out (remember we are in the usr dir of our bundle now): |
|
| 339 | 1 | ||
| 340 | 1 | <pre> |
|
| 341 | 1 | rm -rf include/ mkspecs translations q3porting.xml phrasebooks man info doc |
|
| 342 | 1 | rm -rf lib/*debug* |
|
| 343 | 1 | rm -rf lib/*.a |
|
| 344 | 1 | rm -rf lib/*.la |
|
| 345 | 1 | rm -rf lib/openmodeller/*.la |
|
| 346 | 1 | rm -rf lib/openmodeller/*.a |
|
| 347 | 1 | rm -rf lib/qgis/*.a |
|
| 348 | 1 | rm -rf lib/qgis/*.la |
|
| 349 | 1 | rm -rf bin/*.debug |
|
| 350 | 1 | </pre> |
|
| 351 | 1 | ||
| 352 | 1 | Lets see how much space it consumes now.... |
|
| 353 | 1 | ||
| 354 | 1 | <pre> |
|
| 355 | 1 | du -sh qgis0.8-bundle/ |
|
| 356 | 1 | 150M qgis0.8-bundle/ |
|
| 357 | 1 | </pre> |
|
| 358 | 1 | ||
| 359 | 1 | Right so that looks much better...lets make a nice installer for it now.... |
|
| 360 | 1 | ||
| 361 | 1 | ||
| 362 | 1 | h1. Creating a Installl Wizard using BitRock |
|
| 363 | 1 | ||
| 364 | 1 | http://bitrock.com produce a crossplatform qt4 based installer. |