低版本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
阶段出事了。
可恨的是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的一条信息,人家明确指出:
显然,这是一个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{
什么的,总共只有十来个文件,手动改一改还可以接受。改完编译,moc
,uic
再到rcc
都顺利进行,问题解决!