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