CMake:如何使用不同版本的 Qt 库进行编译?

CMake: How to compile with different library versions of Qt?

如何让 CMake 与 Qt4.8 或 Qt5 有条件地编译? 换句话说,如果 Qt5 可用,则使用 Qt5 进行编译。 否则,如果 Qt4.8 可用,请使用它。

在我的 CMake 中,我有:

find_package(Qt5 COMPONENTS Core Gui Widgets...)

这适用于我的 Qt5 构建,但我如何使用 Qt4.8 构建相同的软件?

我需要一些包含主版本号的东西,例如:

find_package(Qt $QT_VERSION_MAJOR...)

或使用条件,例如:

result = find_package(Qt 5...)
if (!result) then find_package(Qt4 ...)

或者以某种方式检测当前安装的 Qt 版本。

我在安装了 Qt4.8 的机器上得到的错误是(不出所料):

CMake Error at CMakeLists.txt:54 (find_package):
  By not providing "FindQt5.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "Qt5", but
  CMake did not find one.

  Could not find a package configuration file provided by "Qt5" with any of
  the following names:

    Qt5Config.cmake

最好的方法是什么?

使用 find_package 命令的 NAME 选项自动选择可用的 Qt 版本相当容易。问题是 Qt4 和 Qt5 对于相同的模块有不同的名称。

# We first try to find the main module of Qt4, Qt5 or Qt6
find_package(QT NAMES Qt4 Qt5 Qt6 REQUIRED)
set(QT Qt${QT_VERSION_MAJOR})

# We prepare lists of modules and libraries for different
# versions of Qt
if (QT_VERSION_MAJOR EQUAL 4)
    set(APP_QT_MODULES QtCore QtNetwork QtGui QtXml)
    set(APP_QT_TARGETS Qt4::QtCore Qt4::QtNetwork Qt4::QtGui Qt4::QtXml)
else ()
    set(APP_QT_MODULES Core Network PrintSupport Widgets Xml)
    set(APP_QT_TARGETS ${QT}::Core ${QT}::Network ${QT}::PrintSupport ${QT}::Widgets ${QT}::Xml)
endif ()

# Here everything is simple - find the modules we need.
find_package(${QT} REQUIRED ${APP_QT_MODULES})

. . .
. . .

# And at last don't forget to add libraries.
add_executable(my_app app.cpp main.cpp window.cpp)
target_link_libraries(my_app ${APP_QT_TARGETS})

另一个问题是 Qt 函数也有不同的名称,例如 qt4_add_resourcesqt5_add_resources。这是怀疑您的项目是否真的需要 Qt4 支持的一个很好的理由。

更新

我们可以制作 Qt 函数别名(从 5.15 版开始就是 done in Qt)。

if (QT_VERSION VERSION_LESS 5.15)
    macro(qt_wrap_cpp)
        ${QT}_wrap_cpp(${ARGV})
    endmacro()

    macro(qt_add_resources)
        ${QT}_add_resources(${ARGV})
    endmacro()

    macro(qt_generate_moc)
        ${QT}_generate_moc(${ARGV})
    endmacro()
endif ()