为什么 Q_OBJECT 会破坏 QDoc?

Why does Q_OBJECT break QDoc?

问题

自从从 Qt 5.10 升级到 Qt 5.11 后,我开始无法为现有项目生成带有 QDoc 的文档。

许多问题之一是文档中缺少函数,尽管源代码中存在相应的注释。

研究

我已设法将问题缩小到包含 Q_OBJECT 宏,如提供的代码示例所示(见下文)。

Qt documentation中确实提到了这个:

If not specified by the Cpp.ignoretokens or Cpp.ignoredirectives variables, non-standard constructs (typically macros) can result in erroneous documentation.

Q_OBJECT 不应该引起问题,因为它写得更远一点:

The Q_OBJECT macro, however, is an exception: QDoc recognizes this particular non-standard construct, so there is no need specifying it using the Cpp.ignoredirectives variable.

无论如何我都会在我的 qdocconf 文件中包含 qt-cpp-defines.qdocconf

我也试过手动添加Q_OBJECT到忽略列表

Cpp.ignoredirectives += Q_OBJECT

但结果是一样的

我在 Windows 10 和 Ubuntu 17 下遇到了描述的问题。Under Windows 7 I cannot execute qdoc.exe at all

qdocconf 解决此问题的正确配置是什么?

最小示例

为了快速复制(在真实情况下,声明和实现是分开的,并添加了适当的注释),请考虑以下设置:

Foo.h

#include <QObject>

class Foo : public QObject
{
//  Q_OBJECT // <-- uncomment this to break QDoc
public:
    Foo() {}

    void boo() {}

protected:
    void moo() {}
};

Foo.cpp

#include "Foo.h"

/*!
    \class Foo
 */

test.qdocconf

include($QT_INSTALL_DOCS/global/compat.qdocconf)
include($QT_INSTALL_DOCS/global/fileextensions.qdocconf)
include($QT_INSTALL_DOCS/global/qt-cpp-defines.qdocconf)
include($QT_INSTALL_DOCS/global/macros.qdocconf)

# Uncoment this for a test
# Cpp.ignoredirectives += Q_OBJECT

outputdir   = html
headerdirs  = .
sourcedirs  = .
exampledirs = .
imagedirs   = ./images

结果

执行 qdoc.exe test.qdocconf 我或多或少得到以下信息:

  • Foo

Contents

  • Public Functions
  • Protected Functions
  • Detailed Description

Foo Class

  • List of all members, including inherited members

Public Functions

Foo()

void boo()

Protected Functions

void moo()

Detailed Description

Member Function Documentation

Foo::Foo()

Default constructs an instance of Foo.

void Foo::boo()

[protected] void Foo::moo()

取消注释 Q_OBJECT 宏和 运行 qdoc.exe 再次产生以下结果:

  • Foo

Contents

  • Detailed Description

Foo Class

Detailed Description

重要提示: Foomooboo 已消失。

我想到的唯一解决方案是将以下预处理器指令添加到 Q_OBJECT 宏中:

#ifndef Q_QDOC
    Q_OBJECT
#endif //Q_QDOC

Q_QDOC 在包含的 qt-cpp-defines.qdocconf 中定义,因此 QDoc 跳过宏,但它未在构建系统中定义,代码照常编译。

我知道这个问题已经有几年了,但我想 post 为找到这个问题的未来搜索者提供一个答案。我的 .cpp 文件中的 Q_OBJECT 和 Q_INVOKABLE 宏都遇到了这个问题。

解决方案是在您的 .qdocconf 文件中使用未记录的命令,includepaths,或者在您 运行 qdoc 时将 -I 参数传递给您的命令.

我只会展示我如何使用我的 config.qdocconf 文件

...
# undocumented feature that simulates passing -I parameters to the command line
includepaths = . \
           .. \
           $QT_INSTALL_HEADERS \
           $QT_INSTALL_HEADERS/QtCore \
           $QT_INSTALL_HEADERS/QtGui \
           $QT_INSTALL_HEADERS/QtQuick \
           $QT_INSTALL_DOCS
...

如果需要,您也可以使用绝对路径代替 $QT_INSTALL_HEADERS

查看这些特殊变量指向何处的简单方法是 运行 qmake -query(如果您的 qmake 命令需要,请使用您的 qt 安装 bin 的绝对路径)

编辑:对我来说,$QT_INSTALL_HEADERS = C:/Qt/5.12.9/msvc2017_64/include

编辑 2:确保您的系统上安装了 clang(通过 chocolately, homebrew, apt, or others) and if on windows that you run set LLVM_INSTALL_DIR=C:\Program Files\LLVM before you run qdoc - Instructions here: Installing Clang for QDoc