目錄
- 前言
- 概念
- Chapter 3:書寫規則
- 3.3 在規則中使用通配符
- 3.4 檔案搜尋
- 3.8 自動生成依賴性
- 原理 *
- 直接解析例子 **
- sed 指令
- 直接解析例子 **
- 原理 *
- 參考
- 書籍
- 本筆記主要記錄Makefile一些概念要點。
- 本筆記為提取性筆記,章節與《跟我一起寫Makefile》同步,是以會看到有些小标題會跳過。
- make 支援三個通配符:
- *
- 任意長度的任意字元
- ?
- 長度為一的任意字元
- ~ (以例子說明)
- ~/test
- 表示目前使用者的 $HOME 目錄下的 test 目錄
- ~lzm/test
- 表示使用者為 lzm 的宿主目錄下的 test 目錄
- 若使用者沒有宿主目錄,則根據環境變量 HOME 而定。
- ~/test
- *
舉例:
- 例子1
- 變量 objects 表示目前目錄下所有的 .o 檔案。
objects := $(wildcard *.o)
- 例子2 *
- 注:這裡的變量 objects 表示的就是 *.o,因為就像 C語言 的宏。
objects = *.o
- 例子3 *
- 列出目前所有 .c 檔案對應的 .o 檔案。
- 下面的 *,是make的 * ,% 是makefile的 % ,具體看函數定義。
$(patsubst %.c,%.o,$(wildcard *.c))
- VPATH 變量
- Makefile 檔案會在目前目錄下尋找依賴檔案和目标檔案,在找不到的情況下就在 VPATH 變量中指定的路徑去找。
VPATH = src:../headers
* 上面例子中就是 **VPATH** 的格式,用 **:** 隔開多個路徑。
- vpath 關鍵字
- vpath 關鍵字比 VPATH 變量更加靈活, vpath 可以指定不同的檔案在不同的搜尋目錄中。
- 使用方法有三種:
-
vpath
在 。為符合模式
的檔案指定搜尋目錄 (多個目錄可以用空格或者 : 分開)。
-
清除符合模式
的檔案的搜尋目錄。
- vpath 清除所有已被設定好了的檔案搜尋目錄。
-
vpath %.h include //指定.h類型檔案的搜尋路徑是include
在 Makefile 中,我們的依賴關系可能會需要包含一系列的頭檔案,比如,如果我們的 main.c 中有一 句 #include "defs.h" ,那麼我們的依賴關系應該是:
main.o : main.c defs.h
大多數的 C/C++ 編譯器都支援一個“-M”的 選項,即自動找尋源檔案中包含的頭檔案,并生成一個依賴關系。例如,如果我們執行下面的指令:
cc -M main.c
其輸出是:
main.o : main.c defs.h
** 注:如果使用 GNU 的 C/C++ 編譯器,得用 -MM 參數,不然,-M 參數會把一些标準庫的頭檔案也包含進來。 **
如:
gcc -M main.c 的輸出是:
main.o: main.c defs.h /usr/include/stdio.h /usr/include/features.h \
/usr/include/sys/cdefs.h /usr/include/gnu/stubs.h \
/usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stddef.h \
/usr/include/bits/types.h /usr/include/bits/pthreadtypes.h \
/usr/include/bits/sched.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h \
/usr/include/bits/wchar.h /usr/include/gconv.h \
/usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stdarg.h \
/usr/include/bits/stdio_lim.h
gcc -MM main.c 的輸出則是:
main.o : main.c defs.h
- 隐晦規則(其中之一)
- 會自動生成 gcc -c *.c 等語句。
- 如果使用了該 隐晦規則 規則,在不改變 源檔案 的情況下,改變其它(如頭檔案),再去運作 make 指令,是不會幹活的。
- 會自動生成 gcc -c *.c 等語句。
如果想使用 隐晦規則 + 依賴自動包含頭檔案,可以往下看。
- gcc -MM main.c
- 會在 makefile 的依賴上自動添加 main.c 包含的頭檔案。
基于上面這個原理,我們可以把 main.c 包含的頭檔案 資訊 自動識别出來并儲存到 main.d 檔案中。
這時候,.d 檔案就出來了。
- 頭檔案改變,make也會幹活。
- 該腳本實作了,.c 檔案編譯過程中,産生 .d 檔案。
%.d : %.c
@set -e;rm -f $@; \
$(CC) -MM $(CPPFLAGS) $< > $@.; \
sed 's,$∗\.o[ :]*,\1.o $@ : ,g' < $@. > $@; \
rm -f $@.
- 源碼解析
- set -e;
- 表示 直接在指令行模式上進行 sed 動作編輯,其實此為預設選項。
- rm -f $@;
- 表示 删除所有目标檔案,即是删除所有 .d 檔案。
- $(CC) -MM $(CPPFLAGS) $< > $@.;
- 表示 編譯産生的一些标注庫的頭檔案資訊儲存到 .d.xxx 随機檔案中。
- $@.
- 表示字尾為随機的意思。
- 假設 CC= gcc ,CPPFLAGS=空,即 gcc -MM main.c > main.d.xxxx
- > 表示重定向的意思。
- 即是把 main.c 所依賴的頭檔案資訊寫入 main.d.xxxx 檔案。如
- set -e;
main.o: main.c defs.h
* **sed 's,$∗\.o[ :]*,\1.o $@ : ,g' < $@. > $@;**
* 表示執行linux 指令 sed
* **< $@.**
* 該檔案内容交給前面,讓 sed 語句處理
* **$∗\.o[ :]\***
* 為比對字段
* 表示 main 後面 .o 接着的字串段
* **$∗\.o[ :]\***
* 為替換字段
* **$@. > $@**
* 輸入給 .d 檔案,即是 main.d,内容如下:
main.o main.d : main.c defs.h
* **rm -f $@.**
* 删除 main.d.xxxx 的随機檔案。
- 生成 .d 檔案後,Makefile 檔案可以 include 該檔案進入 Makefile 中,這樣, .o .d 都是目标檔案,後面有很多依賴的頭檔案,一旦頭檔案更新,目标檔案便會更新。
- 要點格式,具體百度
- sed 為linux指令,用于替換。
sed‘s:/usr/local:/usr:g’
- s: 就是于把 : 當作分隔符 /。
sed‘s;/usr/local;/usr;g’
- s; 就是于把 ; 當作分隔符 /。
- 《GUN Makefile》
- 《跟我一起寫Makefile》