低版本Qt moc在namespace处报错的问题分析与解决

由于不可描述的原因,需要在XP下强行编译一个标注了兼容性C++17 & Qt 5.9的程序。XP的平台限制很大,目前来看,最靠谱的技术路线是修改项目源码使其兼容Qt 5.5

其他折腾点的背景信息在此:Windows XP下编译C++14/17程序手记,本文不再详述。编译Qt 5.5时,由一个选项当时就引起了我的注意,叫是否启用C++11。按我的想法,C++11是否启用难道不是我的编译环境决定的吗?不过没有深究,开启了事。

然后按部就班CMake,make,不带GUI的部分顺利通过编译,然后GUI部分在moc阶段出事了。

qt中moc的作用

可恨的是moc.exe只报错误,不解释错误原因,连个错误类型提示都没有,只有行号和关键词。为了寻找问题共性,我仿照出错的命令手写了其他几条命令分别处理不同的文件,最后发现出错点总是在某个文件的namespace xx::oo{处报xx错误。按照这个思路搜索,发现了一条有意思的信息:

[Qt MOC error for namespace like FOO::BAR](https://stackoverflow.com/questions/22305609/qt-moc-error-for-namespace-like-foobar)

一个人说他把namespace xx::oo{改成namespace xx{ namespace oo{就可以避免问题,这moc是出啥毛病了?另一人说你才出毛病了,namespace本来就不能那么写。听起来像是一个不标准扩展问题,类似以前的#program once这种。针对这个继续搜索,发现了CppReference/namespace的一条信息,人家明确指出:

CppReference

显然,这是一个C++17引入的新的写法。我可以用gcc 7.2去编译Qt 5.5的库文件和整个工程,前半部分都没错。但Qt 5.5中附带的moc.exe毕竟是来自于C++17发布以前的代码,不会因为它是被gcc 7.2编译出来的就神奇地认识C++17的写法了。

这就比较麻烦了,我要编译的整个工程几乎每个文件都有namespace xx::oo{这种写法,改下去岂不是累死人。多亏图灵保佑,我搜索时还恰好看到了这个帖子:

QMake moc files confused by namespaces

此贴跟我的问题实质上毫无关系,只是恰好具有一样的关键词。文中提到,使用以下宏包装语句,可以使得这部分语句对于moc隐身:

#ifndef Q_MOC_RUN
...
#endif

更加幸运的是,我要编译的这个工程虽然挺大,但GUI部分与计算部分做了严格区分。计算部分没有任何一处包括moc所关注的Q_OBJECT。因此,我可以把所有#include了计算代码的段落用上面的宏包起来,不要让moc顺着#include进去瞎逛。至于GUI部分的namespace xx::oo{什么的,总共只有十来个文件,手动改一改还可以接受。改完编译,mocuic再到rcc都顺利进行,问题解决!

  • 最后更改: 2019/05/29 14:57