一个简单的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)

你可能感兴趣的:(Linux开发)