qmake的主要功能執(zhí)行入口在main.cpp中的runQMake(int argc, char **argv)中。其主要框架如下:
創(chuàng)新互聯(lián)建站長期為超過千家客戶提供的網(wǎng)站建設服務,團隊從業(yè)經(jīng)驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為安仁企業(yè)提供專業(yè)的成都網(wǎng)站制作、網(wǎng)站設計,安仁網(wǎng)站改版等技術服務。擁有十年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。runQMake(int argc, char **argv){
QMakeVfs vfs; //初始化qmake的文件系統(tǒng)。virtual file system。vfs會為每個文件賦予一個id,并提供根據(jù)id進行操作的函數(shù)。
Option::vfs = &vfs;
QMakeGlobals globals;
Option::globals = &globals; globalst提供配置查詢環(huán)境參數(shù)和操作環(huán)境變量相關的一些函數(shù)。
.......
Option::init(argc, argv); //初始化參數(shù)
.....
QMakeProperty prop; //初始化property。構造函數(shù)中調用QMakeProperty 的reload函數(shù)。
....
QMakeParser parser(&proFileCache, &vfs, &Option::evalHandler);//創(chuàng)建parser對象,parser的主要作用是將腳本代碼轉換成ProToken類型的數(shù)據(jù),并存放到Profile對象中的m_proitems中。
Option::parser = &parser;
......
QMakeProject project;//創(chuàng)建qmake工程,構造函數(shù)參數(shù)會使用到option::parser,并賦予成員變量其m_parser,結構中的成員最終用于輔助生成makefile
//QMakeProject::QMakeProject(): QMakeEvaluator(Option::globals, Option::parser, Option::vfs, &Option::evalHandler){}
.......
project.read(fn) //加載和解析(詞法語法語義)配置文件(.prl、pri、.conf、.prf),解析工程pro文件
......
MetaMakefileGenerator *mkfile = MetaMakefileGenerator::createMetaGenerator(&project, QString(), false, &success); //創(chuàng)建makefile對象向,內(nèi)部通過生成SubdirsMetaMakefileGenerator或BuildsMetaMakefileGenerator對象,初始化并返回。
.....
mkfile->write() //生成Makefile.Debug、Makefile.Release、Makefile三個文件。
}
QMakeProject是整體的架構,他繼承與QMakeEvaluator,用于描述一個qt工程,除了完成處理語法和語義分析的QMakeEvaluator的功能,還會做一些工程相關的處理(比如路徑、緩存文件)。一個QMakeProject對象含有一個用于處理詞法分析的QMakeParser對象成員。QMakeProject做完解析后,作為參數(shù)傳入MetaMakefileGenerator對象中,生成makefile文件。
解析從QMakeProject的read函數(shù)開始,內(nèi)部會調用QMakeEvaluator::evaluateFile()。開始進行詞法和語法分析。
詞法分析QMakeParser對象進行語法分析。QMakeParser主要作用是將qmake language語法的代碼進行標記化(tokenized),將原始代碼全部解析成ProToken類型的數(shù)據(jù),解析內(nèi)容放到Profile對象的m_proItems成員中。主要操作在QMakeParser::read中,read的調用堆棧如下:
//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)被解析,未解析會調用readFile將文件內(nèi)容讀取到內(nèi)存中,存放到content變量中,然后調用parsedProBlock解析讀取到的代碼塊。
ProFile *parsedProFile(const QString &fileName, ParseFlags flags)
parsedProBlock創(chuàng)建profile對象,對具體的代碼塊進行解析,然后返回profile對象
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對具體的代碼塊進行解析,可以是一整個文件的代碼,也可以是eval中傳入的小片代碼。
然后返回profile對象。詞法分析階段會進行字符轉義操作,和預處理操作。
void QMakeParser::read(ProFile *pro, const QStringRef &in, int line, SubGrammar grammar){.....}
字符轉義和部分特殊變量的預處理在這個階段進行。引號是否缺乏以及括號是否缺乏會在這個階段得出結果。
語法語義分析對腳本文件的語法和語義分析用QMakeProject中的成員QMakeEvaluator對象進行處理,一個project對象只有一個QMakeEvaluator成員。在evaluateFile函數(shù)中,經(jīng)過QMakeParser的解析出來的Profile傳遞給QMakeEaluator->visitprofile,開始對內(nèi)容進行語法和語義分析。主要操作在visitProBlock中,調用堆棧如下。
E:\workspace\QtWork\qmake\library\qmakeevaluator.cpp
visitProfile的作用是在處理工程文件的時候預先加載背后的配置文件,以及處理不同時態(tài)(state)的命令行命令。
同時維護一個m_profileStack棧,用于存放parsed的ProFile。
QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(ProFile *pro, QMakeHandler::EvalFileType type, LoadFlags flags){}
這個visitProBlock調用下面的visitProBlock
QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(ProFile *pro, const ushort *tokPtr)
{
m_current.pro = pro;
m_current.line = 0;
return visitProBlock(tokPtr);
}
這個visitProBlock是進行詞法和語法分析的主要邏輯。所有變量存入到m_valuemapStack中,這是一個棧和鏈表的功能兼有的數(shù)據(jù)結構類型的成員。
QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(const ushort *tokPtr)
QMakeEvaluator的幾個重要數(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ù)結構類型的變量,元素類型為ProValueMap類型。ProValueMap是QHash
一個ProValueMap中存放的是一個作用域內(nèi)的所有變量和值的鍵值對。有子作用域時,會創(chuàng)建一個新的ProValueMap存放該域內(nèi)的變量名和值。qmake只有兩種作用于,一個是全局的,一個是函數(shù)內(nèi)的。?(qmake language腳本語言的作用域與其他的語言的作用域有點差異,可以參考:qmake language)
QMakeEvaluator初始化時創(chuàng)建一個ProValueMap對象,用于存放全局變量和其值的鍵值對;每次調用自定義函數(shù)的時候會創(chuàng)建一個ProValueMap對象,存放該函數(shù)內(nèi)的局部變量和鍵值對。如果函數(shù)內(nèi)有調用的嵌套,會繼續(xù)為嵌套的函數(shù)創(chuàng)建ProValueMap對象,新創(chuàng)建的ProValueMap會push到m_valuemapStack中,函數(shù)調用結束后再從其中刪除(相應代碼邏輯在QMakeEvaluator::evaluateFunction中)。函數(shù)內(nèi)訪問某個變量會先從該函數(shù)的ProValueMap中查找,未找到會到m_valuemapStack的下一層中尋找,直到找到變量或者遍歷完所有變量名。
ProKey 存放變量名,ProStringList存放變量的值(qmake language中只有字符串組的數(shù)據(jù)類型)。
下面是qmake中訪問一個變量的函數(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ù)。
QStack
statics.functions:存放內(nèi)置的test函數(shù)。
statics.expands:存放內(nèi)置的replace函數(shù)。
m_functionDefs.testFunctions類型是QHash
腳本中調用內(nèi)建函數(shù)cache()函數(shù)時qmake中的調用堆棧
qmake訪問replace函數(shù)和test函數(shù)邏輯。
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateExpandFunction( const ProKey &func, const ushort *&tokPtr, ProStringList *ret) 訪問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) 訪問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);
}
生成makefileqmake 默認生成三個makefile相關的文件BuildsMetaMakefileGenerator::init()函數(shù)中會創(chuàng)建debug和release的MakefileGenerator對象,分別用于生成Makefile.Debug、Makefile.Release文件,BuildsMetaMakefileGenerator對象本身則生成Makefile文件。
具體可參考:如何通過pro文件向moc傳入?yún)?shù)--------qmake組裝makefile中的moc_*.cpp生成規(guī)則
QT_CONFIG(process)
PROEVALUATOR_FULL?
QT_BOOTSTRAPPED?
QT_BUILD_QMAKE?
QT_NO_FOREACH?
PARSER_DEBUG
qmake 與 配置文件_丘上人的博客-博客
你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
名稱欄目:qmakesourcecode解讀-創(chuàng)新互聯(lián)
URL分享:http://vcdvsql.cn/article10/ceohdo.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、網(wǎng)站制作、網(wǎng)站營銷、網(wǎng)站設計公司、外貿(mào)建站、定制網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容