I’d like to describe options I often use in my Qt projects.

OBJECTS_DIR = build
DESTDIR = dist

I don’t use shadow build and this keeps all object files in build/ subfolder making it easier to browse through the root folder. With second option my executables end up in the dist/ subfolder.

VERSION = 0.1
DEFINES += APP_VERSION=\\\"$$VERSION\\\"

This defines version of the project and makes it available as string APP_VERSION in sources. And yes, that amount of backslashes is required for it to work as string. By the way I use it in the following piece of code I put into my main() functions in order for everything to work well:

Q_INIT_RESOURCE(resources);
qsrand(qHash(QTime::currentTime().toString("hmsz")));

QApplication app(argc, argv);
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

app.setApplicationName(QObject::tr("Application Name"));
app.setApplicationVersion(QObject::tr(APP_VERSION));
app.setOrganizationName(QObject::tr("Xilexio"));

I use the last 3 variables through qApp macro later in my applications, usually to display appropriate window title.

win32 {
    LIBS += -Llib/win32
}

unix {
    LIBS += -Llib/unix
}

Example how to use conditionals on win32 and unix variables (defined automatically on Windows and Unix systems respectively) in order to link with appropriate libraries. This works if you provide library binaries together with code and put them to different directory for each system. The same conditionals can be used together with “CONFIG+=variableName” put into Project > Build Settings > Build steps > qmake step > Additional arguments. I use them to add test builds that way.

CONFIG(debug, debug|release) {
    CONFIG += console
}

Another conditional, this time switched only for debug build. We need to add “console” to config in order for information from qDebug and others to appear. That switch takes care of it. For release conditional simply replace “debug” with “release” in the first argument.

INCLUDEPATH += lib/include

This adds a space-separated list of folders for global #includes. They are passed to g++ compiler with -I and are also used for automatic code completion.

LIBS += -lz

Arguments for linking with libraries passed to the compiler. Put your -L and -l arguments here. Note: the code above searches for libz.a, z.a, libz.dll and z.dll in case of g++.

TARGET = great-program

Name of your executable.

build
debug
dist
release
Makefile*
*.pro.user
ui_*
moc_*
qrc_*
*.rc
object_script.*

Not really an option, but this is my generic .gitignore file I use in my Qt projects. Those are all generated or machine-dependent files and shouldn’t be checked into a git repository.

I chose to use VTK 6.0.0 library in my project in order to visualize solution of system of partial differential equations in my Qt 4 application. By the way, I’m solving PDEs using getfem++.

I had to compile VTK first though. It wasn’t quite as complex as compiling getfem++, but still required some tweaking for my non-CMake based project. You can find compiled VTK binaries in my vtk bitbucket repository.

I was building this library on Windows 7 with GNUStep’s mingw32 with g++ 4.6.1.

VTK library build is CMake based. The good news is that the library build itself works well. The bad news is that using it in your non-CMake aplication requires some care. To build VTK first install CMake if you haven’t already done so and make sure it’s in your PATH.
The build I made was with additional Qt and Views modules, so I also had to include Qt libraries in PATH:

export PATH="/C/Qt/4.8.4/bin:/C/Program Files (x86)/CMake 2.8/bin:$PATH"

After unzipping the code I ran CMake from command line including my build options and using MSYS makefiles (normal ones used in GNUStep’s makes):

cmake -D BUILD_EXAMPLES=1 -D BUILD_SHARED_LIBS=1 -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/home/xilexio/vtk -D VTK_Group_Qt=1 -G "MSYS Makefiles" .
make
make install

That created VTK release library. Note that VTK release library uses Qt Release libraries. For debug VTK library, I changed CMAKE_BUILD_TYPE to Debug.

The problems with VTK arrive with its usage in non-CMake. I use Qt Creator and its project file (.pro) for building my application. There are two things to consider here. First – building and running with appropriate VTK libraries. For VTK’s Qt module to work, you have to use release VTK with release Qt and debug VTK with debug Qt. Sounds easy, but requires configuration in two places:

  • You have to include a condition in your project file to link with appropriate VTK version (here we additionally only set it for Windows):
    win32 {
        CONFIG(debug, debug|release) {
            LIBS += -Llib/vtk/release
        } else {
            LIBS += -Llib/vtk/debug
        }
    }
  • You have to run the application with appropriate VTK libraries in PATH. In Qt Creator go to Projects > Run and create two Run Configurations – debug and release. In Run Environment set the PATH to contain only one version of VTK libraries (debug or release). Another option could be renaming all VTK libraries, for example by appending “d” to file name, but I haven’t tested that.

If you’ll forget about those steps, you’ll get following error:

QWidget: Must construct a QApplication before a QPaintDevice

The cause for this error is usually using two different Qt libraries (in our case both debug and release). So, make sure to attach proper set of Qt and VTK libraries when deploying the application.

Second thing to remember is supplying appropriate defines to VTK headers. As stated here, if you’re not using CMake build, you have to set those defines yourself. You must define two variables before including any VTK header. I tried adding defines to my project file:

DEFINES += vtkRenderingVolume_AUTOINIT=...

but in the end I wasn’t able to get a good amount of backslashes and quotes to make it work. So I had to go with a precompiled header:

PRECOMPILED_HEADER = pch.h

and paste default options in it:

#ifndef PCH_H
#define PCH_H
#define vtkRenderingCore_AUTOINIT 4(vtkInteractionStyle,vtkRenderingFreeType,vtkRenderingFreeTypeOpenGL,vtkRenderingOpenGL)
#define vtkRenderingVolume_AUTOINIT 1(vtkRenderingVolumeOpenGL)
#endif // PCH_H

If you’ll forget about this step, program will crash once you actually try to use the library (in my case after clicking QVTKWidget window) giving the following error:

Generic Warning: In c:/GNUstep/msys/1.0/home/Xilexio/vtksrc2/VTK6.0.0/Rendering/Core/vtkRenderWindow.cxx, line 35
Error: no override found for 'vtkRenderWindow'.

With all that configuration VTK becomes usable in Qt project. However, there’s one thing to note if you’re deploying your application. For some reason a hardcoded directory path VTK_MATERIALS_DIRS generated during installation exists in vtkRenderingOpenGLConfigure.h. Apparently it’s used to locate some files with vtkXMLShader::LocateFile (and maybe in other places too). My guess is that as long as you don’t use magical functions like “find my file without me specifying root directory”, it should work on other machines too.

I wanted to find a numerical library that could solve a system of partial differential equations (PDEs) and would support automatic creation of a mesh. My other requirement was to be able to create my application under my favorite MIT license, so GPL libraries were out of question. There are many FEM libraries, however most of them are either GPL, have GPL dependencies (like UMFPACK in latest releases), don’t have automatic mesh creation or are not mature enough. After searching for a while I decided on getfem++, which looked like a promising LGPL library that would suit my needs.

getfem++ is a finite element library, which might be useful if you want to numerically solve a system of PDEs. It uses LAPACK and BLAS libraries for matrix/vector operations, gmm++ library for solving linear systems defined by sparse matrices, optionally Qhull library for automatic mesh creation and optionally muparser library for parsing mathematical expressions (like function determining Dirichlet boundary condition). Licenses were okay – BSD/MIT/BSD-ish for LAPACK, BLAS, Qhull and muparser and LGPL for getfem++ and gmm++.

Everything was great until I actually tried to compile this set on MinGW and make a shared library out of it. Results of my work can be found in my getfem++ bitbucket repository. If you’re not interested in compilation and just want to use this library with MinGW, you can stop reading here.

Let me note that I was doing the compilation on Windows 7 with GNUStep’s mingw32 with g++ 4.6.1.

First dependencies. I downloaded precompiled win32 LAPACK 3.4.1 and BLAS dynamic libraries for mingw32 from here. I’d like to mention that LAPACK and BLAS libraries need two basic libraries to run – libgfortran and libquadmath.

Next one was muparser 2.2.3. While it did build dynamically, for some reason compiled dynamic library didn’t work with getfem++. So I decided to go with custom static muparser library build (it’s on MIT license, so it’s okay). At this point of time I’m not even sure if customizing the build was required, but it worked.
After unzipping sources I built a dynamic library:

cd build
mingw32-make -f makefile.mingw SHARED=1

That made files being built with appropriate flags for dynamic library. Then I created the static library myself from produced files:

cd build/obj/gcc_shared_rel
ar cru libmuparser.a muParser*.o
ranlib libmuparser.a

Last dependency is Qhull 2012.1. I didn’t build the library, I just copied qhull.dll from bin/ folder from its package. I took headers them from src/libqhull/*.h. The problem was that getfem++ required qhull.h header, but it was named libqhull.h in Qhull. So I renamed it to qhull.h and changed #include’s in other headers to look for qhull.h. I also tried building Qhull static library, but for some reason it didn’t work well with getfem++.

Last task was to build getfem++ 4.2 library. It required quite a bit of tweaking in exports and experimenting with builds of its dependencies to make it work. Exports I used in my msys console (put to .profile) were:

export CPPFLAGS="-L/home/Xilexio/lib -I/home/Xilexio/include"
export CXXFLAGS="$CPPFLAGS"
LDFLAGS="-L/home/Xilexio/lib"
export LD_LIBRARY_PATH="/home/Xilexio/lib:$LD_LIBRARY_PATH"
export LIBRARY_PATH="C:/GNUstep/msys/1.0/home/Xilexio/lib;$LIBRARY_PATH"

Where /home/Xilexio/lib contained all previously built libraries and /home/Xilexio/include contained all headers (note: Qhull headers were supposed to be in qhull subdirectory). Those exports allowed both proper compilation and finding libraries by executables. Later I compiled the getfem++ itself with:

./configure --enable-qhull --enable-muparser --enable-shared --prefix="/home/xilexio/getfem" && make && make install

That created static getfem++ library. Next, I created a shared version of the library. I did it by simply taking libgetfem.a static library from install directory, extracting all its contents (.o files) and combining them back together, this time into a dynamic library:

ar x libgetfem.a
g++ -shared -fPIC -Wl,--enable-auto-import -Wl,-no-undefined -Wl,--enable-runtime-pseudo-reloc -Wl,--out-implib,libgetfem_dll.a -o getfem.dll $CPPFLAGS *.o -lblas -llapack -lqhull -lmuparser

Done. This library worked for me.

But still, I wanted to check if getfem++ tests were passing. Because they were compiling test applications directly with src/.libs/libgetfem.a static library, I had to trick this build process by copying getfem.dll to src/.libs/libgetfem.a. In the end g++ somehow understood that it was a dynamic library and linked properly with it. Application didn’t work without getfem.dll in its location, so I guess dynamic linking was done properly. That change made tests build, but one of tests failed – test_large_sliding_contact.cc. It worked after removing one of asserts:


GMM_ASSERT1(err < 4e-6, "Erroneous gradient of normal vector "); I think something might have gone wrong with computations in this test, because I didn't compile this library with QD (high precision floats library). By the way, I couldn't find a version of QD that would work on Windows. Warning: getfem++'s user documentation states that we should have built a static library, so this is not a normal build. There is also no problem in using static getfem++ library version with non-GPL programs, because of getfem++ uses GCC Runtime Library Exception.