1. 程式人生 > 實用技巧 >Makefile 易忘規則記錄

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的三種用法

  1. vpath <pattern> <directories>

    為符合pattern的檔案在directories上也進行搜尋

  2. vpath <pattern>

    清除符合pattern的檔案的搜尋目錄

  3. 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

條件關鍵詞

  1. ifeq

    ifeq (<arg1>, <arg2>)
    ifeq '<arg1>' '<arg2>'
    ifeq "<arg1>" "<arg2>"
    ifeq "<arg1>" '<arg2>'
    ifeq '<arg1>' "<arg2>"
    
  2. ifneq

    用法同上

  3. ifdef

    foo =
    ifdef foo
        frobozz = yes
    else
        frobozz = no
    endif
    

    上述例子,由於foo沒有賦值,故 frobozz為no

  4. 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”引數一同使用,來檢視這個依賴檔案所發生的規則命令。