我正在尝试编译一些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。
答案 0 :(得分:2)
问题是CMake函数引入了一个范围,因此find_package
中定义的变量在函数外部不可用。
解决问题的一个简单方法是使用CMake宏 - 您可以将它们视为CM宏的Cake等价物。在那里声明的变量也可以在宏范围之外使用。
在您的情况下,这意味着将function
替换为macro
,将endfunction
替换为endmacro
。