Makefile编译独立C程序:分文件编译与目录创建失效求助
问题场景
现有目录结构如下:
build ch01 foo.c bar.c ch02 baz.c meow.c
需求:每个.c文件都是独立程序,编译后需放到build/目录下对应同名子文件夹中,最终结构如下:
build ch01 foo, bar ch02 baz, meow
现有Makefile的问题
当前使用的Makefile能实现需求,但存在两个痛点:
- 必须拆分编译/链接阶段,手动删除中间目标文件,因为找不到更优方式从完整构建路径还原源文件名。
- 尝试用标准前置目标方式单独创建目录时,
$(BUILD_DIR)目标完全不执行:all: $(OBJS) | $(BUILD_DIR) $(BUILD_DIR): $(MD) -p $@
优化后的解决方案
子目录Makefile(ch01、ch02下各放一份)
CC = gcc CFLAGS = -g -Wall -Wextra -ansi MD = mkdir -p # 匹配当前目录下所有C源文件 SRCS = $(wildcard *.c) # 生成build目录下的可执行文件路径 BINS = $(patsubst %.c, ../build/$(shell basename $(CURDIR))/%, $(SRCS)) BUILD_DIR = ../build/$(shell basename $(CURDIR)) # 默认目标:构建所有可执行文件 all: $(BINS) # 直接从C源文件编译链接到目标可执行文件 $(BUILD_DIR)/%: %.c | $(BUILD_DIR) $(CC) $(CFLAGS) $< -o $@ # 创建build子目录的目标 $(BUILD_DIR): $(MD) $@ # 清理生成的可执行文件目录 clean: rm -rf $(BUILD_DIR)
优化说明
解决手动删除目标文件问题:
不再生成中间.o文件,直接将.c文件一步编译链接为build目录下的可执行文件。目标路径$(BUILD_DIR)/%与源文件%.c一一对应,无需处理中间文件,自然省去手动删除步骤。解决目录创建目标不执行问题:
将最终可执行文件的编译规则依赖前置条件$(BUILD_DIR),Make在构建可执行文件前会自动检查目录是否存在,不存在则执行目录创建规则。原方案失效是因为all依赖的是.o文件,而.o文件的规则未关联目录创建逻辑,调整目标为最终可执行文件后,前置条件生效。
可选:顶层统一编译Makefile
如果需要在根目录一键编译所有子目录,可在根目录创建如下Makefile:
SUBDIRS = ch01 ch02 all: $(SUBDIRS) $(SUBDIRS): $(MAKE) -C $@ clean: for dir in $(SUBDIRS); do $(MAKE) -C $$dir clean; done
内容的提问来源于stack exchange,提问作者Roman Kurbatov
相关产品推荐
相关产品推荐

