中,已經說明了單個makefile管理層次目錄的侷限性。本文,主要總結一下專案中的一種實用makefile樹寫法,為10來個人協作的中小型專案makefile編寫,提供參考。
1. 需求
從實用角度,makefile樹應該達到以下需求:
1)自動加入編譯系統。新增目錄、檔案後,能夠自動新增(理想),或只需少許修改,就能新增到整個專案編譯中。
2)可讀性好,易於新增。新增目錄、檔案,linux新人能自己看懂新增(理想),或只需口頭10s描述就能很好完成。
3)模組化。新增目錄、檔案後的makefile,和其他目錄完全沒有關係(理想),或只需與最鄰近的前、後有關係。
2. 實現
2.1 自動加入編譯系統
使用makefile遞迴執行,能夠解決此問題。以下指令碼,能夠執行subdirs指定的子目錄內的makefile。
[plain]view plain
copy
makefile。
subdirs = modual-a modual-b modual-c
.phony: subdirs $(subdirs)
subdirs: $(subdirs)
$(subdirs):
$(make) -c $@
說明:1)變數subdirs,指定當前目錄下,要遞迴編譯的子目錄。
2).phony及subdirs目標結構,能保證遞迴到子目錄中。
2.2 可讀性好,易於新增;模組化
使用makefile的變數定義,其位置前後不敏感特性可以做到。示例指令碼如下:
[plain]view plain
copy
subdirs = modual-a modual-b modual-c
objects = x.o y.o z.o
all:subdirs $
clean:cleansubdirs
rm $
說明:1)變數objects,指定當前目錄的目標檔案。新增乙個檔案z.cpp,在變數objects中,增加z.o即可。
2)新增乙個目錄dir-c,在變數subdirs中,增加dir-c。然後參考本目錄中的makfile,在dir-c中,建立乙個類似makfile即可。
2.3 減少重複指令碼
實現中,將makefile中的共用變數,轉移到檔案中,使用include包含,能夠達到函式效果,減少重複指令碼,容易改變。
3. 例項):
[plain]view plain
copy
project-test
+-- makeconfig
| +-- make.global
+-- src
| +-- module-a
| | +-- test.cpp
| | +-- makefile
| +-- module-b
| | +-- test.cpp
| | +-- makefile
| +-- main.cpp
| +-- makefile
+-- makefile
說明:1)project-test/makeconfig/make.global,要包含的makefile共用變數。
2)project-test/makefile,頂層makefile,指定可執行目標,及原始碼目錄。
3)project-test/src/makefile,子目錄的makeflile。目錄module-a、module-b的類似,每個目錄乙個。
3.1 project-test/makeconfig/make.global
如下所示:
[plain]view plain
copy
# compile macro
cc = g++
cflags = -o2 -wall
ldflags = -lm
includes = -i/usr/local/include
# recursive make
.phony: subdirs $ cleansubdirs
subdirs: $
$:
$ -c $@ all
# recursive make clean
cleansubdirs:
@for dir in $; do \
$ -c $$dir clean; \
done
# dependence
%.o: %.cpp
$ $ $ -c $< -o $@
%.o: %.cc
$ $ $ -c $< -o $@
說明:1)包含4個區域,共用變數,遞迴make,遞迴makeclean,依賴關係。
2)遞迴makeclean,使用了不列印的shell語法。原因是,如果和遞迴一樣寫,會造成目標過載警告。
3.2 project-test/makefile
如下所示:
[plain]view plain
copy
# target, subdir, objects in current dir
target = test
subdirs = src
objects =
all:subdirs $
$ -o $ $$(find ./$ -name '*.o') $ $
clean:cleansubdirs
rm -f $ $
# path of "make global scripts"
# note, use absolute path. export once, use in all subdirs
export projectpath=$
export makeinclude=$/makeconfig/make.global
# include "make global scripts"
include $
說明:1)使用shell語法,搜尋出指定目錄的所有.o,鏈結為執行目標檔案。
2)使用export,指定專案絕對路徑,指定共用變數,包含所有目錄共用的makefile變數。
3)每個目標使用乙個頂層的makefile,來執行make和makeclean的遞迴入口,共用makefile。
3.3 project-test/src/makefile
如下所示:
[plain]view plain
copy
# subdir and objects in current dir
subdirs = module-a module-b
objects = main.o
all:subdirs $
clean:cleansubdirs
rm -f $
include $
說明:1)增加目錄,只用修改子目錄變數subdirs;增加檔案,修改當前目標檔案變數objects。
2)不同目錄下,原始碼相同名字,但類、函式不相同,可以正常編譯。
4. 專業makefile樹
以上,只是乙個專案最最普通的makefile樹。乙個實現檔案乙個.o檔案,不考慮庫生成,不考慮功能配置項,不考慮平台相容性。
一些開源專案,考慮了各種平台相容性,及功能特性,通常使用了autoconf和automake,自動生成特殊標頭檔案和巨集定義,來達到效果。使用以下3條命令,向使用者提供配置項設定,編譯,庫、標頭檔案、或目標檔案安裝路徑。在複雜相容專案中,非常實用。
./configure
make
make install
還在繼續學習中。
參考資料:
1. gnu make manual:
2. 同事j的makefile樹。
專案實用makefile
本文 中,已經說明了單個makefile管理層次目錄的侷限性。本文,主要總結一下專案中的一種實用makefile樹寫法,為10來個人協作的中小型專案makefile編寫,提供參考。1.需求 從實用角度,makefile樹應該達到以下需求 1 自動加入編譯系統。新增目錄 檔案後,能夠自動新增 理想 或...
專案實用makefile
中,已經說明了單個makefile管理層次目錄的侷限性。本文,主要總結一下專案中的一種實用makefile樹寫法,為10來個人協作的中小型專案makefile編寫,提供參考。1.需求 從實用角度,makefile樹應該達到以下需求 1 自動加入編譯系統。新增目錄 檔案後,能夠自動新增 理想 或只需少...
c 手寫Makefile 簡單實用的方法
在makefile規則中,萬用字元會被自動展開。但在變數的定義和函式引用時 萬用字元將失效。這種情況下如果需要萬用字元有效,就需要使用函式 wildcard 使用wildcard可以很好的獲取指定路徑下的所有.cpp檔案。比如src wildcard cc 可以獲取當前路徑下所有的.cc檔案 獲取到...