【问题标题】:Qt5, CMake, AUTOMOC and precompiled headersQt5、CMake、AUTOMOC 和预编译头文件
【发布时间】:2014-02-23 05:49:01
【问题描述】:

如何为 CMake (2.8.12.1) AUTOMOC 的输出指定预编译头文件?

到目前为止,在 CMakeLists.txt 中我已经分别尝试了这两个:

 set(AUTOMOC_MOC_OPTIONS "-bstdafx.h")
 set(AUTOMOC_MOC_OPTIONS "-fstdafx.h")

构建项目(project_automoc.cpp)时生成的AUTOMOC输出只包含moc_xxx.cpp文件:

/* This file is autogenerated, do not edit*/
/// <- stdafx.h should be here ?!?!
#include "moc_widget_fps.cpp"
#include "moc_widget_sysevents.cpp"

【问题讨论】:

    标签: visual-studio-2010 qt cmake qt5 stdafx.h


    【解决方案1】:

    要设置的正确变量称为CMAKE_AUTOMOC_MOC_OPTIONS。用于初始化目标的AUTOMOC_MOC_OPTIONS属性,即:

    set (CMAKE_AUTOMOC_MOC_OPTIONS "-bstdafx.h" "-fstdafx.h")
    

    还请注意,这只会使 Qt MOC 编译器将给定的包含添加到每个生成的 moc_xxx.cpp 文件中。整体project_automoc.cpp不受影响。

    【讨论】:

    • 但我需要影响project_automoc.cpp :(。因为项目计数在没有预编译头文件的情况下无法编译此文件。
    • 看CMake源代码好像project_automoc.cpp的生成是硬编码的,不可配置。
    • @DMitry,我目前的解决方法是在 CMAKE-set_target_properties(${TARGET_NAME} PROPERTIES AUTOMOC FALSE) 中对使用预编译头文件的项目禁用 automoc,并使用 QT5_WRAP_CPP(MOC_SOURCES ${MOC_FILES}) 对文件进行 moc。然后对于 MOC_SOURCES 中的每个 moc 文件 foreach(src_file ${moc_SRCS}) set_source_files_properties(${src_file} PROPERTIES COMPILE_FLAGS "/YuStableHeaders.h /FIStableHeaders.h") endforeach()
    • @Pencheff,您可以将其发布为答案。还有一个问题(我现在无法自己检查):将非 qt 标头传递给QT5_WRAP_CPP 是否安全?或者最好检查每个文件中的Q_OBJECT 宏(似乎很慢)?
    • @Dmitry,是的,可以安全地将任何(头)文件传递给 QT5_WRAP_CPP,即使是不存在的文件,也不会失败,项目仍然可以编译并运行良好。
    【解决方案2】:

    经过一番挖掘,我决定为使用预编译头文件的项目关闭 AUTOMOC 功能:

    set_target_properties (ProjectName PROPERTIES AUTOMOC FALSE)
    
    # Set the headers that need moc'ing
    file (GLOB MOC_FILES widget_filetransfer.h widget_main_menu.h widget_main_toolbar.h)
    QT5_WRAP_CPP (MOC_SOURCES ${MOC_FILES})
    
    ...
    # Force PCH for the generated MOC files
    foreach (src_file ${MOC_SOURCES})
        set_source_files_properties (${src_file} 
      PROPERTIES COMPILE_FLAGS "/Yustdafx.h /FIstdafx.h"
    )
    endforeach()
    

    【讨论】:

    • 关闭 automoc 时,请注意,在 Windows 上,您可以通过从命令行在源文件夹上执行 findstr /m /s "Q_OBJECT" "*.h" 轻松获取带有 Q_OBJECT 宏的所有头文件的列表。 Linux/MacOS 肯定有类似的命令
    • 目前还有其他解决方案吗?理想情况下,cmake 会提供一个选项来将包含文件添加到生成的 _automoc 文件中,对吧?
    【解决方案3】:

    AUTOMOC_MOC_OPTIONS 不会影响 project_automoc.cpp 文件。它包含传递给 moc 以创建“moc_widget_fps.cpp”和“moc_widget_sysevents.cpp”的选项。那些应该包含你的 pch 包括。

    【讨论】:

    • 当我打开 AUTOMOC ON 时,我在项目中看到的是,对于每个包含 Q_OBJECT 的类的 file.h,我会在构建目录中获得相应的 moc_file.cpp。这些文件没有添加到我的(visual studio)项目中,而是得到一个 project_automoc.cpp 文件,其中包含所有 moc 的 cpp 文件。由于我的项目使用预编译头文件,因此该文件应包含 stdafx.h。如果我在 VS 中手动将 /FIstdafx.h 添加到该文件中,它编译得很好
    • 在创建 moc_file.cpp 时验证 moc 命令行是否包含适当的 -b 和 -f 选项。
    • @steveire 不确定如果添加 -b/-f 选项不会向 _automoc 文件添加任何内容,编译器只会抱怨这个文件,而不是 @ 987654322@文件?
    【解决方案4】:

    也许更优雅的方法是禁用 mocs_... 文件的预编译头文件。这让你可以保留AUTOMOC:

    append_to_source_file_property(
      ${CMAKE_CURRENT_BINARY_DIR}/<PROJECT_NAME_HERE>_autogen/mocs_compilation.cpp
      COMPILE_FLAGS " /Y- ")
    

    或者,如果您可以/愿意更改预编译头文件的名称和内容,您可以将其添加到其中:

    #ifdef HACK_FOR_TRICKING_MOC_INTO_INCLUDING_ME_IN_THE_MOCS_FILE_DO_NOT_DEFINE
    Q_OBJECT
    #endif
    

    这将欺骗 cmake 将其包含在 mocs_... 文件中。然后,您需要将它放在需要更改名称的顶部,文件首先按数字排序,然后是大写,然后是小写,例如1_precompiled.h 应该可以解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-19
      • 2010-09-13
      • 2020-08-16
      • 1970-01-01
      • 2016-07-20
      相关资源
      最近更新 更多