Welcome, Guest! Log In | Create Account

Compiling on Windows

From qtpfsgui

Jump to: navigation, search

Contents

Building Qtpfsgui from source on Windows

I recently undertook compiling qtpfsgui on windows from the latest source code package and thought I would pass on my experiences for anyone else who is interested in doing this. This is just a rough guide not intended to produce the best final setup. It relies on several libraries and DLLs beyond the win32 distribution available and therefore is not recommended for those who just want to use the software. It's for those of us who like to tinker and may want to contribute but who work in windows.

Prerequisites

If you don't have some experience using MinGW and Qt 4 then this probably isn't a good project to start with. I've been working with Qt (and vicariously MinGW) for a while now and have a good stable installation of both. I'm not here to tell you how to get this. I assume you already have this. Here's the basic pieces of your development environment that you should already have setup:

  • Qt 4 open source edition (I used 4.3.3) and the accompanied MinGW installation (or setup you're own MinGW using one of many guides on the web)
  • MSYS so you can use configure scripts (VERY important, basic installer is available on the web)

Other things that are very helpful but probably not required:

  • eclipse plus the Qt integration plugins (a must for any open source windows Qt developer)
  • Autoconf and Automake for MSYS (I don't think you need them but I've had occasion to want these in the past)

BTW, I'm running XP Pro SP2. I have no idea if this would work on Vista but if you are using Vista you probably already know what needs to change.

Dependencies

You need to acquire and/or build the dependencies and they all need to be built with MinGW (including OpenEXR). For this guide I will tell you how to build them all but you may be able to find some pre-compiled versions out there (notably here, thanks to Giuseppe for these). I think it's good to be able to build them yourself so that you know exactly how they were configured when built and can stay on top of new versions of each dependency as they become available. Note that the version of OpenEXR in the above link is version 4 whereas the latest version is 6.

Notes:

  • For each dependency I will indicate which version I used in parentheses after the name.
  • I use '/mingw' as the install prefix for all dependencies. I think this is typical of most MSYS installations but be sure this is a valid path and one that points to your mingw installation (different from the MSYS installation). You may have to check your MSYS mounting configuration to figure out exactly where the 'mingw' directory gets mapped to under MSYS.

1. exiv2 (0.17.1)

Exiv2 has a slew of it's own dependencies that we need to get working first so here we go.

1.1 zlib (1.2.3)

Available at http://www.zlib.net/. Download and unzip the source archive to within your MSYS directories. Then, fire up MSYS and from within the source directory issue the following commands:

./configure --prefix=/mingw
make
make install

The lib is now in '/mingw/lib' and the header file is in '/mingw/include'

1.2 expat (2.0.1)

Available at http://expat.sourceforge.net/. Download and unzip the source archive to within your MSYS directories. Then, fire up MSYS and from within the source directory issue the following commands:

./configure --prefix=/mingw
make
make install

The dll is now in '/mingw/bin', the lib is in '/mingw/lib' and the header files are in '/mingw/include'

1.3 libiconv (1.12)

This is a GNU library (a blessing on any *nix platform but a curse on windows). The project is described at http://www.gnu.org/software/libiconv/ with instructions on how to grab the source (Note, you might what to check out the pre-compiled GNU Win32 version of this one). As always, download and unzip the source archive to within your MSYS directories.

First, we need to edit the .rc files in the 'windows' directories:
Comment out lines 6-8, 25 & 31 in 'windows\libiconv.rc' and 'windows\iconv.rc'

Now, fire up MSYS and from within the source directory issue the usual three commands:

./configure --prefix=/mingw
make
make install

The libs are now in '/mingw/lib' and the header files are in '/mingw/include' but the DLL didn't get installed for me. You can find it in the source directory under 'lib/.libs'.

1.4 gettext (0.17)

This is another GNU library (a real beast of a project). The project is described at http://www.gnu.org/software/gettext/. Again, you may want to check out GNU Win32. As usual, download and unzip the source archive to within your MSYS directories.

To avoid some errors that were generated for me, make the following changes:

  • gettext-tools\gnulib-lib\xstriconv.c:35 - changed to 'int retval = -1;'
  • gettext-tools\gnulib-lib\xstriconv.c:45 - changed to 'int retval = NULL;'

Now, fire up MSYS and from within the source directory issue the usual three commands:

./configure --prefix=/mingw
make
make install

Additionally, you should now go back to libiconv and rebuild it so it has internationalization support. So, go back to the libiconv directory and issue the usual three commands (with a clean for good measure):

./configure --prefix=/mingw
make clean
make
make install

1. exiv2 (0.17.1)

Now, back to exiv2. You should have all the dependencies ready to go (assuming you didn't hit any errors above). Grab exiv2 from http://www.exiv2.org/ and do the usual source download and unzip. Fire up MSYS and issue the unix holy trinity:

./configure --prefix=/mingw
make
make install

The first dependency (exiv2) used for parsing of EXIF data is now ready to go with the lib in '/mingw/lib', the DLL in '/mingw/bin' and the headers in '/mingw/include/exiv2'.

2. fftw (3.1.2)

The Fast Fourier Transform library ... very good stuff! Grab it from http://www.fftw.org/ and do the usual source download and unpack. Be sure when you configure fftw that you set it up for SINGLE precision float mode instead of double (using --enable-float and --enable-sse). If you get link errors when trying to build qtpfsgui complaining that fftwf functions are not found when they should be, this is a good thing to double check. The double precision version will not link against qtpfsgui. Now, start up MSYS and issue these commands:

./configure --with-our-malloc16 --with-windows-f77-mangling --enable-shared --disable-static --enable-threads --with-combined-threads --enable-portable-binary --enable-float --enable-sse --prefix=/mingw
make
make install

That big configure line comes right from the mingw installation notes that come with the source distribution. I don't know what half of those options do but I trust the fftw maintainers not to steer me wrong.
The DLL is now in '/mingw/bin' with the libs in '/mingw/lib' and the headers in '/mingw/include'.

3. libtiff (3.8.2)

This is another GNU library and I copped out on this one and just used the automatic installer from the GNU Win32 project at http://gnuwin32.sourceforge.net/packages/tiff.htm. Just grab the 'Complete package, except sources' and let the installation wizard do the rest. I just left all the defaults selected for the installer wizard.

The DLL is now in 'C:\Program Files\GnuWin32\bin' and the libs are in 'C:\Program Files\GnuWin32\lib' with the headers in 'C:\Program Files\GnuWin32\include'. I recommend moving these to their appropriate places in the '/mingw' directory but this is up to you. It just makes library and include paths easier later on.

4. OpenEXR (v 6)

Don't say George Lucas never gave us anything. Here's a package from ILM that is a complete API for their very nice and well thought out HDR image format. There are two parts to this (the base code and the image format code) so I will describe both seperately. Prepare to pull out your favorite code editor here as OpenEXR does not compile on MinGW out-of-the-box but with a little work it can be done.

4.1 IlmBase (1.0.1)

This package is available at http://www.openexr.com/downloads.html. As usual, grab the source archive and expand it within your MSYS directies. Now, we need to edit some of the IlmThread files ... all of them in fact. In the 'IlmThread' directory, make the following changes:

For the dummy threading implementation (the one we want to use) hard-code the #if statements at the top of the .cpp files so that they are true:

  • IlmThread.cpp - line 44 becomes: #if true
  • IlmThreadMutex.cpp - line 44 becomes: #if true
  • IlmThreadSemaphore.cpp - line 44 becomes: #if true

NOTE: the following was unnecessary using the latest sources
For the Posix threading implementation (which sadly, we cannot use) we hard-code the #if statements at the top of the .cpp files so that they are false:

  • Ilm(Thread|Mutex|Semaphore)Posix.cpp - line 44 becomes: #if false
  • IlmSemaphorePosixCompat.cpp - line 44 becomes: #if false

NOTE: the following was unnecessary using the latest sources
And for the Win32 threading (again we cannot use) we also hard-code #if false statements at the top. They aren't there initially in these files you have to add some code this time:

  • Ilm(Thread|Mutex|Semaphore)Win32.cpp - add a line around line 40: #if false
  • Ilm(Thread|Mutex|Semaphore)Win32.cpp - add line at end of file: #endif

Note: that last step for the Win32 files may be unnecessary but it fit the pattern so I did it anyways. You can try and leave it out and see what happens.

Now fire up MSYS and you are ready to do the unix build-chain commands as follows (note the extra options in the configure script):

./configure --disable-threading --disable-posix-sem --prefix=/mingw
make
make install

That's it! Now, Imath, Iex, Half and IThreads are all in the '/mingw/bin' and '/mingw/lib' directories and there are a bunch of headers in '/mingw/include/OpenEXR'.

4.2 IlmImf - part of the OpenEXR package (1.6.1)

This package is also available at http://www.openexr.com/downloads.html. As usual, grab the source archive and expand it within your MSYS directies. Start up MSYS and issue the configure command as follows:

./configure --disable-threading --disable-posix-sem --prefix=/mingw

Now, before you run make you need to build one program manually that the configure script always screws up on MinGW.
Change to the IlmImf directory and issue the following command:

g++ -g -O2 -I/mingw/include/OpenEXR -L/mingw/lib b44ExpLogTable.cpp -lHalf -o b44ExpLogTable

Note: if you get a linker error about '--enable-auto-import' then add the following to the command line after '-O2' to fix the error: -Wl,--enable-runtime-pseudo-reloc

That's it. If you want to confirm that it worked then run ./b44ExpLogTable and you will get a butt load of hex numbers flying by.

Now, change back to the source root directory and do the usual:

make
make install

Note: If you are getting errors from 'ld' related to '--enable-auto-import' then you need to add a linker flag by doing the following:

export LDFLAGS="-Wl,--enable-runtime-pseudo-reloc"
re-run configure: ./configure --disable-threading --disable-posix-sem --prefix=/mingw
Try 'make' again

Viola! IlmImf is now in the '/mingw/bin' and '/mingw/lib' directories and you will find there are additional header files in the '/mingw/include/OpenEXR' directory.

Compiling Qtpfsgui

That's it for the dependencies. All that's left is to build the actual program. Here, I do not use MSYS. Instead I use the usual windows shell (cmd). I do this so that I can create an eclipse project and have it build things for me at a later time. As always, the first step is to grab the source code package but this time place it anywhere you want.

First, we need to customize the project.pro file to fit our setup. All of the changes are made at the end of the file in the win32 scoping.

One line needs to change so that it gets parsed by the windows command shell properly. It's near the end of the file:

  • Old: DEFINES += I18NDIR=(QCoreApplication::applicationDirPath()+\\\"/i18n\\\")
  • New: DEFINES += I18NDIR=\'(QCoreApplication::applicationDirPath()+\"/i18n\")\'

The header paths need to point to our headers. You can adjust the existing INCLUDEPATH statements or just add the following near the end:

  • INCLUDEPATH += "C:\Program Files\GnuWin32\include" c:/msys/mingw/include/OpenEXR c:/msys/mingw/include/exiv2

The GnuWin32 one is only necessary if you used the GNU Win32 options at some point (such as I did for the tiff library) and didn't move the files to your '/mingw' directory.

For me, the fftw library had a different name so the following change was necessary:

  • Old: LIBS += -lfftw3f-3 -lm
  • New: LIBS += -lfftw3f -lm

exiv2 needs all its dependencies as well so add the following libraries and make sure they occur somewhere past the '-lexiv2' statement:

  • LIBS += -lintl -liconv -lexpat

I also recommend removing the 'console' configuration unless you want a command shell popping up every time you run the program (this is however handy for debugging).

  • remove the line: CONFIG += console

Now, you are ready to roll. Fire up the Qt command prompt (available under the start menu) and browse over to the source directory. Then issue the following commands:

qmake project.pro
make release

That should do it. The executable is in the 'release' directory. You can build the debug version with 'make debug' but make sure you've got your Qt debug libs handy (must be built separately). In this case the executable is in the 'debug' directory. The program won't run yet unless by some miracle you happen to have all the DLLs in your PATH already. You can move them all to the 'release' directory alongside the executable and this is handy when it comes time to build an installer as all those files will be needed by the end user. However, the easiest way to guide the exe to the DLLs is to just add the '/mingw/bin' directory to your PATH environment variable (also add the C:\Program Files\GnuWin32\bin directory if you use GNU Win32 packages).

Now, qtfpsgui should run. If you need help tracking down all the DLL dependencies grab dependency walker. It will tell you exactly which DLLs cannot be found.

Supporting Programs

We're not quite done yet. there are two supporting programs you need to obtain to complete the Qtpfsgui toolset.

dcraw

First is dcraw. This little program reads and processes camera RAW files like a champ. The code is awful but the program is tops. If you don't agree with me about the code then you should probably drop out of whatever CS program you are in and become a gruff renegade coder for hire just like Dave Coffin. If you've already finished your program then you should call up your software engineering professor and tell them they failed (or maybe dance on their grave depending on your prof.)

But I digress. You can likely find a precompiled version of dcraw for windows out there but I wouldn't be doing my job if I didn't tell you how to compile it from scratch.

First, grab the GNU Win32 libjpeg package available at http://gnuwin32.sourceforge.net/packages/jpeg.htm. Run the installer and then you MUST move the headers and libs to be in the '/mingw' directory (or somewhere else MSYS can access). Also, you should move the libtiff headers and libraries as well now. They will both be needed by the next dependency.

Little CMS

lcms is available at http://www.littlecms.com. Grab the source, extract it to an MSYS directory, then fire up MSYS and do the usual:

./configure --prefix=/mingw
make
make install

lcms is in '/mingw' now.

Compiling dcraw

Yeah, the code for dcraw is an abomination to software engineering. But compiling it is pretty easy. NOT as easy as dave makes it seem on his web page mind you, but pretty easy. Grab dcraw.c (yup, just one file, see what I mean!!) from http://www.cybercom.net/~dcoffin/dcraw/. Throw it in a directory of your choice then start the Qt command prompt (NOT MSYS) and issue this command:

gcc -DWIN32 -DDJGPP -o dcraw -O4 dcraw.c -lm -ljpeg -llcms -lws2_32

It will spit out dcraw.exe in the same directory. Copy dcraw.exe to the same directory as qtpfsgui.exe.

Hugin's allign tool

Can I just say first, I love Hugin! I've used it to create many an environment map in my work and they just turn out fabs. It is the bees knees!! Here's a tool that as far as I'm aware you cannot build yourself (at least not without digging through the rather complicated Hugin compilation toolchain that depends both on cmake and boost). So, just grab the executable from the latest binary distribution for windows. You'll find a link at http://hugin.sourceforge.net/ under the 'Status' heading. Use the pre-release installer if it hasn't been finalized yet. It should work fine.

This time, run the installer and install the program to the location of your choice. Then navigate there and grab the program 'align_image_stack.exe'. Copy it to the same directory as qtpfsgui.exe.

Conclusions

That's everything!! Note that I have not thoroughly tested the resulting build but I did use it to do some basic HDR creation using Fuji raw images and things seemed to work okay. I have only a basic working knowledge of MSYS and MinGW and I'm still learning as a Qt developer so if anything I've said here is silly please feel free to edit the page or to offer your thoughts under the discussion section. They are welcome!

UPDATE

This note applies only if you want to build the svn version of Qtpfsgui.
The svn version of Qtpfsgui contains a bunch of bugfixes and some new features.
Among those new features there are the new parallel TMO algorithms developed by the pfstmo project that can be found in the most recent releases of pfstmo.
The new parallel algorithms have been implemented using OpenMP.
In Windows you need to have gcc 4.2.1-sjlj-2 available at: http://sourceforge.net/project/showfiles.php?group_id=2435&package_id=241304&release_id=532062
(gcc 4.3.0 seems to have OpenMP broken).
I backed up my MinGW directory, downloaded the gcc-core-4.2.1-sjlj-2.tar.gz and gcc-g++-4.2.1-sjlj-2.tar.gz packages and expanded them, overwriting any files. I then substituted the exe files in the <mingw>/bin directory with their "-sjlj" counterparts from gcc 4.2.1. Those files are:

./bin/c++-sjlj.exe ./bin/cpp-sjlj.exe ./bin/g++-sjlj.exe ./bin/gcc-sjlj.exe ./bin/gccbug-sjlj ./bin/gcov-sjlj.exe ./bin/libstdc++_sjlj_6.dll ./bin/mingw32-c++-sjlj.exe ./bin/mingw32-g++-sjlj.exe ./bin/mingw32-gcc-4.2.1-sjlj.exe ./bin/mingw32-gcc-sjlj.exe

Now modify the project.pro files and add something along the lines of:
LIBS += -L../DEPs/lib/pthread -lpthreadGC2
(it seems like OpenMP was implemented in terms of pthread)
So you also need to download win32-pthreads (I used version 2.8.0) from:
ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-8-0-release.exe
or
ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-8-0-release.tar.gz
or one of the mirrors listed at:
http://sourceware.org/mirrors.html
Make sure that in the ../DEPs/lib/pthread directory mentioned above you have only the pthreadGC2.dll file (I only tested the GC2 variant) and not the pthreadGC2.a file.
Having the pthreadGC2.a file means asking to link statically, and that fails with errors like:

c:/mingw/bin/../lib/gcc/mingw32/4.2.1-sjlj/libgomp.a(team.o):team.c:(.text+0x30): undefined reference to `_imp__sem_init'
...
c:/mingw/bin/../lib/gcc/mingw32/4.2.1-sjlj/libgomp.a(sem.o):sem.c:(.text+0xd): undefined reference to `_imp__sem_wait'

Those errors could probably be fixed by passing win32-specific (PE-specific) options to ld (the linker), but I didn't investigate any further because I wanted to link to the dll anyway.
Linking dynamically means that you need to have the pthreadGC2.dll file at runtime.

Now building should succeed as usual, except with warnings like the following one:

{{..\..\Qt\4.4.0\include/QtGui/../../src/gui/painting/qcolor.h:243: warning: 'QDataStream& operator<<(QDataStream&, const QColor&)' redeclared without dllimport attribute: previous dllimport ignored}}

I didn't have the time to investigate but they seem mostly harmless :)

Exiv2

So it turns out that the first build of the exiv2 dll was slightly broken.
We found out about this because we were not able to catch exceptions in Qtpfsgui created by the exiv2 library.
We found out the following note in the release notes of gcc-4.2.1-sjlj

* To throw exception across dll/exe boundaries in C++, you will need to
 link against the shared libgcc and libstdc++ runtime libs. To link
 against shared libgcc, add -shared-libgcc to command line. To link
 against shared libstdc++ add -lstdc++_s to command line. Hopefully, in
 future releases, the mechanism to select static or shared runtime libs
 can be improved. Unless you want to use auto-import to import data
 objects in libstdc++.dll, also add -D_DLL to commands line or #define
 _DLL in top-level headers. Again, this may change in future releases.

So we:

env LDFLAGS="-lstdc++_s -shared-libgcc -L/usr/local/lib -no-undefined" ./configure --disable-xmp --disable-visibility

make goes on ok until libtool tries to build the dll. libtools fails because of duplicate symbols between libstdc++ and libstdc++_s. So I had to edit the libtool script by hand to remove -lstdc++ from the postdeps variable. At this point re-running make builds the dll and its import library (the dll.a file)
Now, using both as a build and runtime dependency the dll we just built, exception throwing across dll/exe boundaries work.
It is not necessary to modify the build system for Qtpfsgui (file project.pro) but libgcc_sjlj_1.gll remains a runtime dependency for Qtpfsgui since exiv2-5.dll requires it.