如何在Makefile中修改目标文件输出路径至镜像源目录的objs子目录?
如何在Makefile中将目标文件生成与源文件目录镜像的objs子目录?
你遇到的问题其实是Makefile中路径替换和规则匹配的常见坑,我来给你讲最简的解决方法,顺便帮你分析下之前尝试的问题出在哪。
首先,直接上能满足你需求的Makefile:
FILES = file1.c file2.c file3.c subdir1/afile1.c subdir2/bfile1.c # 使用patsubst完成正确的路径替换,把每个.c文件映射到objs下的对应.o文件 OBJS = $(patsubst %.c, objs/%.o, $(FILES)) all: $(OBJS) # 静态模式规则:匹配objs目录下所有.o文件,依赖对应的源文件 objs/%.o: %.c # 自动创建目标文件所在的目录,-p确保多级目录都能创建 @mkdir -p $(dir $@) $(CC) $(CFLAGS) -c $< -o $@
为什么这个写法能生效?
- 路径替换用
patsubst而非简单后缀替换:你之前用的$(FILES:.c=objs/.o)是Make的后缀替换,它只会把文件名末尾的.c直接替换成objs/.o,结果就是file1.c变成file1objs/.o,完全不符合预期。而patsubst %.c, objs/%.o, $(FILES)是模式替换,会把整个%.c模式替换成objs/%.o,这样subdir1/afile1.c就会正确转换成objs/subdir1/afile1.o。 - 静态模式规则匹配正确的目标与依赖:
objs/%.o: %.c明确指定了目标是objs目录下的.o文件,依赖是对应的源文件,不会出现你之前的语法错误。加上@mkdir -p $(dir $@)是为了自动创建objs/subdir1、objs/subdir2这些子目录,避免编译时因为目录不存在报错。
你之前尝试的错误分析
- 错误的后缀替换:
$(FILES:.c=objs/.o)的替换逻辑不对,它不是在路径前加objs/,而是直接替换后缀部分,导致生成的路径完全错误。 - 语法错误的规则:你写的
%.o: %.c:多了一个冒号,这会让Make认为你混合了隐式规则和静态模式规则,直接抛出错误。正确的规则应该是单冒号,并且目标要对应你实际想要生成的objs下的文件。
这样写下来,你就能自动把目标文件生成到和源文件目录结构镜像的objs子目录里了,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Andreas
相关产品推荐
相关产品推荐

