Makefile中使用subst在模式先决条件下实现多目录编译的问题
Makefile路径替换问题及修复方案
问题描述
我有如下源文件:src/commonModule.c src/freeRtos/freeRtosIntegration.c,期望生成目标文件build/commonModule.o build/freeRtos/freeRtosIntegration.o,且build/和build/freeRtos/目录已提前创建。调用build目标时,期望执行命令:
gcc -g -x c -c src/freeRtos/freeRtosIntegration.c -o build/freeRtos/freeRtosIntegration.o gcc -g -x c -c src/commonModule.c -o build/commonModule.o
但当前编写的Makefile执行后生成的命令缺失源文件路径:
gcc -g -x c -c -o build/commonModule.o gcc -g -x c -c -o build/freeRtos/freeRtosIntegration.o
现有Makefile代码:
.PHONY: build SRC_PREFIX = src BUILD_PREFIX = build SRCDIRS = ${SRC_PREFIX} ${SRC_PREFIX}/freeRtos SEARCHC = $(addsuffix /*.c ,$(SRCDIRS)) SOURCEFILES := $(wildcard ${SEARCHC}) OBJECTFILES := $(patsubst %.c,%.o,$(SOURCEFILES)) OBJECTFILES := $(subst ${SRC_PREFIX},${BUILD_PREFIX},$(OBJECTFILES)) MP_CC = gcc CFLAGS = -g -x c -c build: ${OBJECTFILES} ${OBJECTFILES}: %.o: $(subst ${BUILD_PREFIX},${SRC_PREFIX},$@) ${MP_CC} ${CFLAGS} $< -o $@
一、修复subst命令解决路径缺失问题
问题出在模式规则的依赖替换逻辑:$(subst ${BUILD_PREFIX},${SRC_PREFIX},$@)仅替换了路径前缀,但$@是目标文件(如build/commonModule.o),替换后得到的是src/commonModule.o——这是不存在的.o文件,而非实际的.c源文件,导致$<为空。
修改方式有两种:
- 先将目标文件的
.o后缀替换为.c,再替换路径前缀:
${OBJECTFILES}: %.o: $(subst ${BUILD_PREFIX},${SRC_PREFIX},$(patsubst %.o,%.c,$@)) ${MP_CC} ${CFLAGS} $< -o $@
- 更简洁的模式匹配写法,直接关联源文件与目标文件的路径对应关系:
${OBJECTFILES}: build/%.o: src/%.c ${MP_CC} ${CFLAGS} $< -o $@
二、临时方案每次重新编译的原因及修复
你的临时方案中,OBJECTFILES是基于源文件路径生成的.o文件(如src/commonModule.o),但实际生成的目标文件是buildTest/commonModule.o。Makefile会认为src/commonModule.o这个目标从未被创建,因此每次执行make都会触发重新编译。
修复步骤:
- 先将
OBJECTFILES替换为BUILD_PREFIX下的路径:
OBJECTFILES := $(patsubst %.c,%.o,$(SOURCEFILES)) OBJECTFILES := $(subst ${SRC_PREFIX},${BUILD_PREFIX},$(OBJECTFILES))
- 再修改模式规则,确保目标与依赖的路径正确对应:
${OBJECTFILES}: %.o: $(subst ${BUILD_PREFIX},${SRC_PREFIX},$(patsubst %.o,%.c,$@)) ${MP_CC} ${CFLAGS} $< -o $@
修改后Makefile会正确检查目标文件与源文件的时间戳,仅在源文件更新时重新编译。
内容的提问来源于stack exchange,提问作者user44791
相关产品推荐
相关产品推荐

