2

我正在尝试编译一些 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链接过程中出现很多问题。

仅调用单个find_package()on files 范围(如 line (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。

4

1 回答 1

2

问题是 CMake 函数引入了一个作用域,因此在find_package函数之外定义的变量不可用。

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

在您的情况下,这意味着替换functionbymacroendfunctionby endmacro

于 2017-08-21T11:45:31.377 回答