qmakesourcecode解讀-創(chuàng)新互聯(lián)

qmake的主要功能執(zhí)行入口在main.cpp中的runQMake(int argc, char **argv)中。其主要框架如下:

創(chuàng)新互聯(lián)建站長(zhǎng)期為超過(guò)千家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為安仁企業(yè)提供專業(yè)的成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì),安仁網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。
runQMake(int argc, char **argv){
    QMakeVfs vfs;   //初始化qmake的文件系統(tǒng)。virtual file system。vfs會(huì)為每個(gè)文件賦予一個(gè)id,并提供根據(jù)id進(jìn)行操作的函數(shù)。
    Option::vfs = &vfs;    
    QMakeGlobals globals;
    Option::globals = &globals;  globalst提供配置查詢環(huán)境參數(shù)和操作環(huán)境變量相關(guān)的一些函數(shù)。
    .......
    Option::init(argc, argv); //初始化參數(shù)
    .....
    QMakeProperty prop; //初始化property。構(gòu)造函數(shù)中調(diào)用QMakeProperty 的reload函數(shù)。
    ....
    QMakeParser parser(&proFileCache, &vfs, &Option::evalHandler);//創(chuàng)建parser對(duì)象,parser的主要作用是將腳本代碼轉(zhuǎn)換成ProToken類型的數(shù)據(jù),并存放到Profile對(duì)象中的m_proitems中。
    Option::parser = &parser;
    ......
    QMakeProject project;//創(chuàng)建qmake工程,構(gòu)造函數(shù)參數(shù)會(huì)使用到option::parser,并賦予成員變量其m_parser,結(jié)構(gòu)中的成員最終用于輔助生成makefile
    //QMakeProject::QMakeProject(): QMakeEvaluator(Option::globals, Option::parser, Option::vfs, &Option::evalHandler){}  
    .......
    project.read(fn)  //加載和解析(詞法語(yǔ)法語(yǔ)義)配置文件(.prl、pri、.conf、.prf),解析工程pro文件
    ......
    MetaMakefileGenerator *mkfile = MetaMakefileGenerator::createMetaGenerator(&project,         QString(), false, &success); //創(chuàng)建makefile對(duì)象向,內(nèi)部通過(guò)生成SubdirsMetaMakefileGenerator或BuildsMetaMakefileGenerator對(duì)象,初始化并返回。
    .....
    mkfile->write() //生成Makefile.Debug、Makefile.Release、Makefile三個(gè)文件。
}

QMakeProject是整體的架構(gòu),他繼承與QMakeEvaluator,用于描述一個(gè)qt工程,除了完成處理語(yǔ)法和語(yǔ)義分析的QMakeEvaluator的功能,還會(huì)做一些工程相關(guān)的處理(比如路徑、緩存文件)。一個(gè)QMakeProject對(duì)象含有一個(gè)用于處理詞法分析的QMakeParser對(duì)象成員。QMakeProject做完解析后,作為參數(shù)傳入MetaMakefileGenerator對(duì)象中,生成makefile文件。

解析從QMakeProject的read函數(shù)開(kāi)始,內(nèi)部會(huì)調(diào)用QMakeEvaluator::evaluateFile()。開(kāi)始進(jìn)行詞法和語(yǔ)法分析。

詞法分析

QMakeParser對(duì)象進(jìn)行語(yǔ)法分析。QMakeParser主要作用是將qmake language語(yǔ)法的代碼進(jìn)行標(biāo)記化(tokenized),將原始代碼全部解析成ProToken類型的數(shù)據(jù),解析內(nèi)容放到Profile對(duì)象的m_proItems成員中。主要操作在QMakeParser::read中,read的調(diào)用堆棧如下:

//E:\workspace\QtWork\qmake\library\qmakeevaluator.cpp
evaluateFile是執(zhí)行腳本文件的入口函數(shù)
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFile(
        const QString &fileName, QMakeHandler::EvalFileType type, LoadFlags flags)
{
    QMakeParser::ParseFlags pflags = QMakeParser::ParseUseCache;
    if (!(flags & LoadSilent))
        pflags |= QMakeParser::ParseReportMissing;
    if (ProFile *pro = m_parser->parsedProFile(fileName, pflags)) {
        ProStringList &tiif = m_valuemapStack.first()[ProKey("QMAKE_VISIT_FILES")];
        ProString tifn(fileName);
        if (!tiif.contains(tifn))
            tiif<< tifn;
        m_locationStack.push(m_current);
        VisitReturn ok = visitProFile(pro, type, flags);
        m_current = m_locationStack.pop();
        pro->deref();
        if (ok == ReturnTrue && !(flags & LoadHidden)) {
            ProStringList &iif = m_valuemapStack.first()[ProKey("QMAKE_INTERNAL_INCLUDED_FILES")];
            ProString ifn(fileName);
            if (!iif.contains(ifn))
                iif<< ifn;
        }
        return ok;
    } else {
        debugMsgInternal(0, "failed evaluateing file %s,parse error", qPrintable(fileName));
        return ReturnFalse;
    }
}

--------------------------

parsedProFile作用是判斷文件是否已經(jīng)被解析,未解析會(huì)調(diào)用readFile將文件內(nèi)容讀取到內(nèi)存中,存放到content變量中,然后調(diào)用parsedProBlock解析讀取到的代碼塊。
ProFile *parsedProFile(const QString &fileName, ParseFlags flags) 

parsedProBlock創(chuàng)建profile對(duì)象,對(duì)具體的代碼塊進(jìn)行解析,然后返回profile對(duì)象
ProFile *parsedProBlock(const QStringRef &contents, int id, const QString &name, int line, SubGrammar grammar)
{
    ProFile *pro = new ProFile(id, name);
    read(pro, contents, line, grammar);
    return pro;
}

parsedProBlock對(duì)具體的代碼塊進(jìn)行解析,可以是一整個(gè)文件的代碼,也可以是eval中傳入的小片代碼。
然后返回profile對(duì)象。詞法分析階段會(huì)進(jìn)行字符轉(zhuǎn)義操作,和預(yù)處理操作。
void QMakeParser::read(ProFile *pro, const QStringRef &in, int line, SubGrammar grammar){.....}

字符轉(zhuǎn)義和部分特殊變量的預(yù)處理在這個(gè)階段進(jìn)行。引號(hào)是否缺乏以及括號(hào)是否缺乏會(huì)在這個(gè)階段得出結(jié)果。

語(yǔ)法語(yǔ)義分析

對(duì)腳本文件的語(yǔ)法和語(yǔ)義分析用QMakeProject中的成員QMakeEvaluator對(duì)象進(jìn)行處理,一個(gè)project對(duì)象只有一個(gè)QMakeEvaluator成員。在evaluateFile函數(shù)中,經(jīng)過(guò)QMakeParser的解析出來(lái)的Profile傳遞給QMakeEaluator->visitprofile,開(kāi)始對(duì)內(nèi)容進(jìn)行語(yǔ)法和語(yǔ)義分析。主要操作在visitProBlock中,調(diào)用堆棧如下。

E:\workspace\QtWork\qmake\library\qmakeevaluator.cpp
visitProfile的作用是在處理工程文件的時(shí)候預(yù)先加載背后的配置文件,以及處理不同時(shí)態(tài)(state)的命令行命令。
同時(shí)維護(hù)一個(gè)m_profileStack棧,用于存放parsed的ProFile。
QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(ProFile *pro, QMakeHandler::EvalFileType type, LoadFlags flags){}


這個(gè)visitProBlock調(diào)用下面的visitProBlock
QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(ProFile *pro, const ushort *tokPtr)
{
    m_current.pro = pro;
    m_current.line = 0;
    return visitProBlock(tokPtr);
}

這個(gè)visitProBlock是進(jìn)行詞法和語(yǔ)法分析的主要邏輯。所有變量存入到m_valuemapStack中,這是一個(gè)棧和鏈表的功能兼有的數(shù)據(jù)結(jié)構(gòu)類型的成員。
QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(const ushort *tokPtr)
QMakeEvaluator的幾個(gè)重要數(shù)據(jù)成員
typedef QHashProValueMap;

class ProValueMapStack : public QLinkedList{}

struct ProFunctionDefs {
    QHashtestFunctions;
    QHashreplaceFunctions;
};

class QMakeEvaluator{
    QStackm_profileStack; // Includes only
    ProValueMapStack m_valuemapStack;
    ProFunctionDefs m_functionDefs;
    QStackm_locationStack;
}

QMakeEvaluator::m_valuemapStack:是存放變量的鍵值的數(shù)據(jù)成員,他的類型如下,兼有鏈表和棧功能操作的數(shù)據(jù)結(jié)構(gòu)類型的變量,元素類型為ProValueMap類型。ProValueMap是QHash類型。QMakeEvaluator初始化時(shí)會(huì)往其中push一個(gè)ProValueMap對(duì)象,這個(gè)對(duì)象存放全局的變量和值鍵值對(duì)。
一個(gè)ProValueMap中存放的是一個(gè)作用域內(nèi)的所有變量和值的鍵值對(duì)。有子作用域時(shí),會(huì)創(chuàng)建一個(gè)新的ProValueMap存放該域內(nèi)的變量名和值。qmake只有兩種作用于,一個(gè)是全局的,一個(gè)是函數(shù)內(nèi)的。?(qmake language腳本語(yǔ)言的作用域與其他的語(yǔ)言的作用域有點(diǎn)差異,可以參考:qmake language)
QMakeEvaluator初始化時(shí)創(chuàng)建一個(gè)ProValueMap對(duì)象,用于存放全局變量和其值的鍵值對(duì);每次調(diào)用自定義函數(shù)的時(shí)候會(huì)創(chuàng)建一個(gè)ProValueMap對(duì)象,存放該函數(shù)內(nèi)的局部變量和鍵值對(duì)。如果函數(shù)內(nèi)有調(diào)用的嵌套,會(huì)繼續(xù)為嵌套的函數(shù)創(chuàng)建ProValueMap對(duì)象,新創(chuàng)建的ProValueMap會(huì)push到m_valuemapStack中,函數(shù)調(diào)用結(jié)束后再?gòu)钠渲袆h除(相應(yīng)代碼邏輯在QMakeEvaluator::evaluateFunction中)。函數(shù)內(nèi)訪問(wèn)某個(gè)變量會(huì)先從該函數(shù)的ProValueMap中查找,未找到會(huì)到m_valuemapStack的下一層中尋找,直到找到變量或者遍歷完所有變量名。
ProKey 存放變量名,ProStringList存放變量的值(qmake language中只有字符串組的數(shù)據(jù)類型)。
下面是qmake中訪問(wèn)一個(gè)變量的函數(shù):

//E:\workspace\QtWork\qmake\library\qmakeevaluator.cpp
ProStringList QMakeEvaluator::values(const ProKey &variableName) const
{
    ProValueMapStack::ConstIterator vmi = m_valuemapStack.constEnd();
    for (bool first = true; ; first = false) {
        --vmi;
        ProValueMap::ConstIterator it = (*vmi).constFind(variableName);
        if (it != (*vmi).constEnd()) {
            if (it->constBegin() == statics.fakeValue.constBegin())
                break;
            return *it;
        }
        if (vmi == m_valuemapStack.constBegin())
            break;
        if (first && isFunctParam(variableName))
            break;
    }
    return ProStringList();
}

QMakeEvaluator::m_functionDefs :存放自定義的replace函數(shù)和test函數(shù)。
QStackm_locationStack:與m_valuemapStack同步使用,用于存放當(dāng)前解析位置,方便進(jìn)入子作用域退出后找到解析位置。
statics.functions:存放內(nèi)置的test函數(shù)。
statics.expands:存放內(nèi)置的replace函數(shù)。

m_functionDefs.testFunctions類型是QHash,是函數(shù)名與函數(shù)定義的鍵值對(duì)。ProFunctionDef中也有一個(gè)ProFile數(shù)據(jù)成員對(duì)象,用于存放函數(shù)定義的Tokens內(nèi)容,在解析函數(shù)的時(shí)候會(huì)將這個(gè)Profile取出來(lái)進(jìn)行解析。

腳本中調(diào)用內(nèi)建函數(shù)cache()函數(shù)時(shí)qmake中的調(diào)用堆棧

腳本中調(diào)用cache函數(shù)的調(diào)用堆棧
腳本中調(diào)用自定義的replace函數(shù)的調(diào)用堆棧

qmake訪問(wèn)replace函數(shù)和test函數(shù)邏輯。

QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateExpandFunction( const ProKey &func, const ushort *&tokPtr, ProStringList *ret)  訪問(wèn)replace函數(shù)
{
    auto isbuildinE = statics.expands.constFind(func);
    if(isbuildinE) evaluateBuiltinExpand(*adef, func, args, *ret);   //expandVariableReferences(tokPtr, 5, &args, true);

    QHash::ConstIterator it =m_functionDefs.replaceFunctions.constFind(func);
    if(it) evaluateFunction(*it, args, ret);  //prepareFunctionArgs(tokPtr, &args);
}

QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(const ProKey &func, const ushort *&tokPtr)  訪問(wèn)test函數(shù)
{
    auto isbuildinE = statics.functions.constFind(func);
    if(isbuildinT) evaluateBuiltinConditional(*adef, func, args);

    QHash::ConstIterator it =m_functionDefs.testFunctions.constFind(func);
    if(it)  evaluateBoolFunction(*it, args, func);
}
生成makefile

qmake 默認(rèn)生成三個(gè)makefile相關(guān)的文件BuildsMetaMakefileGenerator::init()函數(shù)中會(huì)創(chuàng)建debug和release的MakefileGenerator對(duì)象,分別用于生成Makefile.Debug、Makefile.Release文件,BuildsMetaMakefileGenerator對(duì)象本身則生成Makefile文件。
具體可參考:如何通過(guò)pro文件向moc傳入?yún)?shù)--------qmake組裝makefile中的moc_*.cpp生成規(guī)則

qmake組裝moc_*.cpp生成規(guī)則調(diào)用堆棧

編譯使用到的宏開(kāi)關(guān)

QT_CONFIG(process)
PROEVALUATOR_FULL?
QT_BOOTSTRAPPED?
QT_BUILD_QMAKE?
QT_NO_FOREACH?
PARSER_DEBUG

qmake 與 配置文件_丘上人的博客-博客

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

名稱欄目:qmakesourcecode解讀-創(chuàng)新互聯(lián)
URL分享:http://bm7419.com/article10/ceohdo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化網(wǎng)站制作、網(wǎng)站營(yíng)銷網(wǎng)站設(shè)計(jì)公司、外貿(mào)建站定制網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)