【问题标题】:How do you get cmake to add compiler definitions only for automoc files如何让 cmake 仅为 automoc 文件添加编译器定义
【发布时间】:2016-07-20 07:22:11
【问题描述】:

我们的项目使用了非常严格的警告集,但 Qt5 生成的 moc 文件生成的代码违反了这些警告。我们显然可以全局关闭警告,但我只想禁止 automoc 文件的警告。

例如:

In file included from /Users/stebro/client/build/NotificationServer/Notification_automoc.cpp:2:
/Users/stebro/client/build/NotificationServer/moc_NotificationServer.cpp:100:18: error: dereference of type '_t *' (aka 'void (carbonite::NotificationServer::**)(const QByteArray &, const QString, const QVariant)') that was reinterpret_cast from type 'void **' has undefined behavior [-Werror,-Wundefined-reinterpret-cast]
            if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&NotificationServer::notificationQueued)) {
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

以下不起作用:

set_property(
  DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
  PROPERTY COMPILE_DEFINITIONS -Wundefined-reinterpret-cast
  )

cmake 抱怨:

  set_property DIRECTORY scope provided but requested directory was not
  found.  This could be because the directory argument was invalid or, it is
  valid but has not been processed yet.

我不能使用 set_property(FILE ...) 因为我没有在构建 makefile 时自动执行的文件的完整列表(所以大概 GLOBing 也不起作用)。我不想手动维护将由构建生成的所有 moc 文件的列表。

【问题讨论】:

  • 自从你问了这个问题后,你找到解决方法了吗?我目前遇到了同样的问题。
  • @Corristo:我们已经转移到 Qt 5.7 并且不再遇到这个问题(也许 Qt 的 automoc 清理了他们的行为)。如果您在 clang/OSX 环境中运行,我知道您可以通过在编译行中使用 -isystem 而不是 -I 来获得抑制“系统”标头的警告。可以将 ${CMAKE_CURRENT_BINARY_DIR} 指定为系统路径。
  • @Corristo:实际上,我说错了(我检查了我最初提交的日期——这条评论是针对我当前的项目,而不是我以前的)。不幸的是,我只是通过对所有代码进行全局抑制来解决 Qt 的不良行为,从而解决了这个问题。请参阅下面的答案。

标签: qt cmake moc automoc


【解决方案1】:

有点晚了,但我找到了一个可行的解决方案(CMake 3.16)。

首先,Automoc 无法生成警告。它是一个预处理器,它接受一个 cpp 文件并生成一个 moc 文件。此操作不会产生编译警告。

在 CMake 中,当您将 AUTOMOC 属性设置为 true 时,CMake 会(至少)做两件事:

  1. 它将您的所有源代码提供给 MOC 以生成 moc 文件(这些 MOC 文件不会添加到您的目标中,我们不关心它们)
  2. 它会创建一个包含所有必要 moc 文件的 mocs_compilation.cpp 文件,将此文件添加到您的目标然后编译它。

只有这第二个操作会产生警告。正是您想要静默的编译步骤。


在我的情况下(CMake 3.16),mocs_compilation 文件是在以下路径中生成的:

${&lt;target_name&gt;_BINARY_DIR}/&lt;target_name&gt;_autogen/mocs_compilation.cpp 一旦您知道该路径,您可以通过仅将编译标志传递给该文件来消除一些警告:

set_source_files_properties("&lt;target_name&gt;_autogen/mocs_compilation.cpp" PROPERTIES COMPILE_FLAGS "-Wno-undefined-reinterpret-cast")

即使将来路径发生变化,CMake 也始终有一个“通用”cpp 文件,其中包含所有其他 MOC 文件。如果你能找到这个文件的路径,这个解决方案就可以了。


在您的情况下(旧 CMake 版本),此文件为 Notification_automoc.cpp,因此以下行应该工作:

set_source_files_properties("Notification_automoc.cpp" PROPERTIES COMPILE_FLAGS "-Wno-undefined-reinterpret-cast")

【讨论】:

  • 这确实会将标志添加到编译器命令行以构建 mocs_compilation.cpp,但它对编译器将输出的警告没有任何影响(至少对于 Visual C++)。仍然会针对各个 moc_...cpp 文件报告警告。是否可以直接将编译器标志添加到这些文件中?
  • @mgr 这很奇怪。 mocs_compilation.cpp 的工作方式是直接包含所有其他 .cpp 文件。它们总是通过 mocs_compilation.cpp 编译。从不直接。你确定你静音了正确的文件吗? (应该是#include "XXXXXXX/moc_xxx.cpp的列表
  • 编译标志被添加到正确的生成文件 mocs_compilation.cpp 中,带有详细选项 ninja 我可以看到该文件的命令行中添加的标志。我什至尝试添加一个无效的编译标志并得到预期的警告(cl:命令行警告 D9002:忽略未知选项......)。如果我将 /wd... 更改为 /we... 它会触发编译错误,因此肯定会应用编译标志。
【解决方案2】:

您可以通过在 moc 命令行上传递“无警告”选项来禁用所有 AUTOMOC 警告。 CMAKE_AUTOMOC_MOC_OPTIONS 初始化AUTOMOC_MOC_OPTIONS,其文档链接如下。

SET(CMAKE_AUTOMOC   ON)
SET(CMAKE_AUTOMOC_MOC_OPTIONS "-nw")

【讨论】:

  • 添加此行不会抑制编译器警告。我不认为 -nw 标志控制编译器警告。从上面的 Qt 链接来看,似乎 -nw 抑制了生成 moc 文件时的警告,而不是编译文件时生成的警告。
  • @SteveBroberg 根本问题是您正在编译和链接具有您想要被警告的警告的文件。为此,除了在编译 automoc.cpp 的项目上取消设置警告或使用不生成警告的 Qt 版本之外,我不确定是否能找到解决方法。也许你可以编写一个脚本来在文件被moc'd之后在文件中生成pragma,但这似乎需要很多努力。
  • 鉴于上述警告的性质,任何版本的 Qt 似乎都不太可能没有此警告,因为它将指向 void* 的指针向下转换为函数指针,这是 Qt 设法做到的调用回调。除了重构他们的整个信号/槽机制之外,我看不出他们如何避免这种情况,除了将编译器特定的编译指示放入代码中以忽略它们。 Qt 标头通常充满了触发 -Weverything 的警告 - 我不得不取消其中的 8 个,但这可以通过标头包装器进行管理 - 这里不是这样。
猜你喜欢
  • 2014-02-23
  • 1970-01-01
  • 1970-01-01
  • 2018-11-16
  • 1970-01-01
  • 2012-10-13
  • 1970-01-01
  • 1970-01-01
  • 2020-03-12
相关资源
最近更新 更多