qtcreator编译qt程序是如何调用moc的,如何通过pro文件向moc传入参数

目录

一、qt程序编译时调用moc

二、qmake组装makefile中的moc_*.cpp生成规则

三、通过qt工程文件向moc传入参数


一、qt程序编译时调用moc

qtcreator对qt程序的编译过程是先“qmake” ,然后“构建(等价于make)”。

qtcreator右键点击项目 出现的 “执行qmake”和“构建” 两个选项其实就是运行 项目-》build->构建步骤 中的“qmake”和“make”步骤所对应的命令行命令。


从项目->build->构建步骤可以看出,构建过程中先用qmake生成makefile,构建(make)过程用jom和前面产生的makefile生成目标程序的exe。jom按makefile规则的运行过程中根据依赖会先调用moc.exe生成moc_*.cpp文件,然后是按正常C++编译过程进行C++预编译(宏替换),再然后是C++编译。也就是说moc生成moc_*.cpp代码是在C++编译器进行预编译之前!

jom具体如何调用moc的过程请参考下面链接中的 构建步骤 部分:qt 工程构建过程 默认构建路径设置 通过Dos窗口 命令行 编译qt工程_丘上人的博客-CSDN博客 

二、qmake组装makefile中的moc_*.cpp生成规则

qmake 组装makefile中的moc_*.cpp生成规则的调用堆栈如下:

qmake组装moc_*.cpp生成规则调用堆栈
//E:\workspace\QtWork\qmake\generators\makefile.cpp
QString
MakefileGenerator::replaceExtraCompilerVariables(
        const QString &orig_var, const QStringList &in, const QStringList &out, ReplaceFor forShell)
{
......
 if(val.isEmpty() && var.startsWith(QLatin1String("QMAKE_FUNC_"))) {
            const ProKey funcname = var.mid(11).toKey();
            val += project->expand(funcname, QList<ProStringList>() << ProStringList(in) << ProStringList(out));
        }
......

-----------------------------------------------
//E:\workspace\QtWork\qmake\project.cpp
QStringList QMakeProject::expand(const ProKey &func, const QList<ProStringList> &args)
{
......
    QHash<ProKey, ProFunctionDef>::ConstIterator it =
            m_functionDefs.replaceFunctions.constFind(func);
    if (it != m_functionDefs.replaceFunctions.constEnd()) {
        ProStringList ret;
        if (evaluateFunction(*it, args, &ret) == QMakeProject::ReturnError)
            exit(3);
        return ret.toQStringList();
    }
....
}
.....

-------------------------
//E:\workspace\QtWork\qmake\library\qmakeevaluator.cpp
......
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFunction(
        const ProFunctionDef &func, const QList<ProStringList> &argumentsList, ProStringList *ret)
{
    VisitReturn vr;

    if (m_valuemapStack.count() >= 100) {
        evalError(fL1S("Ran into infinite recursion (depth > 100)."));
        vr = ReturnFalse;
    } else {
        m_valuemapStack.push(ProValueMap());
        m_locationStack.push(m_current);

        ProStringList args;
        for (int i = 0; i < argumentsList.count(); ++i) {
            args += argumentsList[i];
            m_valuemapStack.top()[ProKey(QString::number(i+1))] = argumentsList[i];
        }
        m_valuemapStack.top()[statics.strARGS] = args;
        m_valuemapStack.top()[statics.strARGC] = ProStringList(ProString(QString::number(argumentsList.count())));
        vr = visitProBlock(func.pro(), func.tokPtr());
        if (vr == ReturnReturn)
            vr = ReturnTrue;
        if (vr == ReturnTrue)
            *ret = m_returnValue;
        m_returnValue.clear();

        m_current = m_locationStack.pop();
        m_valuemapStack.pop();
    }
    return vr;
}
.......

调用的部分代码如上:replaceExtraCompilerVariables()中传入expand函数的变量funcname值为:mocCmdBase,expand内部调用evaluateFunction,该函数作用是调用 用qmake language写的replace函数。也就是说断点处的目的是调用qmake language写的函数mocCmdBase()。

找到配置文件中的mocCmdBase()函数代码如下:

//QtInstallDir\Qt5.12.0\5.12.0\msvc2015_64\mkspecs\features\moc.prf
.......
defineReplace(mocCmdBase) {
    !isEmpty(WIN_INCLUDETEMP) {
        incvar = @$$shell_quote($$WIN_INCLUDETEMP)
    } else {
        incvar =
        for (inc, MOC_INCLUDEPATH): \
            incvar += -I$$shell_quote($$inc)
        incvar += $$QMAKE_FRAMEWORKPATH_FLAGS
    }

    RET = $$QMAKE_MOC $(DEFINES)
    msvc: RET += --compiler-flavor=msvc

    isEmpty(MOC_PREDEF_FILE): RET += $$join(QMAKE_COMPILER_DEFINES, " -D", -D)
    else: RET += --include $$shell_quote($$absolute_path($$moc_predefs.output, $$OUT_PWD))

    RET += $$incvar $$QMAKE_MOC_OPTIONS
    return($$RET)
}
.......

可以将上面的mocCmdBase中的RET与下面具体的moc_*.cpp生成规则做一下对照,QMAKE_MOC_OPTIONS是在某个prf或pri或conf配置文件中用qmake language预定义全局变量,表示传递给moc的参数,在pro中可以使用: 

	D:\Qt\Qt5.12.0\5.12.0\msvc2015_64\bin\moc.exe $(DEFINES) --compiler-flavor=msvc --include E:/workspace/QtWork/build-plugandpaint-Desktop_Qt_5_12_0_MSVC2015_64bit-Debug/plugins/extrafilters/debug/moc_predefs.h -ID:/Qt/Qt5.12.0/5.12.0/msvc2015_64/mkspecs/win32-msvc -IE:/workspace/QtWork/plugandpaint/plugins/extrafilters -IE:/workspace/QtWork/plugandpaint/app -ID:/Qt/Qt5.12.0/5.12.0/msvc2015_64/include -ID:/Qt/Qt5.12.0/5.12.0/msvc2015_64/include/QtWidgets -ID:/Qt/Qt5.12.0/5.12.0/msvc2015_64/include/QtGui -ID:/Qt/Qt5.12.0/5.12.0/msvc2015_64/include/QtANGLE -ID:/Qt/Qt5.12.0/5.12.0/msvc2015_64/include/QtCore -I. -I"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6\include\um" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\shared" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\um" -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\winrt" -M yy=ttet ..\..\..\plugandpaint\plugins\extrafilters\extrafiltersplugin.h -o debug\moc_extrafiltersplugin.cpp

三、通过qt工程(pro)文件向moc传入参数

知道了moc的调用和组装规则,及相应逻辑,通过pro文件对moc传入参数就变得很显而易见了
直接在pro文件中加入如下代码:

QMAKE_MOC_OPTIONS = "-M yy=ttet"
通过pro文件对moc传递参数
pro文件设置moc参数后会写入到生成的makefile.debug中

  最终生成的qt_pluginMetaData[]会变成如下:

//moc_*.cpp
QT_PLUGIN_METADATA_SECTION
static constexpr unsigned char qt_pluginMetaData[] = {
    'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!',
    // metadata version, Qt version, architectural requirements
    0, QT_VERSION_MAJOR, QT_VERSION_MINOR, qPluginArchRequirements(),
    0xbf, 
    // "IID"
    0x02,  0x78,  0x1c,  'E',  'x',  'a',  'm',  'p', 
    'l',  'e',  's',  '.',  'P',  'l',  'u',  'g', 
    'i',  'n',  '.',  'C',  'a',  'l',  'I',  'n', 
    't',  'e',  'r',  'f',  'a',  'c',  'e', 
    // "className"
    0x03,  0x69,  'C',  'a',  'l',  'P',  'l',  'u', 
    'g',  'i',  'n', 
    // "MetaData"
    0x04,  0xa2,  0x62,  'i',  'd',  0x78,  0x1c,  'E', 
    'x',  'a',  'm',  'p',  'l',  'e',  's',  '.', 
    'P',  'l',  'u',  'g',  'i',  'n',  '.',  'C', 
    'a',  'l',  'I',  'n',  't',  'e',  'r',  'f', 
    'a',  'c',  'e',  0x64,  'n',  'a',  'm',  'e', 
    0x69,  'C',  'a',  'l',  'P',  'l',  'u',  'g', 
    'i',  'n', 
    // command-line "yy"
    0x62,  'y',  'y',  0x81,  0x64,  't',  't',  'e', 
    't', 
    0xff, 
};
QT_MOC_EXPORT_PLUGIN(CalPlugin, CalPlugin)

另外还可以通过qt的关键字Q_PLUGIN_METADATA,将json文件传递meta内容到qt_pluginMetaData中参考如下:

Q_PLUGIN_METADATA Q_INTERFACE Q_DECLARE_INTERFACE qt_pluginMetaData_丘上人的博客-CSDN博客_q_plugin_metadata

moc所支持的参数

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值