Makefile实例学习

makefile

小记忆恢复术

  • $@ Target
  • $^ 所有依赖,空格分隔
  • $< 第一个依赖

模板 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))
posted @ 2024-06-16 01:09  开宝特攻  阅读(7)  评论(0编辑  收藏  举报
Back to Top Button