Qt Creator 源碼學(xué)習(xí)筆記03,大型項(xiàng)目如何管理工程

“
閱讀本文大概需要?6 分鐘
一個項(xiàng)目隨著功能開發(fā)越來越多,項(xiàng)目必然越來越大,工程管理成本也越來越高,后期維護(hù)成本更高。如何更好的組織管理工程,是非常重要的
今天我們來學(xué)習(xí)下??是如何組織管理這么龐大的一個項(xiàng)目工程的
QMake 多工程管理方法
我們知道??采用?
語法進(jìn)行組織管理工程結(jié)構(gòu),想要更好的學(xué)習(xí)管理一個工程需要你了解基本的
語法
在當(dāng)中,一般以
結(jié)尾的文件是某個工程文件,我們只要打開該文件即可打開該文件管理的工程
單工程基本用法
比如我們新建一個工程,那么自動會生成如下結(jié)構(gòu)的工程文件

其中文件內(nèi)容如下所示
該文件描述了這個工程一些基本信息
QT += 表示需要包含哪些模塊
greaterThan 可以判斷 Qt 的一些版本進(jìn)而做一些版本之間差異的事情
TEMPLATE 表示該工程編譯完最終會連接生成一個App,即會生成
可執(zhí)行文件
TARGET 表示該工程最終生成的文件名字,如果沒有配置默認(rèn)取該工程名字
那么如果我們想編譯生成一個動態(tài)庫或者靜態(tài)庫該怎么辦?關(guān)鍵語句來進(jìn)行控制
此時編譯該工程默認(rèn)會生成動態(tài)庫
此時編譯該工程又會生成靜態(tài)庫,所以關(guān)鍵地方就在上面兩句配置
多工程用法
多工程項(xiàng)目中一般是某些核心模塊編譯成庫(靜態(tài)庫、動態(tài)庫),然后在依賴的地方進(jìn)行引入即可
比如我們有一個字符串處理工具模塊,該模塊最終編譯完會生成一個動態(tài)庫
,然后我們其中一個模塊需要使用到該模塊,那么該工程怎么使用呢?
首先是工程文件需要導(dǎo)入該動態(tài)庫,這樣才能加載進(jìn)來參與編譯,否則會提示某些函數(shù)未定義的錯誤
插件依賴管理緣由
上述代碼正常情況下是沒有任何問題的,但是,但是,但是
凡是重要的事情肯定要說三遍,你以為這樣寫就完事了,那么說明你的這個庫被依賴的工程比較少,如果這個基礎(chǔ)庫在 n 個工程下面要使用呢?
到這里相比有些人就說了,哪個工程要使用直接復(fù)制上述代碼過去不就行了,這樣做從功能上來看是沒有問題,可以正常使用和運(yùn)行,但是你想過沒有,未來的那一天因?yàn)樘厥庠蜻@個庫有變化(名字、路徑等等),你是不是得修改這 n 個地方使用該庫的地方呀
程序員碰見重復(fù)的代碼肯定是不可以忍受的,肯定要想辦法封裝一下,將修改減少到最小,那么怎么實(shí)現(xiàn)比較好呢?
核心思想就是把依賴導(dǎo)入相關(guān)流程使用循環(huán)搞定,工程初始化時(也就是qmake)自動根據(jù)某個規(guī)則加載你的所有依賴即可
管理方案
當(dāng)你閱讀??源碼的時候就可以看到比較有意思的寫法,每個插件或者動態(tài)庫都有自己的依賴配置
文件,該文件記錄了這個庫或插件依賴那些庫、那些插件
每個插件的依賴配置文件命名類似這樣:,我們拿歡迎界面插件來舉個栗子分析下
打開該文件?。,查看文件內(nèi)容
?表示了當(dāng)前生成動態(tài)庫或者插件的名字
?表示當(dāng)前庫依賴的庫文件名稱,多個庫依次追加即可
?表示當(dāng)前插件依賴的插件名稱,比如
插件依賴核心
插件
那么這些定義的文件是怎么加載進(jìn)來的?又是怎么起作用的呢?源碼面前了無秘密,我們打開文件來一探究竟,重點(diǎn)關(guān)注 244 行到 277 行之間的內(nèi)容,可以看到如下內(nèi)容:
“上述代碼核心思想就是循環(huán)獲取依賴庫文件,然后進(jìn)行引入
第一句?是一個無限循環(huán),相當(dāng)于是死循環(huán)
,等到?
?語句才會退出
第二個循環(huán)獲取值挨個進(jìn)行遍歷,這個循環(huán)是為了檢測引入每個依賴插件
第三個循環(huán),首先會判斷對應(yīng)的依賴描述文件是否存在,如果不存在則會輸出錯誤信息給與提醒,后面會?進(jìn)來該文件,最后使用我們熟悉的
進(jìn)行進(jìn)入庫文件
循環(huán)最后面兩句非常重要,這兩句起到停止循環(huán)作用,每次會從
中去重
變量對應(yīng)的插件,最后直到
為空退出最外邊的循環(huán)
“上面就是插件依賴處理流程,動態(tài)庫依賴處理流程原理也類似,比如下面所示
可以看到整個過程幾行代碼就可以解決整個項(xiàng)目工程之間的依賴問題,后面開發(fā)其它插件和模塊只需要按照這個規(guī)則編寫對應(yīng)?文件即可,后續(xù)的依賴加載會自動處理,可以減少很多工作量以及出錯問題
小試牛刀
我們來驗(yàn)證下,編寫一個工具集模塊,該模塊編譯后生成一個動態(tài)庫,為了盡可能的簡單,工程結(jié)構(gòu)如下所示


文件列舉了該庫的依賴信息
demo 全部工程源碼下載可以訪問這里[https://github.com/kevinlq/Qt-Creator-Opensource-Study]
多工程管理
上面提到了多工程依賴庫的一些管理方法,下面來看看工程中一些其它管理技巧
善于定義變量
工程中難免會有很多重復(fù)的配置,比如:
某些文件編譯時生成的臨時文件路徑、編譯后動態(tài)庫、靜態(tài)庫、插件的路徑;
動態(tài)庫、靜態(tài)庫命名怎么區(qū)分;
?和?
?版本下每個庫生成后的名字怎么區(qū)分
程序版本號怎么在工程配置,然后代碼中直接使用
其實(shí)稍微大一點(diǎn)的項(xiàng)目,會面臨很多基礎(chǔ)的問題,解決這些問題要善于定義變量
這句話怎么理解呢?我們來看一些基本的例子就明白了
Debug 和 Release 區(qū)分
有時候我們不同編譯模式下生成的庫是不一樣的,調(diào)用第三方庫的時候也要注意這一點(diǎn),那么就要求程序在不同模式下編譯后生成的庫路徑放到不同路徑中
上面配置會在當(dāng)前目錄下對應(yīng)編譯模式下生成對應(yīng)庫
文件生成路徑定義
項(xiàng)目中一般都會定義文件的輸出路徑,比如我有一個動態(tài)庫要輸出指定目錄,那么對應(yīng)的??文件該怎么寫呢?
上述配置命令,在我們程序編譯后最終生成的路徑格式如下所示:
自動根據(jù)當(dāng)前是??還是?
模式生成到對應(yīng)目錄,對程序不會造成干擾,而且每個模塊插件可以單獨(dú)設(shè)置其路徑,這樣做的好處就是分離清晰明確,便于管理和維護(hù)
針對插件和動態(tài)庫可以分別處于不同的目錄,以依葫蘆畫瓢即可完成
“PS:如果想要完整的?
?配置模板可以私信我,真的很好用,拿來就可以直接用。事實(shí)上,上述代碼你也可以學(xué)習(xí)完
后自己也可以整理出來。
Qt Creator源碼工程結(jié)構(gòu)

源碼雖然看起來很多很復(fù)雜,不過大概可以分為三個部分,?、
,
。如上圖我重點(diǎn)標(biāo)紅的內(nèi)容,我在上一篇學(xué)習(xí)筆記當(dāng)中介紹過這三個部分分別是干什么的,詳細(xì)可以看上篇文章
Qt Creator 源碼學(xué)習(xí)筆記02,認(rèn)識框架結(jié)構(gòu)結(jié)構(gòu)
?工程封裝了一些外部使用的方法和函數(shù),以動態(tài)庫的方式呈現(xiàn),調(diào)用時引入動態(tài)庫加入頭文件即可。具體是怎么加入的呢?閱讀源碼你發(fā)現(xiàn)其它子工程并沒有直接引入,關(guān)鍵點(diǎn)還是上面提到的依賴管理方法
每個子工程都有自己的依賴配置文件,比如,這個文件必須要有,否則編譯時會報(bào)錯,提醒你缺少對應(yīng)的依賴文件
比如核心插件管理庫依賴配置?
你能很清晰的看出來這個庫依賴兩個庫,那么在編譯它時這兩個庫必須先編譯
是所有插件功能的實(shí)現(xiàn)部分,包含核心插件以及剩余的擴(kuò)展插件
插件也是一個個的動態(tài)庫,只不過每個插件都是繼承自同一個接口或者說叫純虛類,各自實(shí)現(xiàn)一些必要的初始化函數(shù),這樣才能統(tǒng)一管理和訪問控制
工程管理原理還是一樣的手法,每個插件都擁有一個配置文件,比如核心插件?
可以看出來該插件依賴三個動態(tài)庫,那么如果插件要依賴呢,怎么寫?也非常簡單,只需要添加依賴的插件名字即可,比如「書簽」插件依賴配置文件
可以看出多了一項(xiàng),需要依賴那些插件只需要往后追加即可
這里說到書簽插件,是一個非常好用的功能,平時編寫調(diào)試代碼梳理流程非常有用,比如閱讀到某個關(guān)鍵函數(shù),發(fā)現(xiàn)這個函數(shù)又調(diào)用了其它文件的方法,跳過去后發(fā)現(xiàn)又調(diào)用其它功能函數(shù),每次跳轉(zhuǎn)此時太多,想要返回初始位置查看就不方便,有了書簽隨時點(diǎn)擊書簽就可以跳轉(zhuǎn)回去了
PS:建議大家使用最新版本的
,書簽會一直緩存,直到你手動刪除了,有時候標(biāo)記了書簽,但是下班后電腦關(guān)機(jī)了第二天打開后發(fā)現(xiàn)書簽還在,直接開始干活,效率非常高
工程是程序主入口,會顯示加載三個動態(tài)庫,各個插件的調(diào)用是在
函數(shù)里面動態(tài)加載調(diào)用的
當(dāng)然了,實(shí)際配置時你還要考慮各各個平臺下的一些兼容性,比如?、
等平臺,如果你的軟件不涉及這些平臺那么就不用考慮了
總結(jié)
通過閱讀開源的框架和項(xiàng)目,可以增加我們的見識,平時工作或者學(xué)習(xí)當(dāng)中可能不注意或者想不到的一些技巧方法和編程思想在閱讀源碼的過程中都可以看到,時間久了各方面都會有很大的提升
下一篇我們來學(xué)習(xí)看看核心插件管理機(jī)制是如何實(shí)現(xiàn)的,也是學(xué)習(xí)的重點(diǎn)
相關(guān)閱讀
Qt Creator 源碼學(xué)習(xí)01,初識QTC
Qt Creator 源碼學(xué)習(xí)02,認(rèn)識框架結(jié)構(gòu)結(jié)構(gòu)