You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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源文件,导致$<为空。

修改方式有两种:

  1. 先将目标文件的.o后缀替换为.c,再替换路径前缀:
${OBJECTFILES}: %.o: $(subst ${BUILD_PREFIX},${SRC_PREFIX},$(patsubst %.o,%.c,$@))
    ${MP_CC} ${CFLAGS} $< -o $@
  1. 更简洁的模式匹配写法,直接关联源文件与目标文件的路径对应关系:
${OBJECTFILES}: build/%.o: src/%.c
    ${MP_CC} ${CFLAGS} $< -o $@

二、临时方案每次重新编译的原因及修复

你的临时方案中,OBJECTFILES是基于源文件路径生成的.o文件(如src/commonModule.o),但实际生成的目标文件是buildTest/commonModule.o。Makefile会认为src/commonModule.o这个目标从未被创建,因此每次执行make都会触发重新编译。

修复步骤:

  1. 先将OBJECTFILES替换为BUILD_PREFIX下的路径:
OBJECTFILES :=      $(patsubst %.c,%.o,$(SOURCEFILES))
OBJECTFILES :=      $(subst ${SRC_PREFIX},${BUILD_PREFIX},$(OBJECTFILES))
  1. 再修改模式规则,确保目标与依赖的路径正确对应:
${OBJECTFILES}: %.o: $(subst ${BUILD_PREFIX},${SRC_PREFIX},$(patsubst %.o,%.c,$@))
    ${MP_CC} ${CFLAGS} $< -o $@

修改后Makefile会正确检查目标文件与源文件的时间戳,仅在源文件更新时重新编译。

内容的提问来源于stack exchange,提问作者user44791

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 03:22:42