Makefile 编译多级目录多个目标文件模板

对于当前目录结构下的Makefile(基于银行系统Bank)

目录树

. tree
├── Makefile
├── bin
│   ├── client
│   └── server
├── build
│   ├── clientcore.o
│   ├── clientimpl.o
│   ├── clientmain.o
│   ├── clientview.o
│   ├── servercore.o
│   ├── serverimpl.o
│   ├── servermain.o
│   └── tools.o
├── data
├── include
│   ├── bankaccount.h
│   ├── clientcore.h
│   ├── clientimpl.h
│   ├── clientview.h
│   ├── servercore.h
│   ├── serverimpl.h
│   └── tools.h
├── lib
├── run.sh
└── src
    ├── client
    │   ├── Makefile
    │   ├── clientcore.c
    │   ├── clientimpl.c
    │   ├── clientmain.c
    │   └── clientview.c
    ├── server
    │   ├── Makefile
    │   ├── servercore.c
    │   ├── serverimpl.c
    │   └── servermain.c
    └── tools
        ├── Makefile
        └── tools.c

9 directories, 30 files

根目录Makefile模板

CC = gcc
# 添加的编译选项
CFLAGS = -Wall -Werror
# 需要链接的库
CLIBS =  

# 根目录路径
TOP_DIR = $(PWD)
# TOP_DIR = .

# 存放中间文件的路径
BUILD_DIR = $(TOP_DIR)/build

# 存放库文件的中间路径
LIB_DIR = $(TOP_DIR)/lib

# 存放可执行文件的路就路径
BIN_DIR = $(TOP_DIR)/bin

# 存放头文件的文件夹
INC_DIR = $(TOP_DIR)/include

# 存放.c 源文件的路径
SRC_DIR := \
	$(TOP_DIR)/src/client \
	$(TOP_DIR)/src/server \
	$(TOP_DIR)/src/tools

SRC_SERVER_DIR := $(TOP_DIR)/src/server
SRC_CLIENT_DIR := $(TOP_DIR)/src/client
SRC_TOOLS_DIR := $(TOP_DIR)/src/tools

# 在头文件路径前面加上-I
INCLUDE = $(patsubst %, -I %, $(INC_DIR))

# 在库文件路径前面加上-L
LIB = $(patsubst %, -L%, %(LIB_DIR))

VPATH = $(SRC_DIR)

# 将变量添加进环境变量表中,进入子目录的makefile时可以共享
export INCLUDE INC_DIR BIN_DIR BUILD_DIR TOP_DIR CC CFLAGS CLIBS LIB_DIR LIB \
	SRC_SERVER_DIR \
	SRC_CLIENT_DIR \
	SRC_TOOLS_DIR

# 去到各个目录执行makefile
all:CHECKDIR $(VPATH)
CHECKDIR:
	@mkdir -p $(BUILD_DIR) $(BIN_DIR) $(LIB_DIR)
$(VPATH): RUN
	@make -C $@
RUN:

# 清理所有编译产生的文件
.PHONY:clean
clean:
	rm -rf $(BUILD_DIR) $(BIN_DIR) $(LIB_DIR)

需要编译出可执行文件目录的Makefile模板(以server目录下的makefile文件示例)

# 路径
DIR = $(SRC_SERVER_DIR)
# 需要链接的库
LIBS := $(LIBS) -lpthread -ltools
# 得到带路径的.c 文件
FILES := $(foreach dir,$(DIR),$(wildcard $(dir)/*.c))
# 得到不带路径的.c 文件
FILENDIR := $(notdir $(FILES))
# 将工程中的.c 文件替换成 ./build 目录下对应的目标文件 .o
OBJS = $(patsubst %,$(BUILD_DIR)/%,$(patsubst %c,%o, $(FILENDIR)))
# 可执行文件名
TARGET = $(patsubst %main.c,%,$(notdir $(foreach dir, $(DIR), $(wildcard $(dir)/*main.c))))

# 可执行文件列表
# TARGETLIST = $(patsubst %main.c, %sys, $(TARGET))

# 运行
$(BIN_DIR)/$(TARGET): $(OBJS)
	$(CC) $(FLAGS) -o $@ $^ $(LIB) $(LIBS)

$(OBJS): $(BUILD_DIR)/%.o: %.c
	$(CC) $(FLAGS) $(INCLUDE) $(LIB) -c -o $@ $^

需要编译出库文件目录的Makefile模板(以tools目录下的makefile文件示例)

# 路径
DIR = $(SRC_TOOLS_DIR)
# 编译选项 记得加上 -fpic -shared
FLAG += -fpic -shared
# 得到带路径的.c 文件
FILES := $(foreach dir,$(DIR),$(wildcard $(dir)/*.c))
# 得到不带路径的.c 文件
FILENDIR := $(notdir $(FILES))
# 将工程中的.c 文件替换成 ./build 目录下对应的目标文件 .o
OBJS = $(patsubst %,$(BUILD_DIR)/%,$(patsubst %c,%o, $(FILENDIR)))
# 可执行文件名 注意必须以lib开头.so结尾
TARGET = $(patsubst %.c,lib%.so,$(notdir $(foreach dir, $(DIR), $(wildcard $(dir)/*.c))))

# 运行
$(LIB_DIR)/$(TARGET): $(OBJS)
	$(CC) $(FLAG) -o $@ $^

$(OBJS): $(BUILD_DIR)/%.o: %.c
	$(CC) $(FLAG) $(INCLUDE) -c -o $@ $^

调试语句

$(shell echo $(需要输出的变量) > a.txt)

附:Makefile语法基础 or 陈皓老师的《跟我一起写Makefile》也是经典

End...放一个上面的银行系统源码(github太难进了,只好放在gitee上了)

posted @ 2024-08-13 09:22  sleeeeeping  阅读(303)  评论(0)    收藏  举报