Makefile 易忘規則記錄
Makefile 易忘規則記錄
主要用於記錄一些Makefile中容易忘記的規則等
目錄
粗略規則
target... : prerequisites ... [tab] command ...
易忘規則
偽目標宣告
.PHONY: clean
clean:
[tab] rm ./*.o
自動推導
a.o 的預設依賴 a.c
註釋
Makefile 中只有行註釋
p := /home/wangha #註釋
當註釋以上面方式時,要注意,p實際上為'/home/wangha ',後面是攜帶著空格的
命令
命令的執行必須以[TAB]開頭,除非命令是緊跟在依賴規則的';'後面的
引用其他Makefile
include <filename1> <filename2> #允許使用萬用字元
-include <*.h> # 忽略無法讀取的檔案
指定目錄搜尋標頭檔案或依賴檔案
VPATH = src:../others # src和../others
vpath的三種用法
-
vpath <pattern> <directories>
為符合pattern的檔案在directories上也進行搜尋
-
vpath <pattern>
清除符合pattern的檔案的搜尋目錄
-
vpath
清除所有已被設定好的檔案搜尋目錄
多目標中的$> $@
$> 表示多目標中對應的依賴
$@ 表示多目標中對應的目標
替換
source = foo.c bar.c include $(source:.c=.d) # 轉化為foo.d bar.d include $(source:%.c=%.d) # 靜態模式的轉換
命令執行
exec:
[TAB] :cd /home/abc; pwd # 只有在一行時才會有效
exec2:
[TAB] : cd/home
[TAB] : pwd # 依舊是Makefile的目錄下
忽略ERROR
方式一:
-command 加上'-'後,不管出錯與否,繼續執行
方式二:
全域性忽略,make的引數中加'-i'或者'--ignore-errors'
巢狀執行的變數傳遞
export <var1 ...>;
僅僅侷限於傳遞到下層的Makefile
如果傳遞所有變數 則只需要export即可
等於號
= 普通的定義變數,但存在著遞迴定義的問題
:= 修復了遞迴定義問題,但前面的變數不能使用後面的變數,如
a := $(b) a.o #a的實際值是a.o
b := b.o
?= 例如b?=bar
,如果b已經定義過了,則什麼也不做
變數巢狀
x = $(y)
y = z
z = Hello
a := $($(x))
此處a應該為Hello,自行推導
override的使用
在make的時候,會指定一些引數,在Makefile中對這些變數賦值是會被忽略的,如果希望修改,則需要使用override,語法i如下
override <var1>; =<value>;
override <var1>; +=<more>;
override define foo
bar
endef
define的使用
define double-echo
echo abc
echo $(abc)
endef
區域性變數
a := bar.c
tmp : a:=foo.c
tmp : $(a)
[TAB] gcc -o b.o $(a) #在tmp的範圍內,a為foo.c
模式變數
%.o : CFLAGS = -O
使用時
a.o: a.c
[TAB] : $(CC) $(CFLAGS) a.o a.c
上述例子為,給所有的 .o 檔案,在編譯時候,自動新增-O
條件關鍵詞
-
ifeq
ifeq (<arg1>, <arg2>) ifeq '<arg1>' '<arg2>' ifeq "<arg1>" "<arg2>" ifeq "<arg1>" '<arg2>' ifeq '<arg1>' "<arg2>"
-
ifneq
用法同上
-
ifdef
foo = ifdef foo frobozz = yes else frobozz = no endif
上述例子,由於foo沒有賦值,故 frobozz為no
-
ifndef
用法同上
函式的呼叫
$(func-name argus)
例子:將空格全部轉換為','
comma:= ,
empty:=
space:= $(empty) $(empty)
foo:= a b c
bar:= $(subst $(space),$(comma),$(foo))
foreach函式
$(foreach <var>,<list>,<text>)
功能:對list中的每一個賦值給var,並執行text
例子:
names := a b c d
files := $(foreach n,$(names), $(n).o)
files 的值為a.o b.o c.o d.o
if函式
$(if <condition>,<then-part>)
$(if <condition>,<then-part>,<else-part>)
返回值,如果 <condition>
為真(非空字串),那個 <then-part>
會是整個函式的返回值,如果 <condition>
為假(空字串),那麼 <else-part>
會是整個函式的返回值。如果 <else-part>
沒有被定義,那麼,整個函式返回空字串。
call函式
$(call <expression>,<parm1>,<parm2>,...,<parmn>)
返回值: <expression>
的返回值就是 call 函式的返回值
例子 foo=a b
reverse = $(1) $(2)
foo = $(call reverse,a,b)
origin函式
$(origin <variable>)
功能:告訴你這個變數是哪裡來
返回值:
undefined: 如果 <variable>
從來沒有定義過
default: 如果 <variable>
是一個預設的定義,比如“CC”這個變數
environment: 如果 <variable>
是一個環境變數,並且當Makefile被執行時, -e
引數沒有被開啟。
file: 如果 <variable>
這個變數被定義在Makefile中。
command line: 如果 <variable>
這個變數是被命令列定義的。
override: 如果 <variable>
是被override指示符重新定義的。
automatic: 如果 <variable>
是一個命令執行中的自動化變數。
常用於 :判斷當前的這個變數到底來自於哪裡
例子:
ifdef bletch
ifeq "$(origin bletch)" "environment"
bletch = barf, gag, etc.
endif
endif
shell函式
呼叫/bin/sh來執行一些功能
contents := $(shell cat foo)
控制make的函式
$(error <text ...>)
$(warning <text ...>)
可用於檢測Makefile執行時的資訊,決定你繼續執行OR報Error或者Warning和停止
例子,當發現有ERROR_001時,報錯
ifdef ERROR_001
$(error error is $(ERROR_001))
endif
make的退出碼
0-succeed
1-error
2-如果你使用了make的“-q”選項,並且make使得一些目標不需要更新
指定Makefile
make -f 123.mk
指定目標
推薦採取以下方式
.PHONY: all
all: prog1 prog2 prog3 prog4
makefile中的目標生成參照規則
- all:這個偽目標是所有目標的目標,其功能一般是編譯所有的目標。
- clean:這個偽目標功能是刪除所有被make建立的檔案。
- install:這個偽目標功能是安裝已編譯好的程式,其實就是把目標執行檔案拷貝到指定的目標中去。
- print:這個偽目標的功能是例出改變過的原始檔。
- tar:這個偽目標功能是把源程式打包備份。也就是一個tar檔案。
- dist:這個偽目標功能是建立一個壓縮檔案,一般是把tar檔案壓成Z檔案。或是gz檔案。
- TAGS:這個偽目標功能是更新所有的目標,以備完整地重編譯使用。
- check和test:這兩個偽目標一般用來測試makefile的流程。
檢查規則
-n: 不執行引數,這些引數只是列印命令,不管目標是否更新,把規則和連帶規則下的命令打印出來,但不執行,這些引數對於我們除錯makefile很有用處。
-t: 這個引數的意思就是把目標檔案的時間更新,但不更改目標檔案。也就是說,make假裝編譯目標,但不是真正的編譯目標,只是把目標變成已編譯過的狀態。
-q: 這個引數的行為是找目標的意思,也就是說,如果目標存在,那麼其什麼也不會輸出,當然也不會執行編譯,如果目標不存在,其會打印出一條出錯資訊。
-W <file>: 這個引數需要指定一個檔案。一般是是原始檔(或依賴檔案),Make會根據規則推導來執行依賴於這個檔案的命令,一般來說,可以和“-n”引數一同使用,來檢視這個依賴檔案所發生的規則命令。