我正在尝试编译一些 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。