Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to include a certain Qt installation using CMake?

Tags:

We have plenty Qt copies on every dev PC - each project has its own Qt copy in the thirdparties directory. That's done due to each project is developed and tested with its own Qt; an often case is that we need a custom build of Qt for some project. So due to mentioned above we have a separate SVN repo for holding various Qt builds and an external in each Qt project, which refers to one among those builds.

The problem is, when using CMake we can only select a version of Qt and the Qt4 finder decides what Qt to use by itself. And that's not the correct one. We need to redirect the finder to configure all stuff for a particular Qt copy in project's third parties directory.

I've tried to specify the PATHS option for FIND_PACKAGE like that: FIND_PACKAGE( Qt4 REQUIRED PATHS "thirdparty/Qt" ) but that didn't help. I have tried to set the QT_QMAKE_EXECUTABLE variable, but that didn't work. I've tried to add the required QMake's path (it's used by the FindQt4.cmake to determine all directories) to the PATH variable before the installed one, but that didn't help too.

Is there a way to use all the stuff which the FIND_PACKAGE provides but for a certain Qt copy? I really don't want to implement all Qt wrappers, set all definitions, includes, dirs, etc manually.

Here is my CMake project. Maybe that will help:

CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )

#############################################################################

MACRO( ADD_FILES_TO_FILTER rootFilterName rootFilterPath files )
    FOREACH( curFile ${files} )
        FILE( RELATIVE_PATH curFilter "${CMAKE_CURRENT_SOURCE_DIR}/${rootFilterPath}" "${CMAKE_CURRENT_SOURCE_DIR}/${curFile}" )
        FILE( RELATIVE_PATH test "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/${curFile}" )
        GET_FILENAME_COMPONENT( curFilter ${curFilter} PATH )
        SET( curFilter "${rootFilterName}/${curFilter}" )
        STRING( REPLACE "/" "\\\\" curFilter ${curFilter} )
        SOURCE_GROUP( ${curFilter} FILES ${curFile} )
    ENDFOREACH( curFile )
ENDMACRO( ADD_FILES_TO_FILTER rootFilterName rootFilterPath files )

MACRO( TO_RELATIVE_PATHS filePaths )
    SET( resPaths "" )
    FOREACH( curPath ${${filePaths}} )
        FILE( RELATIVE_PATH relPath ${CMAKE_CURRENT_SOURCE_DIR} ${curPath} )
        SET( resPaths ${resPaths} ${relPath} )
    ENDFOREACH( curPath )
    SET( ${filePaths} ${resPaths} )
ENDMACRO( TO_RELATIVE_PATHS filePaths )

######################################################################

# Define project settings
PROJECT( RealTimeCapture )
FIND_PACKAGE( Qt4 REQUIRED PATHS "thirdparty/Qt" )
SET( BOOST_ROOT "thirdparty/boost" )
FIND_PACKAGE( Boost REQUIRED )

# Collect all required files for build
FILE( GLOB_RECURSE headers RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/RTCF/include/*.h" )
FILE( GLOB_RECURSE sources RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/RTCF/src/*.cpp" )
FILE( GLOB_RECURSE resources RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.qrc" )
FILE( GLOB_RECURSE forms RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.ui" )

# Preprocess all Qt files
QT4_WRAP_CPP( header_mocs ${headers} )
QT4_WRAP_UI( form_headers ${forms} )
QT4_ADD_RESOURCES( resources_rcc ${resources} )

# Convert all generated files paths to relative ones
TO_RELATIVE_PATHS( header_mocs )
TO_RELATIVE_PATHS( form_headers )
TO_RELATIVE_PATHS( resources_rcc )

# Create executable
ADD_EXECUTABLE( RealTimeCapture ${headers} ${sources} ${header_mocs} ${form_headers} ${resources_rcc} )
SET_TARGET_PROPERTIES( RealTimeCapture PROPERTIES COMPILE_FLAGS "/Zc:wchar_t-" )

# Set filters for project according to its namespaces
FILE( RELATIVE_PATH buildDir ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} )
ADD_FILES_TO_FILTER( "Headers" "src/RTCF/include" "${headers}" )
ADD_FILES_TO_FILTER( "Sources" "src/RTCF/src" "${sources}" )
ADD_FILES_TO_FILTER( "Generated" "${buildDir}/src/RTCF/include" "${header_mocs}" )
ADD_FILES_TO_FILTER( "Forms" "${buildDir}/src/RTCF/include" "${form_headers}" )
ADD_FILES_TO_FILTER( "Resources" "${buildDir}" "${resources_rcc}" )

# Set additional include directories
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} )
INCLUDE_DIRECTORIES( "src" )
INCLUDE_DIRECTORIES( "src/RTCF/include" )
INCLUDE_DIRECTORIES( "thirdparty" )

# Configure Qt
SET( QT_USE_QTNETWORK TRUE )
SET( QT_USE_QTSQL TRUE )
SET( QT_USE_QTSCRIPT TRUE )
SET( QT_USE_QTXML TRUE )
SET( QT_USE_QTWEBKIT TRUE )
INCLUDE( ${QT_USE_FILE} )
ADD_DEFINITIONS( ${QT_DEFINITIONS} )
TARGET_LINK_LIBRARIES( RealTimeCapture ${QT_LIBRARIES} )

# Add boost support
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} )
TARGET_LINK_LIBRARIES( RealTimeCapture ${Boost_LIBRARIES} )

# Add other libs include dirs
INCLUDE_DIRECTORIES( "thirdparty/SimpleCrypt" )
INCLUDE_DIRECTORIES( "thirdparty/id3lib/include" )
INCLUDE_DIRECTORIES( "thirdparty/libtwitcurl" )
INCLUDE_DIRECTORIES( "thirdparty/curl-7.24.0/curl/include" )
INCLUDE_DIRECTORIES( "thirdparty/log4qt/include" )
INCLUDE_DIRECTORIES( "thirdparty/fervor-auto" )

# Add defines
ADD_DEFINITIONS( RealTimeCapture -DQUAZIP_STATIC )
ADD_DEFINITIONS( RealTimeCapture -DBUILDING_LIBCURL )
ADD_DEFINITIONS( RealTimeCapture -DID3LIB_LINKOPTION=1 )
ADD_DEFINITIONS( -DUNICODE -D_UNICODE ) #enable unicode support

UPDATE

As it's mentioned in the comments to the accepted answer, I've managed to set a custom qmake.exe (different from the one added to the OS PATH variable) by setting the QT_QMAKE_EXECUTABLE CMake variable. But the problem was, the qmake executable has hardcoded paths to all Qt's modules. So I have solved it by providing a custom qt.conf file (as it's mentioned in the answer). I haven't found any examples of it in the internet, so here it is, maybe it will help someone:

[Paths]
Prefix=..
Documentation=doc
Headers=include
Libraries=lib
Binaries=bin
Plugins=plugins
Imports=imports
Data=
Translations=
Settings=
Examples=
Demos=

I used exactly this. You can consider specifying an absolute path to the Qt install in the prefix though. I just didn't want to use an absolute path in a repo, which can be cloned in an arbitrary location. See this link about details on using qt.conf.

like image 800
Roman Kruglov Avatar asked Sep 20 '12 11:09

Roman Kruglov


People also ask

How do I add CMake to Qt?

To add a path to a CMake executable that Qt Creator does not detect automatically, and to specify settings for it, select Add. To make changes to automatically detected installations, select Clone. Qt Creator uses the default CMake if it does not have enough information to choose the CMake to use.

How does CMake find Qt?

CMake can find and use Qt 4 and Qt 5 libraries. The Qt 4 libraries are found by the FindQt4 find-module shipped with CMake, whereas the Qt 5 libraries are found using "Config-file Packages" shipped with Qt 5.

Does Qt use CMake?

CMake is a buildsystem generator developed in the open, and widely used for Qt based development.


1 Answers

You're on the right track with QT_QMAKE_EXECUTABLE. That variable is a cache variable, so simply setting it won't work... the cached value will stick around unless you change it via the GUI, or before running cmake the first time, or in CMakeCache.txt, or with the CACHE and FORCE options to SET.

Here's the idiom I use, since I have fixed logic to choose my QT directory based on variables known at configure time. Here, I set the variable before ever running FIND_PACKAGE, so no cache issues.

IF(WIN32 AND ${CMAKE_SIZEOF_VOID_P} MATCHES 8)
  # Hardcode a location for a QT toolkit compiled for Win64.  By overriding QT_QMAKE, all the rest is found
  # Choose any version of QT found in the 64-bit tools area
  FILE(GLOB QTROOTS c:/Tools_x64/Qt/*/bin)     # */
  FIND_PROGRAM(QT_QMAKE_EXECUTABLE NAMES qmake qmake4 qmake-qt4 qmake-mac PATHS ${QTROOTS})
ENDIF()

Put this before FIND_PACKAGE( Qt4 )

EDITING based on new information in comments:

Oh, I'm with you now. You have what amount to broken Qt installations. The FindQt module will always use the qmake executable to discover the settings for the Qt tree. Qmake stores this information in a set of "persistent properties", which can be queried with qmake -query, and set with qmake -set. So you can "fix" a Qt installation by running it's qmake and setting the QT_INSTALL_PREFIX property, as documented here: http://doc.qt.digia.com/4.7-snapshot/qmake-environment-reference.html

qmake -set "QT_INSTALL_PREFIX" /path/to/qt/

Or, in an old SO question qmake and QT_INSTALL_PREFIX. How can I select a new location for Qt library?, a non-accepted answer uses qt.conf to override the QT prefix.

Both of these solutions involve modifying the Qt installation. I'm not sure there's any way around this, but how this fits into your repository and build system is out of scope here.

like image 121
Peter Avatar answered Oct 06 '22 06:10

Peter