Makefile例項學習

开宝特攻發表於2024-06-16

makefile

模板 1

# 一個適合中小規模的makefile模版,基本上自己按照實際情況指定一下 原始檔,目標檔案,標頭檔案目錄,以及原始檔字尾就行了。

# ---------------------------------------------------------------------------
# commands
# ---------------------------------------------------------------------------
CC := gcc
LINK := gcc
RM := rm -rf
MV := mv
TAR := tar
MKDIR := mkdir

# ---------------------------------------------------------------------------
# settings
# ---------------------------------------------------------------------------
SRC_SUFFIX := .c
OBJ_SUFFIX := .o
LIB_SUFFIX := .a
BIN_SUFFIX := .exe
DLL_SUFFIX := .so

INC_PREFIX := -I
LIB_PREFIX := -L

OPT_C := -c
OPT_OUT := -o
OPT_LINKOUT := -o

CFLAGS := $(OPT_C)
LIBFLAGS := -Debug

# ---------------------------------------------------------------------------
# directories
# ---------------------------------------------------------------------------
SRC_DIR := ./src
OBJ_DIR := ./obj
INC_DIR := ./inc
LIB_DIR := ./lib /usr/local/lib /lib /usr/lib

# ---------------------------------------------------------------------------
# common settings
# ---------------------------------------------------------------------------
SRCS := $(wildcard $(SRC_DIR)/*$(SRC_SUFFIX))
OBJS := $(patsubst $(SRC_DIR)/%$(SRC_SUFFIX),$(OBJ_DIR)/%$(OBJ_SUFFIX),$(SRCS))
INCS := $(addprefix $(INC_PREFIX), $(INC_DIR))
LIBS := $(addprefix $(LIB_PREFIX), $(LIB_DIR)) $(LIBFLAGS)
TEMPFILES := core core.* *$(OBJ_SUFFIX) temp.* *.out typescript*

# ---------------------------------------------------------------------------
# make rule
# ---------------------------------------------------------------------------
TARGET := loader

.PHONY: all clean

all: $(TARGET)

clean:
$(RM) $(TARGET)$(BIN_SUFFIX) $(OBJS)

$(TARGET):$(OBJS)
$(LINK) $(OPT_LINKOUT)$(TARGET)$(BIN_SUFFIX) $(LIBS) $(OBJS)

$(OBJS):$(OBJ_DIR)/%$(OBJ_SUFFIX):$(SRC_DIR)/%$(SRC_SUFFIX)
$(CC) $(CFLAGS) $(INCS) $(OPT_OUT)$@ $<

模板 2

CXX := g++

SRC_DIR := ./src
OBJ_DIR := ./build
BIN_DIR := ./bin
INC_DIR := ./include

VPATH = $(INC_DIR) $(OBJ_DIR) $(SRC_DIR)
vpath %.h $(INC_DIR)

# 一種搜尋原始檔的方式
# SRC_DIRS = $(shell find $(SRC_DIR) -maxdepth 3 -type d)
# SRCS = $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.cpp))
# TODO: 這樣子出來的目標檔案,在jing'tai時就找不到依賴了
# OBJS := $(OBJ_DIR)/$(notdir $(patsubst %.cpp, %.o, $(SRCS)))

SRCS := $(wildcard $(SRC_DIR)/*.cpp)
OBJS := $(patsubst $(SRC_DIR)/%.cpp, $(OBJ_DIR)/%.o, $(SRCS))
INCS := $(addprefix -I, $(INC_DIR))
BUILDING_DIRS := $(OBJ_DIR) $(BIN_DIR)

TARGET := adb_lab2.exe
RUN := run.sh

$(TARGET) : $(BUILDING_DIRS) $(OBJS)
	$(CXX) -o $(BIN_DIR)/$(TARGET) $(OBJS)
	@touch $(RUN)
	@echo "$(BIN_DIR)/$(TARGET)" > $(RUN)

# 這裡的字首不能少。makefile不會自動去VPATH裡面找這幾個目標,而是直接當成新的目標來對待
$(OBJ_DIR)/BufferPoolManager.o : BufferPoolManager.h LRUReplacer.h
$(OBJ_DIR)/DataStorageManager.o : DataStorageManager.h
$(OBJ_DIR)/LRUReplacer.o : LRUReplacer.h
$(OBJ_DIR)/main.o : BufferPoolManager.h

# 一個建立執行時依賴資料夾的方法
$(BUILDING_DIRS) :
	@mkdir $@

# 這叫 靜態模式
$(OBJS) : $(OBJ_DIR)/%.o : $(SRC_DIR)/%.cpp
	$(CXX) -o $@ -c $< $(INCS)

.PHONY: all clean output
all : $(TARGET)
clean:
	-rm -rf $(BUILDING_DIRS) test.dbf $(RUN)
output:
	@echo $(SRCS)
	@echo --------------
	@echo $(OBJS)

模板 3

CC := gcc
CC_INCLUDE_FLAGS := -I ./include/
CC_FLAGS := $(CC_INCLUDE_FLAGS) -g

# 程式執行的引數
ARGS := ~/codes

DIR_SRC := ./src
DIR_OBJ := ./build
DIR_EXE := ./bin

SRCS := $(shell find $(DIR_SRC) -name "*.c")
OBJS := $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS))
DPTS := $(patsubst %.c, %.d, $(SRCS))
DIRS := $(DIR_OBJ) $(DIR_EXE)

target := $(DIR_EXE)/my_ls_pro

$(target): $(DIRS) $(OBJS)
	$(CC) $(OBJS) -o $@

$(DIRS):
	@mkdir $@

$(DIR_OBJ)/%.o: $(DIR_SRC)/%.c
	$(CC) $(CC_FLAGS) -c $< -o $@

%.d: %.c
	@set -e; \
	rm -f $@; \
	$(CC) -MM $(CC_FLAGS) $< $(CC_INCLUDE_FLAGS) > $@.$$$$.dtmp; \
	sed 's,\(.*\)\.o\:,$*\.o $*\.d\:,g' < $@.$$$$.dtmp > $@;\
	rm -f $@.$$$$.dtmp

-include $(DPTS)

clean:
	rm -f $(OBJS)
	rm -f $(DPTS)

run:
	make
	$(target) $(ARGS)

教程

REF1:makefile 簡明教程, REF2:如何輸出到指定資料夾REF3:關於自動生成依賴.d 檔案

模式替換

$(patsubst <pattern>,<replacement>,<text> )
查詢中的單詞(單詞以“空格”、“Tab”或“回車”“換行”分隔)是否符合模式,如果匹配的話,則以替換。

​ 這裡,可以包括萬用字元“%”,表示任意長度的字串。如果中也包含“%”,那麼,中的這個“%”將是中的那個“%”所代表的字串。(可以用“\”來轉義,以“%”來表示真實含義的“%”字元)

$(patsubst %.c,%.o, a.c b.c)
# 把字串 “a.c b.c” 符合模式[%.c]的單詞替換成[%.o],返回結果是 “a.o b.o”

變數替換引用

​ 對於一個已經定義的變數,可以使用“替換引用”將其值中的字尾字元(串)使用指定的字元(字串)替換。格式為$(VAR:A=B)或者${VAR:A=B}

​ 意思是,替換變數“VAR”中所有“A”字元結尾的字為“B”結尾的字。“結尾”的含義是空格之前(變數值多個字之間使用空格分開)。而對於變數其它部分的“A”字元不進行替換。

foo := a.o b.o c.o
bar := $(foo:.o=.c)
# 注意變數不要帶 $
SRCS_NODIR := $(notdir $(wildcard $(SRC_DIR)/*$(SRC_SUFFIX)))
OBJS_NODIR := $(SRCS_NODIR:$(SRC_SUFFIX)=$(OBJ_SUFFIX))

相關文章