Linux Makefile
Makefile 格式
一個例子如下。Makefile由一系列規則組成。
規則格式如下:命令列表中的命令,以TAB鍵開始。
目標…: 依賴文件集合……命令 1命令 2……下面規則,目標是main,依賴文件是main.o input.o calcu.o,命令是gcc -o main main.o input.o calcu.o。
依賴文件其中任何一個更新了,目標也得更新。
更新,執行一遍規則中的命令列表。
由于第一次編譯,main不存在,所以執行第一條規則。
由于第一條規則依賴于main.o input.o calcu.o,但是目前沒有這三個.o文件,所以make會去找以這三個.o文件為目標的規則,然后執行。
main : main.o input.o calcu.ogcc -o main main.o input.o calcu.o最后一個規則,目標是clean,但是沒有依賴文件,所以其對應命令不執行。
如果想要執行clean,使用命令make clean。
make執行過程:
1.當前目錄下,找以Makefile命名的文件。
2.找到后,按Makefile中的規則,編譯生成最終的目標文件。
3.目標文件不存在,或目標的依賴文件比目標新,執行后面的命令更新目標。
Makefile 變量
Makefile中的變量都是字符串。
定義一個變量objects,使用=賦值。
引用變量使用$(變量名)。
objects = main.o input.o calcu.o main: $(objects)gcc -o main $(objects)賦值符
=賦值符
變量的真實值,是它所引用的變量的最后一次有效值。
name = 111 curname = $(name) name = 222print:@echo curname: $(curname)運行結果如下。
:=賦值符
不使用后定義的變量,只使用前面已經定義好的。
name = 111 curname := $(name) name = 222print:@echo curname: $(curname)運行結果如下。
?=賦值符
如果變量在前面沒有被賦值,那么就賦為新值;如果前面賦過值,那么就使用前面賦的值。
name = 111 curname = $(name) curname ?= 222print:@echo curname: $(curname)結果:
+=賦值符
給前面已定義好的變量添加一些字符串。
objects = main.o inpiut.o objects += calcu.oMakefile 模式規則
通過模式規則,可以用一條規則,將所有.c 文件編譯為對應的.o文件。
%表示長度任意的非空字符串。
如%.c,是所有以.c 結尾的文件。
a.%.c,表示以a.開頭,以.c結束的所有文件。
下面這個代碼加上命令,可以代替原來Makefile的3-8行代碼。
命令還沒寫,需要借助自動化變量。
%.o : %.c#命令Makefile 自動化變量
每一次對模式規則進行解析,都是不同的目標和依賴文件。
自動化變量,可以把符合模式的文件自動依次取出。
自動化變量,只出現在規則的命令中。
| $@ | 規則中的目標集合,在模式規則中,如果有多個目標,$@表示匹配模式中定義的目標集合。 |
| $< | 依賴文件集合中的第一個文件,如果依賴文件是以模式(%)定義的,$<是符合模式的一系列的文件集合。 |
| $^ | 所有依賴文件的集合,空格分開,如果依賴文件中有多個重復的文件,$^會去除重復的依賴文件,只保留一份。 |
| $% | 當目標是函數庫時,表示規則中的目標成員名,如果目標不是函數庫文件,那么其值為空。 |
| $? | 所有比目標新的依賴目標集合,以空格分開。 |
| $+ | 類似$^,但是,當依賴文件存在重復時,不會去除重復的依賴文件。 |
| $* | 表示目標模式中%及其之前的部分,如果目標是test/a.test.c,目標模式為a.%.c,$*就是test/a.test。 |
下面這個代碼,可以代替原來Makefile的3-8行代碼。
%.o : %.cgcc -c $<Makefile 偽目標
下面這個代碼,用來清理工程。
但是,規則中,沒有創建文件clean的命令。
如果規則目錄下創建一個名為clean的文件,執行make clean時,由于沒有依賴文件,目標被認為是最新的。后面的rm命令不執行。
clean:rm *.orm main為解決這個問題,可以將clean聲明成偽目標。
聲明clean為偽目標后,無論當前目錄下是否存在名為clean的文件,輸入make clean,會執行rm命令。
.PHONY:cleanMakefile 條件判斷
<條件關鍵字><條件為真時執行的語句> endif<條件關鍵字><條件為真時執行的語句> else<條件為假時執行的語句> endif條件關鍵字:ifeq判斷是否相等、ifneq判斷是否不相等
ifeq (<參數 1>, <參數 2>) ifeq ‘<參數 1 >’,‘ <參數 2>’ ifeq “<參數 1>”, “<參數 2>” ifeq “<參數 1>”, ‘<參數 2>’ ifeq ‘<參數 1>’, “<參數 2>”ifdef變量名非空,表達式為真、ifndef。
ifdef <變量名>Makefile 函數
不支持自定義函數,函數是已經定義好的。
參數之間以逗號,隔開,函數名和參數之間用空格分開,調用函數以$開頭。
$(函數名 參數集合) ${函數名 參數集合}subst
字符串替換。
$(subst <from>,<to>,<text>) 將字符串<text>中的<from>替換為<to>,返回替換以后的字符 串 $(subst jym,JYM,Dog is JYM)patsubst
模式字符串替換。
$(patsubst <pattern>,<replacement>,<text>)找字符串<text>中,符合<pattern>的字符串,用<replacement>替換掉。<pattern>可以使用通配符%表示任意長度的字符串。 $(patsubst %.c,%.o,a.c b.c c.c) 將字符串a.c b.c c.c中,所有符合%.c的字符串替換為%.o替換后,字符串是a.o b.o c.odir
獲取目錄。
$(dir <names…>) 從文件名序列<names>中提取出目錄部分。 $(dir </src/a.c>) 提取文件/src/a.c的目錄部分,/src。notdir
去除文件中的目錄部分,提取文件名。
$(notdir <names…>) $(notdir </src/a.c>)提取出a.cforeach
完成循環。
$(foreach <var>, <list>,<text>) 把參數<list>中的單詞逐一取出,放到參數<var>中。 執行<text>包含的表達式。 每次<text>都返回一個字符串。 循環的過程中,<text>中所包含的每個字符串以空格隔開。 最后整個循環結束時,<text>返回的每個字符串所組成的整個字符串是foreach函數的返回值。 names := a b c d files := $(foreach n,$(names),$(n).o) $(name)中的單詞被挨個取出,存到變量n中。$(n).o每次根據$(n)計算出一個值,這些值以空格分隔,最后作為foreach函數的返回$(files)的值是“a.o b.o c.o d.o”。wildcar
%只有在規則中才會展開,變量定義和函數使用時,通配符不會自動展開,此時用函數wildcar。
$(wildcard PATTERN…) $(wildcard *.c) 獲取當前目錄下,所有.c文件。總結
以上是生活随笔為你收集整理的Linux Makefile的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 结合反向传播算法使用python实现神经
- 下一篇: linux 其他常用命令