c++ - 如果从函数调用 find_package() 和 qt5_use_modules() ,为什么 AUTOMOC 会失败?

标签 c++ qt cmake moc qt5.7

我正在尝试编译一些 Qt 项目,包括 QCustomPlot 库。作为一个最小的例子,我建立了一个项目,其中包括:

qcustomplot.h
qcustomplot.cpp
CMakeLists.txt
../cmake/QCustomPlot.cmake

原始项目更大,但仅使用这些文件就可以重现问题。

CMakeLists.txt 包含以下代码:

cmake_minimum_required(VERSION 3.6)

set(CMAKE_AUTOMOC ON)
include(../cmake/QCustomPlot.cmake)

function(findqt)                                       #(1)
  find_package(Qt5Core)
  find_package(Qt5Gui)
  find_package(Qt5Widgets)
  find_package(Qt5PrintSupport)
endfunction()                                          #(1)

findqt()                                               #(1)
#find_package(Qt5Core)                                 #(2)

add_library(
  Plots
  src/qcustomplot.h
  src/qcustomplot.cpp
)


function(linkqt)                                       #(3)
  qt5_use_modules(Plots Core Gui Widgets PrintSupport)
endfunction()                                          #(3)
linkqt()                                               #(3)

如果所有标记为 (1) 的行或所有标记为 (3) 的行都被注释掉,则意味着调用 find_package()qt5_use_modules() 在文件范围内,我得到一个包含两个 qcustomplot 文件和一个附加 Plots_automoc.cpp 的项目。附加文件是自动生成的,包含必要的 #include "moc_qcustomplot.cpp" 并且项目可以正确编译和链接。

但是,一旦我将所有与 qt 相关的命令移至函数中,automoc.cpp 文件就不再生成,也不再是项目的一部分,这导致了相当多的 Unresolved 问题链接期间的外部符号

在文件范围内仅调用一个 find_package()(如 (2) 行)即可解决问题并再次生成 automoc 文件。

为什么简单地将调用移动到函数中会改变这样的 automoc 行为,我如何才能仍然将它们移动到函数中?

一点背景知识:我的项目中已经有相当多的目标,预计数量会快速增长,并希望避免代码冗余。没有真正接受过 CMake 培训的人也应该使用它。这就是为什么我试图将所有这些 Qt 相关命令移至函数中并提供如下命令:

add_my_target(
  targetName
  SOURCES qcustomplot.h qcustomplot.cpp
  QT Core Gui Widgets PrintSupport
  BOOST filesystem
)

除了 Qt 之外,我已经实现了这一点......

我也尝试过使用

target_link_libraries(${projectName} ${Qt5_Core_LIBRARIES} ...
//or
target_link_libraries(${projectName} Qt5::Core ...

它会导致相同的结果,只要没有至少一个 find_package() 调用直接作用于文件范围,就不会生成 automoc。

我正在使用 CMake 3.6.2、Qt 5.7、Visual Studio 2015 和 Win 10。

其他示例 oLen 通过他的回答解决了我大部分潜在的困惑,但仍然存在一个情况:

cmake_minimum_required(VERSION 3.6)
set(CMAKE_AUTOMOC ON)

function(doit)                        #(4)
  find_package(Qt5Core)

  add_library(
    Plots
    qcustomplot.h
    qcustomplot.cpp
    )

  qt5_use_modules(Plots Core Gui Widgets PrintSupport)
endfunction()                         #(4)

doit()                                #(4)

使用(4)标记的行将目标的所有生成放入一个函数中可以让CMake正常运行,即定义了qt5_use_modules(),能够找到所有模块并链接它们(例如正确设置包含目录)。在函数之外的任何地方,我都不依赖任何 Qt 函数设置的变量。但 automoc 仍然没有生成所需的 .cpp 文件。注释掉标记的行会再次运行 automoc。

最佳答案

问题在于 CMake 函数引入了作用域,因此 find_package 中定义的变量在函数外部不可用。

解决您的问题的一个简单方法是使用 CMake 宏 - 您可以将它们视为 C 宏的 CMake 等效项。在那里声明的变量也可以在宏作用域之外使用。

就您而言,这意味着将 function 替换为 macro,将 endfunction 替换为 endmacro

关于c++ - 如果从函数调用 find_package() 和 qt5_use_modules() ,为什么 AUTOMOC 会失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45795303/

相关文章:

linux - QCA 不加载插件

c++ - 使用 CMake 在可执行文件中嵌入二进制数据

c++ - boost & asio 作为 Cmake 大项目的一部分

c++ - 动态分配数组的矩阵乘法;结果不正确

c++ - 无法使用 socat 写入打开 QSerialPort

python - OpenCV:自动调整窗口大小以显示图像

mysql - 无法链接到 C++ 中已编译/.so 源库

c++ - 此功能的问题

c++ - 将字符从一个字符串简单分配到另一个字符串不起作用

c++ - 元编程技巧 : how to simplify implementation of two metafunctions