2017-08-21 131 views
2

我想编译一些Qt项目,包括QCustomPlot库。作为最小的例子,我设置了包括项目:如果从函数调用find_package()和qt5_use_modules(),为什么AUTOMOC会失败?

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不再一部分。

在文件范围(如行(2))上只调用一个find_package()可解决此问题并再次生成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()定义,能够找到的所有模块并将其链接(如包括目录都设置适当的LY)。函数之外的任何地方都不依赖于由任何Qt函数设置的变量。但仍然automoc不会生成所需的.cpp文件。再次注释已标记的线路将自动运行。

回答

2

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

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

在你的情况下,这意味着用macroendfunctionendmacro代替function

+0

对于这个最小的例子,你的解决方案可能是合适的,但对于它后面的更大的项目它不是。除此之外,我可以在嵌套函数内调用所有'find_package()',并可以使用定义的变量,如Qt5_Core_LIBRARIES,这些变量完全不同。只有AUTOMOC无法生成该单个文件。 – Anedar

+0

@Anedar你可以在你的问题中指定为什么“宏”不适合? – oLen

+0

@Anarar对于'Qt5Core_LIBRARIES'仍然被定义,我只是测试它,当我使用'function'时变量不会被定义,这意味着我的答案在这方面是正确的。在你的情况下,它可能仍然存在,因为缓存或因为它来自其他地方。 – oLen

相关问题