Back to Articles

Notes on linking Open CV with QMake

So, I'm going to talk about a few additions to linking OpenCV with qmake. The basic part involves setting up the include path, and then adding the needed libraries:

INCLUDEPATH += path/to/opencv/include
LIBS += -Lpath/to/opencv/lib -lopencv_core2410 -lopencv_highgui2410

On linux we can use pkg-config:

CONFIG += link_pkgconfig
PKGCONFIG += opencv

Although this simplicity, there's 2 things I don't like for the windows part of this configuration:

  • The PATH to Open CV binaries must be set for the application to run, or the binaries must be copied to our release manually
  • The version must be specified for each lib, which is a bit annoying when someone using a different version is using your code, and also whn releasing through a build server with a diffrent version, which you then have to configure specifically

To resolve these, I'll look into adding this functionality within an includable qmake project file.


If you want to skip the process, you can find the file here

For the version problem, wildcard matching doesn't work, since it can expand to both opencv_core2410d.lib and opencv_core2410.lib on msvc:

LIBS += -l$$files(/path/to/opencv/opencv_core*.lib)

So, the solution is to strip down the version number, and insert it into our library file. The following function does just this:


isEmpty(OPENCV_VERSION){  #version number isn't set
	OPENCV_VERSION_FIND = $$files($$OPENCV_DIR_LIBRARIES/opencv_core*) 
	OPENCV_VERSION_FIND = $$first(OPENCV_VERSION_FIND) 
	 
	OPENCV_VERSION_FIND = $$split(OPENCV_VERSION_FIND, opencv_core) 
	OPENCV_VERSION_FIND = $$last(OPENCV_VERSION_FIND) 

	OPENCV_VERSION_FIND = $$replace(OPENCV_VERSION_FIND, [^0-9], '') 
	OPENCV_VERSION      = $$OPENCV_VERSION_FIND 
	
	CONFIG(debug, debug|release):OPENCV_VERSION = $${OPENCV_VERSION}d
}

First, we get the 2 files (opencv_core2140d.lib, and opencv_core2140.lib). Then we select the first one, split around opencv_core, and select the last segment, which ends up being 2410.lib or 2410d.lib. We remove any expression that isn't a number, and we get the version. If it's a debug, we append the 'd' at the end.

To copy our files, we define the following section:

CONFIG(debug, debug|release):  DLL_DESTINATION = $$OUT_PWD/debug/ 
CONFIG(release, debug|release):DLL_DESTINATION = $$OUT_PWD/release/

defineTest(copyCvDll) { 
	files = $$1 
	for(FILE, files) { 
		DDIR = $${DLL_DESTINATION} 
		# Replace slashes in paths with backslashes 
		win32:FILE ~= s,/,\\,g 
		win32:DDIR ~= s,/,\\,g 
		QMAKE_POST_LINK += $$QMAKE_COPY \"$$FILE\" \"$$DDIR\" $$escape_expand(\\n\\t) 
	} 
	export(QMAKE_POST_LINK) 
} 

We use the system copy function defined by $$QMAKE_COPY, which copies each file to the path configured in DLL_DESTINATION.

To wrap this up, we add a function to load OpenCV modules. A second parameter is needed in case we want to deploy the binaries:

defineTest(loadOpenCV){ 
	modules = $$1 
	copyDll = $$2 
	 
	contains(modules, core){ 
		LIBS += -L$${OPENCV_DIR_LIBRARIES} -lopencv_core$${OPENCV_VERSION} 
		equals(copyDll, deploy):copyCvDll($${OPENCV_DIR_DLLS}/opencv_core$${OPENCV_VERSION}.dll) 
	}
	
	contains(modules, highgui){ 
		LIBS += -L$${OPENCV_DIR_LIBRARIES} -lopencv_highgui$${OPENCV_VERSION} 
		equals(copyDll, deploy):copyCvDll($${OPENCV_DIR_DLLS}/opencv_highgui$${OPENCV_VERSION}.dll) 
	}
	
	# ...
	
	export(LIBS)
}

Then, we can use the file as:

include(opencvconfig.pro) 
loadOpenCV(core highgui, deploy) 

Download at: https://gist.github.com/dinusv/0fb3c7149ec28ce7edf7