qmake的主要功能執(zhí)行入口在main.cpp中的runQMake(int argc, char **argv)中。其主要框架如下:
創(chuàng)新互聯建站長期為超過千家客戶提供的網站建設服務,團隊從業(yè)經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯網生態(tài)環(huán)境。為安仁企業(yè)提供專業(yè)的成都網站制作、網站設計,安仁網站改版等技術服務。擁有十年豐富建站經驗和眾多成功案例,為您定制開發(fā)。runQMake(int argc, char **argv){
QMakeVfs vfs; //初始化qmake的文件系統(tǒng)。virtual file system。vfs會為每個文件賦予一個id,并提供根據id進行操作的函數。
Option::vfs = &vfs;
QMakeGlobals globals;
Option::globals = &globals; globalst提供配置查詢環(huán)境參數和操作環(huán)境變量相關的一些函數。
.......
Option::init(argc, argv); //初始化參數
.....
QMakeProperty prop; //初始化property。構造函數中調用QMakeProperty 的reload函數。
....
QMakeParser parser(&proFileCache, &vfs, &Option::evalHandler);//創(chuàng)建parser對象,parser的主要作用是將腳本代碼轉換成ProToken類型的數據,并存放到Profile對象中的m_proitems中。
Option::parser = &parser;
......
QMakeProject project;//創(chuàng)建qmake工程,構造函數參數會使用到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對象向,內部通過生成SubdirsMetaMakefileGenerator或BuildsMetaMakefileGenerator對象,初始化并返回。
.....
mkfile->write() //生成Makefile.Debug、Makefile.Release、Makefile三個文件。
}
QMakeProject是整體的架構,他繼承與QMakeEvaluator,用于描述一個qt工程,除了完成處理語法和語義分析的QMakeEvaluator的功能,還會做一些工程相關的處理(比如路徑、緩存文件)。一個QMakeProject對象含有一個用于處理詞法分析的QMakeParser對象成員。QMakeProject做完解析后,作為參數傳入MetaMakefileGenerator對象中,生成makefile文件。
解析從QMakeProject的read函數開始,內部會調用QMakeEvaluator::evaluateFile()。開始進行詞法和語法分析。
詞法分析QMakeParser對象進行語法分析。QMakeParser主要作用是將qmake language語法的代碼進行標記化(tokenized),將原始代碼全部解析成ProToken類型的數據,解析內容放到Profile對象的m_proItems成員中。主要操作在QMakeParser::read中,read的調用堆棧如下:
//E:\workspace\QtWork\qmake\library\qmakeevaluator.cpp
evaluateFile是執(zhí)行腳本文件的入口函數
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作用是判斷文件是否已經被解析,未解析會調用readFile將文件內容讀取到內存中,存放到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函數中,經過QMakeParser的解析出來的Profile傳遞給QMakeEaluator->visitprofile,開始對內容進行語法和語義分析。主要操作在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中,這是一個棧和鏈表的功能兼有的數據結構類型的成員。
QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(const ushort *tokPtr)
QMakeEvaluator的幾個重要數據成員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:是存放變量的鍵值的數據成員,他的類型如下,兼有鏈表和棧功能操作的數據結構類型的變量,元素類型為ProValueMap類型。ProValueMap是QHash
一個ProValueMap中存放的是一個作用域內的所有變量和值的鍵值對。有子作用域時,會創(chuàng)建一個新的ProValueMap存放該域內的變量名和值。qmake只有兩種作用于,一個是全局的,一個是函數內的。?(qmake language腳本語言的作用域與其他的語言的作用域有點差異,可以參考:qmake language)
QMakeEvaluator初始化時創(chuàng)建一個ProValueMap對象,用于存放全局變量和其值的鍵值對;每次調用自定義函數的時候會創(chuàng)建一個ProValueMap對象,存放該函數內的局部變量和鍵值對。如果函數內有調用的嵌套,會繼續(xù)為嵌套的函數創(chuàng)建ProValueMap對象,新創(chuàng)建的ProValueMap會push到m_valuemapStack中,函數調用結束后再從其中刪除(相應代碼邏輯在QMakeEvaluator::evaluateFunction中)。函數內訪問某個變量會先從該函數的ProValueMap中查找,未找到會到m_valuemapStack的下一層中尋找,直到找到變量或者遍歷完所有變量名。
ProKey 存放變量名,ProStringList存放變量的值(qmake language中只有字符串組的數據類型)。
下面是qmake中訪問一個變量的函數:
//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函數和test函數。
QStack
statics.functions:存放內置的test函數。
statics.expands:存放內置的replace函數。
m_functionDefs.testFunctions類型是QHash
腳本中調用內建函數cache()函數時qmake中的調用堆棧
qmake訪問replace函數和test函數邏輯。
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateExpandFunction( const ProKey &func, const ushort *&tokPtr, ProStringList *ret) 訪問replace函數
{
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函數
{
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()函數中會創(chuàng)建debug和release的MakefileGenerator對象,分別用于生成Makefile.Debug、Makefile.Release文件,BuildsMetaMakefileGenerator對象本身則生成Makefile文件。
具體可參考:如何通過pro文件向moc傳入參數--------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)新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧