Without much forethought, I began to use qmake from NVidia's Qt toolkit. I did this originally because I was using Qt to build cross-platform GUIs for code, but continue to do so because it works well and is dead easy. There are other cross-platform build systems out there such as CMake, SCONS, and so on, but I've yet to find one that gives me a compelling reason to switch from qmake.
That said, the process that I went through to finally arrive at this process was not straightforward. This post is intended to roughly document how I set up my machines to work cleanly and easily with qmake. Ultimately this boils down to:
- Use ONLY portable third-party libraries
- Create consistently-named qmake include files for each library on each system
- Keep ALL those include files in a single directory, ideally with the source-tree of the library
- Define a consistently-named environment variable on all machines that points to the directory
The *.pri files are the qmake include files, while the directories hold the library source trees. Some libraries, like CGAL, automatically install themselves to a different location on the machine, such as /usr/local. That doesn't matter, the project include file still goes in the directory pointed to by $ThirdPartyDir. On Windows, I have another directory ThirdPartyDir, located at a completely different path, pointed to by the environment variable %ThirdPartyDir%, with the same sub-directories and versions of the *.pri files modified to work for Windows.
The *.pri files themselves handle adding linker flags, header search paths and any preprocessor definitions needed to the project. They look like incomplete qmake project files, as seen by the excerpt of my vtk.pri file:
INCLUDEPATH += "/usr/local/include/vtk-5.8" LIBS += -L/usr/local/lib/vtk-5.8 LIBS += -lvtkalglib \ -lvtkCharts \ -lvtkCommon \ -lvtkGraphics \ -lvtkDICOMParser \ -lvtkexoIIc \ -lvtkexpatNow any project that needs vtk can simply include the qmake include file into it's project file. Provided the include file exists and is correct, all the include paths, linker flags and preprocessor definitions will be set up correctly, as in the following project file:
TEMPLATE = app QT += opengl CONfIG += console debug_and_release TARGET = camera_model !include( $$(ThirdPartyDir)/eigen.pri ) !include( $$(ThirdPartyDir)/cimg.pri ) !include( $$(ThirdPartyDir)/vtk.pri ) mac { CONFIG -= app_bundle MOC_DIR = build } INCLUDEPATH += include HEADERS += include/camera.h SOURCES += src/main.cpp \ src/camera.cpp
This project file is now completely portable, able to be built on Windows, OS-X and Linux without change. The include files themselves eigen.pri, cimg.pri and vtk.pri may differ between systems as necessitated by versions, access permissions and install locations, but the project itself is consistent.
This process is ultimately similar to how CMake is intended to function, however I have wasted hours trying to get CMake find scripts to function, often without success. By just creating these include files whenever I use third-party code, I've found that much of the frustration of cross-platform development just goes away.
No comments:
Post a Comment