Makefile 是一個非常強大的構建自動化工具,用於管理專案的編譯、連結和其他構建任務。以下是一個詳細的 Makefile 使用檔案,包括基本概念、語法、範例和常見任務。
一個基本的 Makefile 規則的語法如下:
target: dependencies
command
target
:要生成的目標的名稱。dependencies
:生成目標所需的檔案或其他目標的列表。command
:生成目標的命令,必須以 Tab 鍵開頭。以下是一個簡單的範例 Makefile,用於編譯一個 C 程式:
CC = gcc
CFLAGS = -Wall
TARGET = myprogram
SOURCES = main.c utils.c
$(TARGET): $(SOURCES)
$(CC) $(CFLAGS) -o $(TARGET) $(SOURCES)
clean:
rm -f $(TARGET)
這個 Makefile 使用了變數 CC
、CFLAGS
、TARGET
和 SOURCES
,並定義了一個 all
目標用於編譯程式,以及一個 clean
目標用於清理生成的檔案。
all: $(TARGET)
$(TARGET): $(SOURCES)
$(CC) $(CFLAGS) -o $(TARGET) $(SOURCES)
clean:
rm -f $(TARGET)
CC = gcc
CFLAGS = -Wall
TARGET = myprogram
SOURCES = main.c utils.c
$(TARGET): $(SOURCES)
$(CC) $(CFLAGS) -o $(TARGET) $(SOURCES)
.PHONY: clean
clean:
rm -f $(TARGET)
除了基本用法外,還支援一些高階用法,可以用來處理更復雜的構建需求。以下是一些高階用法的詳細介紹:
Makefile 支援條件語句,可以根據條件來執行不同的規則或命令。通常使用 ifeq
和 ifdef
這兩個條件語句。
ifeq ($(VARIABLE), value)
# 條件為真時的規則和命令
else
# 條件為假時的規則和命令
endif
例如,可以根據是否定義了 DEBUG
變數來設定不同的編譯選項:
ifeq ($(DEBUG), 1)
CFLAGS = -g
else
CFLAGS = -O2
endif
Makefile 還提供了一些內建函數,用於處理文字和檔案列表。以下是一些常見的函數:
$(shell command)
:執行 shell 命令並返回結果。$(wildcard pattern)
:匹配檔名模式並返回符合條件的檔案列表。$(foreach var, list, text)
:對列表中的每個元素執行指定的操作。$(strip string)
:刪除字串開頭和結尾的空白字元。$(subst find,replace,text)
:替換文字中的字串。$(filter pattern, text)
:從文字中篩選出匹配指定模式的字串。$(patsubst pattern,replacement,text)
:用指定字串替換文字中的模式。$(notdir names)
:從檔案路徑中提取檔名。這些函數可以在 Makefile 中用於各種目的,例如檔案操作、文書處理和條件判斷。
通常,Makefile 中的依賴關係需要手動維護。但是,對於 C/C++ 專案,您可以使用編譯器提供的 -M
選項來自動生成依賴關係。例如:
SOURCES = main.c utils.c
DEPS = $(SOURCES:.c=.d)
%.d: %.c
$(CC) -M $< -o $@
-include $(DEPS)
在這個範例中,%.d: %.c
規則用於自動生成 .d
檔案,其中包含了 .c
檔案的依賴關係。然後使用 -include
指令來包含這些 .d
檔案,以自動跟蹤依賴關係。
對於大型專案,通常需要將 Makefile 拆分成多個子目錄,每個子目錄都有自己的 Makefile。然後,可以使用遞迴或變數傳遞來管理這些子目錄之間的依賴關係。例如:
SUBDIRS = dir1 dir2
all: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@
clean:
for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir clean; \
done
在這個範例中,SUBDIRS
變數包含了子目錄的列表。$(MAKE)
是一個 Makefile 中的特殊變數,用於啟動另一個 Makefile。
Makefile 支援高階的變數操作,包括字串操作、條件賦值、變數展開等。以下是一些範例:
STR1 = hello
STR2 = world
STR3 = $(STR1) $(STR2)
在這個範例中,STR3
的值將是 "hello world"
。
FOO ?= default_value
如果 FOO
變數未定義,則將其賦值為 default_value
。
VAR1 = $(VAR2)
VAR2 = value
在這個範例中,VAR1
的值將是 value
,因為 Make 會遞迴地展開變數。
宣告:本作品採用署名-非商業性使用-相同方式共用 4.0 國際 (CC BY-NC-SA 4.0)進行許可,使用時請註明出處。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 戀水無意