【问题标题】:How to include a certain Qt installation using CMake?如何使用 CMake 包含某个 Qt 安装?
【发布时间】:2012-09-12 17:53:15
【问题描述】:

我们在每台开发 PC 上都有大量 Qt 副本 - 每个项目在第三方目录中都有自己的 Qt 副本。这是因为每个项目都是用自己的 Qt 开发和测试的;通常情况下,我们需要为某个项目定制 Qt 构建。因此,由于上面提到的,我们有一个单独的 SVN 存储库,用于保存各种 Qt 构建和每个 Qt 项目中的外部,它指的是这些构建中的一个。

问题是,在使用 CMake 时,我们只能选择 Qt 的版本,而 Qt4 finder 会自行决定使用什么 Qt。这不是正确的。我们需要重定向查找器以配置项目第三方目录中特定 Qt 副本的所有内容。

我尝试为FIND_PACKAGE 指定PATHS 选项,如下所示:FIND_PACKAGE( Qt4 REQUIRED PATHS "thirdparty/Qt" ),但这没有帮助。我试图设置QT_QMAKE_EXECUTABLE 变量,但没有奏效。我尝试在安装之前将所需的 QMake 路径(FindQt4.cmake 使用它来确定所有目录)添加到 PATH 变量中,但这也没有帮助。

有没有办法使用 FIND_PACKAGE 提供的所有东西,但用于某个 Qt 副本?我真的不想实现所有 Qt 包装器,手动设置所有定义、包含、目录等。

这是我的 CMake 项目。也许这会有所帮助:

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

更新

正如 cmets 中提到的已接受答案,我已通过设置 QT_QMAKE_EXECUTABLE CMake 变量设法设置了一个自定义 qmake.exe(不同于添加到 OS PATH 变量中的那个)。但问题是,qmake 可执行文件具有所有 Qt 模块的硬编码路径。所以我通过提供一个自定义的qt.conf 文件解决了这个问题(正如答案中提到的那样)。我在互联网上没有找到任何例子,所以在这里,也许它会对某人有所帮助:

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

我正是用这个。您可以考虑在前缀中指定 Qt 安装的绝对路径。我只是不想在 repo 中使用绝对路径,它可以克隆到任意位置。有关使用qt.conf 的详细信息,请参阅this 链接。

【问题讨论】:

  • "PATHES" -- 不正确的拼写是“PATHS”吗?
  • 这就是为什么 CMake 的 find_package 命令完全是垃圾。每个 FindXXX.cmake 模块都只是一些不一致的混乱,与任何其他查找模块几乎没有相似之处。这破坏了 CMake 的用处。要成为一个一致的查找模块,只需使您的模块完全不一致以保持与其他模块的一致性。

标签: qt cmake


【解决方案1】:

QT_QMAKE_EXECUTABLE 让您走在正确的轨道上。该变量是一个缓存变量,所以简单地设置它是行不通的……除非您通过 GUI 更改它,或者在第一次运行 cmake 之前,或者在 CMakeCache.txt 中,或者使用 CACHE 更改它,否则缓存的值将一直存在和 FORCE 选项到SET

这是我使用的惯用语,因为我有固定的逻辑来根据配置时已知的变量选择我的 QT 目录。在这里,我在运行 FIND_PACKAGE 之前设置了变量,所以没有缓存问题。

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()

把它放在 FIND_PACKAGE(Qt4) 之前

根据 cmets 中的新信息进行编辑:

哦,我现在和你在一起。你有多少损坏的 Qt 安装。 FindQt 模块将始终使用 qmake 可执行文件来发现 Qt 树的设置。 Qmake 将这些信息存储在一组“持久属性”中,可以用qmake -query 查询,用qmake -set 设置。因此,您可以通过运行它的 qmake 并设置 QT_INSTALL_PREFIX 属性来“修复”Qt 安装,如此处所述:http://doc.qt.digia.com/4.7-snapshot/qmake-environment-reference.html

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

或者,在旧的 SO 问题 qmake and QT_INSTALL_PREFIX. How can I select a new location for Qt library? 中,未接受的答案使用 qt.conf 覆盖 QT 前缀。

这两种解决方案都涉及修改 Qt 安装。我不确定有什么办法可以解决这个问题,但是这超出了您的存储库和构建系统的范围。

【讨论】:

  • 问题是,所有的 Qt 副本都是在不同的计算机上构建和使用的。并且 qmake 顽固地继续返回构建机器的路径,而不是当前位置。我该如何处理?
  • 这就是我刚刚给出的答案。如果你不能以任何方式自动选择,那么在填充缓存之前手动 QT_QMAKE_EXECUTABLE 并且在运行 FIND_PACKAGE(Qt4) 之前。
  • 你还没有得到它。众所周知,qmake.exe 已经为它构建的机器内置了路径。 FindQt4.cmake 使用 qmake.exe 来确定 Qt 的安装路径。它只是返回不正确的!它们指的是构建它的计算机上的路径,但不能保证它将在另一台开发 PC 上以完全相同的路径检出。我可以指定 qmake 可执行文件,但由于这些损坏的路径,这没有给我任何帮助。不过,似乎有一种解决方案 - 使用 qt.conf。这就是我现在正在尝试做的事情。
  • 是的,成功了!您提供的解决方案和 qmake.exe 旁边的 qt.conf 文件起到了作用。我可能会更新我的问题以添加我的 qt.conf(我在互联网上没有找到它的示例,也许它会对某人有所帮助)。
【解决方案2】:

如果可以的话,我想完成/确认这里所说的一些信息并给出一个完整的例子。

像 Occulta 一样,我有一个定制的 Qt 环境,我必须将其用于我的项目。这些是我为使项目编译而复制的步骤:

  1. 我项目的 CMakeLists.txt,已经拥有所有 CMake 内容,只需包含一个“qt.cmake”文件

    include(qt)
    
  2. qt.cmake 文件包含 Peter 的解决方案,并用其他东西装饰。通过这个配置,我可以使用moc、uic和rcc来管理UI文件、资源文件等。这是我的一些cmets的文件。如果它们不完全正确,请不要犹豫(CMake 的工作方式对我来说仍然是多云的):

    # The path where Qt is.
    SET(QT_ROOT_DIR "path/to/qt")
    
    set(QT_QMAKE_EXECUTABLE ${QT_ROOT_DIR}/osx/bin/qmake)
    
    # Loads CMake macros bound to Qt.
    find_package(Qt4 REQUIRED)
    # Includes used Qt headers.
    include(${QT_USE_FILE})
    
  3. 我还添加了 Occulta 的 qt.conf 文件,与 qmake 可执行文件处于同一级别。

完成这三个步骤后,一切都很好。希望这个完整的例子对某人有所帮助。

谢谢你们,你们显然帮助了我!

【讨论】:

    【解决方案3】:

    这对我有用:

    set( QT_ROOT /opt/myqt/ )
    set( ENV(CMAKE_PREFIX_PATH) ${QT_ROOT} )
    FIND_PACKAGE( Qt4 COMPONENTS QtCore QtGui QtDBUS REQUIRED )
    

    这将改变PATH环境变量,但我还没有找到其他方法。其他答案对我不起作用。

    【讨论】:

      猜你喜欢
      • 2018-04-10
      • 2018-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-25
      相关资源
      最近更新 更多