一個簡單的Makefile編譯所有c代碼文件爲每個單獨程序

一個簡單的Makefile編譯所有c代碼文件爲每個單獨程序

筆者初學Makefile用來方便編譯項目,記錄一下,若有問題歡迎指正,文件內容附在文末

本文目的

我在./src/目錄下有若干.c文件,想對每個文件均進行編譯,中間代碼文件*.o存放在./build/obj/下,目標可執行文件放在./build/

Makefile的工作流程

  1. 沒有指定輸出項目時,Makefile會先在所有目標中找到第一個沒有通配符的目標進行構造;例如本文中的all,即時它是個僞目標
  2. 根據構造all的規則,需要構造$(BUILD),而$(BUILD)即是$(BUILD_DIR)下無後綴的可執行文件
  3. 於是要構造的目標就變爲了$(OBJ_DIR)/%.o,然後make在規則中繼續尋找,找到了一個匹配的規則$(BUILD_DIR)/%: $(OBJ_DIR)/%.o,但不幸的是該規則依賴OBJS := $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o),於是繼續尋找
  4. 下面又找到了$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c,現在不需要繼續尋找了,即執行這個規則下的語句進行編譯但不鏈接
  5. 完成後回到上層進行對.o文件的鏈接,然後繼續回到上層,重複這個過程使得對於每一個$(BUILD)中的目標都得到了生成

不刪除中間文件

上述過程會在全部編譯完成後使用rm命令刪除中間過程文件,僅保留目標文件,可以通過添加一條

.SECONDARY: $(OBJS)

$(OBJS)成爲第二目標,從而不被清理掉

編寫clean方法

我們有時需要對項目進行清理,此時只需要將clean寫進僞目標,然後把它的實現放到最後一個就好了,實現很簡單,即使用rm對編譯過程文件和結果文件進行清理即可

一個比較建議的項目樹組織

.
├── build
│   ├── 若干可執行文件
│   └── obj
│       └── 若干.o中間代碼文件
├── LICENSE
├── Makefile
├── README.md
└── src
    └── 若干c源文件

附:Makefile全文

# File paths
SRC_DIR := ./src
BUILD_DIR := ./build
OBJ_DIR := $(BUILD_DIR)/obj

# Compilation flags
CC := gcc
LD := gcc
CFLAGS := -Wall

# Files to be compiled
SRCS := $(wildcard $(SRC_DIR)/*.c)
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
BUILD := $(OBJS:$(OBJ_DIR)/%.o=$(BUILD_DIR)/%)

# Don't remove *.o files automatically
.SECONDARY: $(OBJS)

all: $(BUILD)

# Compile each *.c file as *.o files
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c 
    @echo + CC $<
    @mkdir -p $(OBJ_DIR)
    @$(CC) $(CFLAGS) -c -o $@ $<

# Link each *.o file as executable files
$(BUILD_DIR)/%: $(OBJ_DIR)/%.o
    @echo + LD $@
    @mkdir -p $(BUILD_DIR)
    @$(LD) $(CFLAGS) -o $@ $<

.PHONY: all clean

clean:
    rm -rf $(BUILD_DIR)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章