通過Makefile管理。
根據(jù)目標(biāo)和依賴的最后修改時間判斷是否需要更新。
三要素:目標(biāo)、依賴和規(guī)則。

目標(biāo)可以是文件或者偽目標(biāo)。
命令可以與目標(biāo)依賴同一行,中間用;隔開?;蛘擢毩⒁恍?,一條命令占一行,命令以tab開始。
可以使用反斜杠\續(xù)行,但是其后不能有空格。
make有默認規(guī)則,.c文件會默認生成同名的.o文件。所以單獨每個文件只需要將目標(biāo)和除文件本身外的其他依賴寫上即可。
單目標(biāo),多依賴。
命令前加-,表示忽略命令執(zhí)行錯誤。
可以通過-f或者--file=指定make讀取的文件。
使用include包含其他Makefile文件,多個文件使用空格分隔,可以使用通配符。
include前通常會有-,例如-include xxx xxx,這表示忽略包含文件不存在或者無法創(chuàng)建的錯誤提示。
不加-,編譯停止

加-,可以編譯。

$有特殊含義,表示變量或函數(shù)的引用。
order-only依賴使用|指示,|后邊的為此依賴,表示構(gòu)建目標(biāo)存在時,此依賴改變也不會重建目標(biāo)。
庫文件通過lNAME的方式作為依賴。只是指定了庫的名稱,最后對應(yīng)的庫應(yīng)該是libNAME.a或者libNAME.so的文件。
通配符
*、?、[]可以用在目標(biāo)、規(guī)則命令中,其他地方需要wildcard函數(shù)指定。注意在文件名中出現(xiàn)通配符的話需要\轉(zhuǎn)義。
變量中使用wildcard顯示指明通配符,他被展開為已經(jīng)存在的、使用空格分開的、匹配此模式的所有文件的列表。objs=$(wildcard *.o),這樣objs的值是具體的一個一個的xxx.o文件,也就是通配符展開。如果直接objs=*.o那么objs就是*.o這個字符串。
objs:=$(patsubst %.c,%.o,$(wildcard *.c)):獲取所有.c文件,并將后綴改為.o,構(gòu)成.o列表賦值給變量。
$^表示通過目錄搜索得到的依賴文件的完整路徑名列表,即所有的依賴文件。
$@表示規(guī)則的目標(biāo)。
$<第一個依賴文件
$?表示所有依賴文件
變量
多字符變量的引用必須加()。定義變量有兩種方式:直接展開(:=)和遞歸展開(=或define),推薦使用前者。
?=表示條件賦值,如果左值沒有賦值則將右值賦值。
VPATH:指定搜索路徑。路徑之間用冒號隔開。
????????????VPATH=src:../headers
GPATH:與VPATH類似,保證已存在的目標(biāo)在所在目錄重建。
CFLAGS:
.LIBPATTERNS:其值為lib%.so lib%.a,使用lNAME時會將%替換為NAME。
RM:定義為RM=rm -f,可以使用$(RM)來作為clean的命令
MAKELEVEL:make的調(diào)用深度。
關(guān)鍵字
vpath:指定文件的搜索路徑
? ? ? ? ? ? vpath PATTERN DIR? ? 指定
? ? ? ? ? ? vpath PATTERN? ? ? ? ? ? ?清除指定
? ? ? ? ? ? vpath? ? ? ? ? ? ? ? ? ? ? ? ? ? 清除所有
PATTERN需要使用%作為模式匹配,匹配一個或者多個字符。
偽目標(biāo)
.PHONY是一個特殊目標(biāo),其依賴就是偽目標(biāo),
可以使用all作為偽目標(biāo)來構(gòu)建多個程序,這些程序就是all的依賴。
強制目標(biāo),指沒有依賴也沒有命令,且目標(biāo)不存在,主要用在非GNU的make版本中。
特殊目標(biāo)
.PHONY .SUFFIXES .DEFAULT .PRECIOUS .INTERMEDIATE? .SECONDARY? .DELETE_ON_ERROR? .IGNORE? .LOW_RESOLUTION_TIME? .SILENT? .EXPORT_ALL_VARIABLES? .NOTPARALLEL
通過例子講解
#下面三行定義變量ROOT、SRC_DIR、BUILD_DIR并賦值,分別記錄了根目錄、源碼目錄和build中間目錄
ROOT=.
SRC_DIR=$(ROOT)/src
BUILD_DIR = build
#下面兩行CC表示編譯器,CFLAGS表示編譯的參數(shù)
CC = gcc
CFLAGS=-ansi -I$(ROOT)/include -Wall -DLINUX -D_GNU_SOURCE
#下面兩行LIBAPUE表示庫的路徑,LDLIBS表示鏈接的參數(shù)-L表示庫路徑-l表示庫名稱
LIBAPUE=$(ROOT)/lib/libapue.a
LDLIBS=-L$(ROOT)/lib -lapue
#下面兩行C_FILES表示c源文件,wildcard指明后邊的*表示通配符,否則*不起作用。
#OBJ_FILES是c文件對應(yīng)的_c.o文件,冒號前邊表示文件列表,后邊表示匹配規(guī)則。%與*作用類似。
C_FILES = $(wildcard $(SRC_DIR)/*.c)
OBJ_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%_c.o)
#all后邊表示我們最終想要得到的文件,all是一個偽目標(biāo)。
all: linux-api-demo
#表示目標(biāo)linux-api-demo的依賴和目標(biāo)已經(jīng)產(chǎn)生的方法
linux-api-demo:$(OBJ_FILES) $(LIBAPUE)
gcc -o linux-api-demo $(OBJ_FILES) $(LDLIBS)
表示.c生成.o目標(biāo)的規(guī)則,$<表示依賴,$@表示目標(biāo),$(@D)表示目標(biāo)的路徑,不包括/
$(BUILD_DIR)/%_c.o: $(SRC_DIR)/%.c
mkdir -p $(@D)
$(CC) $(CFLAGS) $< -c -o $@
#清除規(guī)則,clean偽目標(biāo)
clean:
rm -rf $(BUILD_DIR) linux-api-demo
#make執(zhí)行的時候先通過 all查看其依賴,all的依賴就是我們要得目標(biāo),此處是linux-api-demo,
#要得到linux-api-demo,就要找其生成規(guī)則,找到后發(fā)現(xiàn)他的依賴是.o和.a文件,
#繼續(xù)找.o文件的生成規(guī)則,找到后根據(jù)規(guī)則命令生成對應(yīng)的文件,此處文件的生成是一個一個的,不是批量
#的,可以通過make的輸出看出這一點。
#.o和.a生成后滿足了生成linux-api-demo的條件,編譯產(chǎn)生linux-api-demo后all的依賴也滿足了,
#此時make完成。