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

为何Make将前缀文件夹插入词干中间而非开头?依赖路径疑问

问题描述

文件系统结构如下:

$ tree
.
├── deps
├── file2.c
├── Makefile
└── subfolder
    └── file1.c

3 directories, 3 files

为生成依赖文件并保留目录结构编译目标文件,编写了简化版Makefile:

OBJECTS := subfolder/file1.o file2.o

all: $(OBJECTS)

%.o: %.c deps/%.d
    @echo '%.o: %.c deps/%.d'
    @echo '$@: $^ ($*)'
    @echo

%.d: ;

.SUFFIXES:

运行make后得到不符合预期的结果:

$ make
%.o: %.c deps/%.d
subfolder/file1.o: subfolder/file1.c subfolder/deps/file1.d (subfolder/file1)

%.o: %.c deps/%.d
file2.o: file2.c deps/file2.d (file2)

疑问:当词干为subfolder/file1时,为何deps/%.d匹配为subfolder/deps/file1.d,而非预期的deps/subfolder/file1.d?

原因分析与解决方法

原因

这种情况通常是因为你使用的Make实现(如部分非GNU版本的Make)对模式匹配的%处理逻辑不同:

  • GNU Make中,%会匹配包含路径分隔符的完整词干,因此对于目标subfolder/file1.o,%对应的词干是subfolder/file1,deps/%.d会被解析为deps/subfolder/file1.d,这是符合预期的结果。
  • 若你使用的Make版本仅让%匹配文件名部分(不包含路径前缀),那么subfolder/file1.o的词干是file1,Make会自动将目标的路径前缀subfolder/附加到依赖路径前,导致deps/%.d被解析为subfolder/deps/file1.d。

解决方法

如果你需要兼容不同Make版本,或确保依赖路径严格符合deps/subfolder/file1.d的结构,可以用以下方式修改Makefile:

方法1:明确构造依赖路径(GNU Make兼容)

OBJECTS := subfolder/file1.o file2.o

all: $(OBJECTS)

# 确保依赖文件路径为deps/xxx.d,自动创建子目录
%.o: %.c deps/%.d
	@echo '$@: $^ ($*)'
	# 替换为实际编译命令,例如:gcc -c $< -o $@

# 生成依赖文件时自动创建deps下的子目录
deps/%.d:
	@mkdir -p $(dir $@)
	@touch $@

.SUFFIXES:

方法2:遍历目标生成规则(兼容更多Make版本)

OBJECTS := subfolder/file1.o file2.o

all: $(OBJECTS)

# 为每个目标单独生成规则,精准控制依赖路径
define compile_rule
$(1): $(1:.o=.c) deps/$(1:.o=.d)
	@echo '$@: $$^ ($$(basename $$@))'
endef

$(foreach obj,$(OBJECTS),$(eval $(call compile_rule,$(obj))))

# 生成依赖文件时自动创建目录
deps/%.d:
	@mkdir -p $(dir $@)
	@touch $@

.SUFFIXES:

这样修改后,无论使用哪种Make实现,都能生成deps/subfolder/file1.d格式的依赖文件,符合你的预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 16:05:08