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

Makefile仅编译列表首个文件:为何test.c未被编译?

问题:为何test.c未被编译?

问题场景

编写了如下Makefile代码:

SRCS = ../compilation-test2/src/test2.c ./test.c
OBJS = $(foreach src,$(SRCS),$(patsubst %.c,build/%.o,$(notdir $(src))))

define build_obj
$(info $(1))
obj_file := $(patsubst %.c, build/%.o, $(notdir $(1)))
src_file := $(1)
$(info $(obj_file))
$(info $(src_file))
$(obj_file): $(src_file)
    g++ -c $(src_file) -o $(obj_file)
endef

$(foreach src,$(SRCS),$(eval $(call build_obj,$(src))))

all: $(OBJS)
    g++ $^ -o build/exec_file

clean:
    rm -rf build/*

对应的目录结构:

$ tree compilation-test
compilation-test
├── Makefile
├── build
└── test.c

1 directory, 2 files

$ tree compilation-test2/
compilation-test2/
├── include
│   └── test2.h
└── src
    └── test2.c

执行make命令后,仅test2.c被编译:

$ make
../compilation-test2/src/test2.c


./test.c
build/test2.o
../compilation-test2/src/test2.c
g++ -c ../compilation-test2/src/test2.c -o build/test2.o

$ ls build/
test2.o

询问:为何test.c未被编译?


原因分析与解决办法

问题根源

你在build_obj宏中定义的obj_file和src_file是全局变量,每次调用宏时都会覆盖之前的变量值;再加上:=的立即展开特性,导致处理第二个源文件./test.c时,变量被前一次处理test2.c的内容污染,最终生成的编译规则并未正确关联test.c和build/test.o。

从执行输出的info信息也能看出异常:处理./test.c时,输出的obj_file仍是build/test2.o,src_file仍是../compilation-test2/src/test2.c,说明宏内部的变量赋值完全被前一次的内容覆盖了。

解决办法

办法1:使用局部变量(GNU Make 3.81+支持)

在宏内的变量定义前加上local关键字,确保每次调用宏时变量都是独立的局部变量,不会互相干扰:

define build_obj
$(info $(1))
local obj_file := $(patsubst %.c, build/%.o, $(notdir $(1)))
local src_file := $(1)
$(info $(obj_file))
$(info $(src_file))
$(obj_file): $(src_file)
    g++ -c $(src_file) -o $(obj_file)
endef

办法2:去掉中间变量,使用自动变量

直接利用Make的自动变量简化宏定义,避免变量污染问题。其中$$<代表第一个依赖文件(即源文件),$$@代表当前目标文件(即.o文件),注意要使用$$来转义,确保eval展开时能正确解析为自动变量:

define build_obj
$(info $(1))
$(patsubst %.c, build/%.o, $(notdir $(1))): $(1)
    g++ -c $$< -o $$@
endef

修改后重新执行make,就能同时编译test.c和test2.c,生成对应的build/test.o和build/test2.o文件。


内容的提问来源于stack exchange,提问作者andre.hre

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 01:52:22