[CMake] FindQt4.cmake to automatically include QT_USE_FILE?

Michael Hertling mhertling at online.de
Wed Jun 8 21:14:43 EDT 2011


On 06/07/2011 02:20 PM, Bjørn Forsman wrote:
> Hi all,
> 
> As far as I can tell, all Qt programs built with CMake must include
> QT_USE_FILE after find_package(). So why doesn't FindQt4.cmake simply
> include QT_USE_FILE itself? Is there maybe a use case where
> QT_USE_FILE is *not* wanted?

Yes, there is: Suppose there is a tiny library package X which uses
Qt's signal/slot mechanism and, thus, must link against QtCore. X's
FindX.cmake or XConfig.cmake is expected to provide the variables
X_LIBRARIES, X_INCLUDE_DIRS and X_DEFINITIONS. While you can add
QT_QTCORE_LIBRARY to X_LIBRARIES and QT_QTCORE_INCLUDE_DIR to
X_INCLUDE_DIRS, how do you add the preprocessor definition for
the compilation with the QtCore headers, i.e. -DQT_CORE_LIB, to
X_DEFINITIONS? These definitions are hardcoded in QT_USE_FILE and
immediately enabled there via ADD_DEFINITIONS(). FindQt4.cmake does
not provide symbolic names for them, so you cannot set up a complete
compilation environment for Qt modules without including QT_USE_FILE,
and that's not allowed for find modules or config files as Michael W.
has pointed out in this thread earlier. The only possibilities for X
to allow its users to prepare a complete compilation environment are

1) either tell X's users to include QT_USE_FILE after FIND_PACKAGE(X)
when they want to use the X stuff ("Why do I have to include this
QT_USE_FILE thing when all I want is just using X? Strange...")

2) or provide an own X_USE_FILE which just includes QT_USE_FILE, and
tell X's users to include X_USE_FILE after FIND_PACKAGE(X) when they
want to use the X stuff ("Why do I have to bother with this USE_FILE
thing when I want to use a tiny package like X? I have already seen
more complex packages that don't require such hassle. Strange...").

Currently, the QT_USE_FILE is not just convenient, but *necessary* to
completely set up the compilation environment. IMO, that's wrong, in
particular as it is not only to be used in CMakeLists.txt files, but
also in other find modules and, possibly, configuration files.

There's another reason why QT_USE_FILE is somewhat essential to set
up the compilation environment: It cares for the Qt inter-module
dependencies. Look at the following example:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(QTMODDEPS C CXX)
SET(CMAKE_VERBOSE_MAKEFILE ON)
FIND_PACKAGE(Qt4 COMPONENTS QtSvg)
INCLUDE(${QT_USE_FILE})
FILE(WRITE ${CMAKE_BINARY_DIR}/main.c "int main(void){return 0;}\n")
ADD_EXECUTABLE(main main.c)
TARGET_LINK_LIBRARIES(main ${QT_LIBRARIES})

It's QT_USE_FILE that enables Qt{Xml,Gui,Core} in the link command line
although only QtSvg has been requested. Therefore, if one doesn't want
to use QT_USE_FILE, one has to sort out these dependencies by oneself.
IMO, that's also wrong as I'd consider it to be the find module's job
to track dependencies among components requested with FIND_PACKAGE(),
not a USE_FILE's one. BTW, if you replace Svg by Sql in the example
above, you'll see that the main target is linked only against QtSql
although the latter does depend on QtCore. Obviously, QT_USE_FILE's
dependency management is not complete, so one should take care of
mentioning all necessary Qt modules in FIND_PACKAGE() by oneself.

Personally, I'd appreciate a FindQt4.cmake which

- completely and correctly tracks dependencies among the Qt modules,
- provides the usual variables QT_{LIBRARIES,INCLUDE_DIRS,DEFINITIONS},
- populates them with settings based on the COMPONENTS list passed to
  the FIND_PACKAGE(Qt4 ...) call and those components' prerequisites,
- does *not* take the results of previous FIND_PACKAGE(Qt4 ...) calls
  into consideration, i.e. does not act in an accumulative manner. So,
  the values of the QT_{LIBRARIES,INCLUDE_DIRS,DEFINITIONS} variables
  after a call to FIND_PACKAGE() do depend only on the COMPONENTS list
  passed to FIND_PACKAGE(), well-known variables as CMAKE_PREFIX_PATH
  and package-specific - documented - ones as QT_QMAKE_EXECUTABLE.

In this way, QT_USE_FILE would not be necessary anymore, and one could
invoke FIND_PACKAGE(Qt4 ...) multiple times and anywhere in a project
and gets exactly what has been requested without the risk of catching
unmeant results from previous FIND_PACKAGE(Qt4) invocations. Finally,
find modules may provide their users with complete information about
the compilation environment if their respective package uses Qt4.

Regards,

Michael


More information about the CMake mailing list