1. 程式人生 > >make--打造專業的編譯環境

make--打造專業的編譯環境

方式 需要 blog color uil ccf 路徑 cto 出現

一.項目的目錄結構

技術分享圖片
分析
A.項目被劃分為多個不同模塊
1.每個模塊的代碼用一個文件夾進行管理--文件夾由inc,src,makefille構成
2.每個模塊的對外函數聲明統一放置於common/inc中--如:commom.h xxxfunc.h
B.需要打造的編譯環境
1.編碼文件夾在編譯時不能被改動
2.在編譯時自動創建文件夾用於存放編譯結果
3.編譯過程中能夠自動生成依賴關系,自動搜索需要的文件
4.每個模塊可以擁有自己獨立的編譯方式
5.支持調試版本的編譯選項
C.解決方案的設計
第1階段:將每個模塊中的代碼編譯成靜態文件
技術分享圖片
第2階段:將每個模塊的靜態文件鏈接成最終可執行程序
技術分享圖片

二.實現

第一階段
1.完成可用於各個模塊編譯的makefile文件

2.每個模塊的編譯結果為靜態庫文件(.a文件)
關鍵的實現要點:
1.自動生成依賴關系(gcc -MM)
2.自動搜索需要的文件(vpath)
3.將目標文件打包為靜態庫文件(ar crs)

技術分享圖片
編譯實現
技術分享圖片
對應項目的目錄結構,對應的文件夾下包含著相應的頭文件和源文件
技術分享圖片技術分享圖片
運行的結果如圖所示
技術分享圖片
在module文件夾和main文件夾下分別新建makefile,復制當前的makefile,在build新建module和main的空文件夾,運行make all命令都可以生成.o文件,實現了各個模塊編譯的makefile文件
第二階段任務:
1.完整編譯整個工程的makefile文件
2.調用模塊makefile編譯生成靜態庫文件
3.鏈接所有模塊的靜態庫文件,最終得到可執行程序

技術分享圖片
關鍵的實現要點
1.如何創建build文件夾以及子文件夾
2.如何進入每一個模塊文件夾進行編譯
3.編譯成功後如何鏈接所有模塊靜態庫
解決方案設計
1.定義變量保存模塊名列表
2.利用Shell中的for循環遍歷模塊名變量
3.在for循環在進入模塊文件夾進行編譯
4.循環結束後鏈接所有的模塊靜態庫文件
技術分享圖片技術分享圖片
鏈接的註意事項
A.gcc在進行靜態庫鏈接時必須遵循嚴格的依賴關系
1.gcc -o app.out x.a y.a z.a《==》其中的依賴關系必須為:x.a->y.a,y.a->z.a;默認情況下遵循自左向右的依賴關系
2.如果不清楚庫間的依賴,可以使用-Xlinker自動確定依賴關系
gcc -o app.out -Xlinker(x.a y.a z.a -Xlinker)
運行代碼及運行結果圖如圖所示
技術分享圖片技術分享圖片
在makefile中可以知道 可以一步一步的進行make也可以一步完成makefile
技術分享圖片
技術分享圖片
結果對比圖
技術分享圖片技術分享圖片
三. 可能出現的問題
A.所有模塊makefile中使用的編譯路徑均為寫死的絕對路徑,一旦項目文件夾移動,編譯必將失敗
技術分享圖片
解決方案:
1.在工程makefile中獲取項目的源碼路徑
2.根據項目源碼路徑:a:拼接得到編譯文件的路徑(DIR_BUILD),b:拼接得到全局包含路徑(DIR_COMMON_INC)
3.通過定義命令行變量將路徑傳遞給模塊makefile
代碼的實現:
對之前的代碼進行該動的地方(紅線進行了標出)
技術分享圖片
運行的結果
技術分享圖片
通過對每個文件夾的makefile進行修改 對每個makefile中的每個絕對路徑進行刪除 發現運行的結果沒有改變

#####################################
B.所有模塊makefile的內容完全相同
當模塊makefile需要該動時,將涉及多處相同的改動

解決方案:
1.將模塊makefile拆分為兩個模板文件
mod-cfg.mk 定義可能改變的變量
mod-rule.mk 定義相對穩定的變量和規則
2.默認情況下
模塊makefile復用模板文件實現功能(include)
關鍵問題:
1.模塊makefile如何知道模板文件的具體位置
2.解決方案:通過命令行變量進行模板文件位置的傳遞
實現:
技術分享圖片技術分享圖片技術分享圖片技術分享圖片技術分享圖片
.運行結果如圖:
技術分享圖片

四 :小結
1.大型項目的編譯環境是由不同makefile構成的
2.編譯環境的設計需要依據項目的整體構架設計
3.整個項目的編譯過程可以分解為不同階段
4.根據不同的階段有針對性的對makefile進行設計
5.makefile也需考慮復用性和維護性等基本程序特性

make--打造專業的編譯環境