Tuesday, August 11, 2009

Using qmake without a build target

One of the greatest weaknesses of Qt's qmake utility has been its over-reliance on templates. The available templates are standard stuff for Qt projects: app, lib, and subdirs (new with Qt4, I believe). These are all well and good when one is just slapping together a bunch of Qt code, but what about when interfacing with other build systems? A command template would be quite useful.

The follow project file is a workaround. The lib template is used (although app could be used as well) with empty HEADERS and SOURCES variables. The qmake variables that specify which build tools to use are set to a NOP (no-operation) tool such as echo or true. An "extra" target is created for the command to be executed, and set to be a pre-dependency of the main target.

Background: There is a config.py in . that has sip generate all C++ code, as well as the Makefile, in the directory 'sip'. The python module (sip_test.so) is output to the same directory. This project filed is invoked, along with many others, from a subdirs project file in the parent directory.


-----------------------------------------------------
# sip_test.pro
TEMPLATE = lib
TARGET = sip_test

# Check that sip exists
unix {
!system(sip -V > /dev/null) {
error( "SIP does not exist!" )
}
}

# sip build command and makefile targets
sip.commands = python ./config.py && cd sip && make
QMAKE_EXTRA_TARGETS += sip
PRE_TARGETDEPS = sip

# compiler toolchain override
unix {
# 'true' should exist on Unix and OS X. Win32 folk can
# use TYPE.EXE or something.
NOP_TOOL = true
}

QMAKE_CC = $$NOP_TOOL
QMAKE_CXX = $$NOP_TOOL
QMAKE_LINK = $$NOP_TOOL
QMAKE_LN_SHLIB = $$NOP_TOOL

# Copy the .so created by sip.commands to the current directory
QMAKE_POST_LINK = cp sip/$${TARGET}.so .
-----------------------------------------------------

With this project file, the standard "qmake && make" command works as expected.