當前位置: 妍妍網 > 碼農

深入淺出 Makefile:從基礎到高級套用

2024-05-14碼農

轉自:網路

Makefile是一種編譯控制檔,廣泛用於計畫的自動化構建。它定義了一系列的規則來指導構建的過程。透過Makefile,開發者可以輕松管理大型計畫的編譯連結、清理等任務。本文將從Makefile的基礎用法講起,逐步深入到更高級的套用,為你呈現一個全面而詳細的Makefile使用手冊。

Makefile的基本結構

一個最簡單的Makefile包含規則,規則由目標(target)、依賴(dependencies)和命令(commands)三部份組成:

target: dependencies
commands

命令前的Tab鍵是必須的。下面是一個簡單的範例:

hello: hello.c
gcc-ohellohello.c

變量的使用

在Makefile中聲明變量可以使得我們的程式碼更加簡潔。

CC=gcc
CFLAGS=-std=c99
LDFLAGS=
OBJ=main.o utils.o
app: $(OBJ)
$(CC) -o app $(OBJ)$(LDFLAGS)
main.o: main.c
$(CC)$(CFLAGS) -c main.c
utils.o: utils.c utils.h
$(CC)$(CFLAGS) -c utils.c

通用規則和模式匹配

模式規則可以減少我們重復相同命令的工作量。

%.o: %.c
$(CC)$(CFLAGS) -c $<

$< 是自動變量之一,代表依賴列表中的第一項。

自動化變量

Makefile提供了一系列自動化變量,它們在規則的命令中非常有用:

  • $@ 表示規則中的目的檔名;

  • $^ 表示所有的依賴檔列表;

  • $< 表示第一個依賴檔;

  • $? 表示所有比目標新的依賴檔列表。

  • 函式的使用

    Makefile中內建了許多函式,用以執行字串操作、檔操作等。

    例如,獲取原始檔列表:

    SRC=$(wildcard *.c)
    OBJ=$(patsubst %.c,%.o,$(SRC))

    控制Make的行為

  • make -B 強制重新編譯所有目標;

  • make -n 顯示將要執行的命令而不實際執行;

  • make -f <file> 指定使用其他名稱的Makefile檔;

  • make -j 允許並列執行(多核編譯)。

  • 高級用法 - 條件判斷

    Makefile也支持條件判斷,這在不同環境需要執行不同命令時非常有用。

    ifeq ($(OS),Windows_NT)
    RM=del /Q
    else
    RM=rm -f
    endif
    clean:
    $(RM) *.o

    使用變量和檔包含來組織Makefile

    對於大型計畫,組織多個Makefile是一種好方法。

    # 在子Makefile中
    include config.mk

    自訂函式

    透過定義可以重用的函式,你可以使你的Makefile變得更加強大和靈活。

    define run-cc
    $(CC)$(CFLAGS) -o $@$^
    endef
    app: $(OBJ)
    $(call run-cc)

    處理多目標

    定義一個規則來批次處理多個檔。

    FILES := file1 file2 file3
    all: $(FILES)
    $(FILES):
    touch $@

    偽目標的使用

    偽目標不代表實際的檔,它只是一個動作的名稱。

    .PHONY: clean
    clean:
    rm -f *.o app

    偵錯Makefile

    你可以使用 make --debug 或添加註釋來幫助偵錯Makefile。

    app: main.o utils.o
    # 這是一個連結的命令
    $(CC) -o app main.o utils.o

    結語

    Makefile是構建自動化的強大工具,既可以簡化小型計畫的構建流程,也能夠靈活管理大型應用程式的復雜構建系統。透過本文的詳細論述和豐富範例,您應該能夠基本掌握Makefile的各項技能,並在實際計畫中加以套用。

    希望以上內容對你深入理解和使用Makefile有所幫助。記住,「實踐出真知」——編寫你自己的Makefile並嘗試使用這些特性是最好的學習方式。