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

时间:2017-08-21 10:54:09

标签: 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 external symbol。 / p>

仅在文件范围内调用单个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。

1 个答案:

答案 0 :(得分:2)

问题是CMake函数引入了一个范围,因此find_package中定义的变量在函数外部不可用。

解决问题的一个简单方法是使用CMake宏 - 您可以将它们视为CM宏的Cake等价物。在那里声明的变量也可以在宏范围之外使用。

在您的情况下,这意味着将function替换为macro,将endfunction替换为endmacro