Makefile中指定目标文件输出路径问题咨询
问题原因
你声明的目标是$(BUILD)main.o、$(BUILD)message.o,但编译命令gcc -c $^没有指定输出文件路径,gcc默认会将生成的.o文件命名为源文件同名,存放在Makefile所在的当前工作目录,不会自动匹配你写的目标路径,因此生成的是main.o、message.o而非./build/main.o、./build/message.o,后续链接步骤自然无法从build目录找到目标文件。
修复方案
修改编译命令,通过-o $@指定输出文件为规则的目标路径,同时添加build目录自动创建逻辑,避免目录不存在导致的编译报错:
SHELL := /bin/bash SOURCE = ./src/ BUILD = ./build/ output: $(BUILD)main.o $(BUILD)message.o gcc $^ -o output $(BUILD)main.o: $(SOURCE)main.c | $(BUILD) gcc -c $^ -o $@ $(BUILD)message.o: $(SOURCE)message.c | $(BUILD) gcc -c $^ -o $@ # 自动创建build目录,顺序-only前提不会因目录时间戳变化触发重编译 $(BUILD): mkdir -p $@
其中自动变量$@指代当前规则的目标文件名,也就是你要生成的./build/xxx.o路径,| $(BUILD)表示build目录是顺序前置依赖,仅在目录不存在时执行创建,不会因为目录修改时间变化触发不必要的重编译。
可选优化:通用模式规则
如果后续源文件数量增加,可以用模式规则简化写法,不需要为每个.o单独写编译规则:
SHELL := /bin/bash SOURCE = ./src/ BUILD = ./build/ # 自动扫描src目录下所有.c源文件 SRCS = $(wildcard $(SOURCE)*.c) # 替换为build目录下对应的.o目标文件 OBJS = $(patsubst $(SOURCE)%.c, $(BUILD)%.o, $(SRCS)) output: $(OBJS) gcc $^ -o $@ # 通用模式规则,匹配所有.o的编译逻辑 $(BUILD)%.o: $(SOURCE)%.c | $(BUILD) gcc -c $< -o $@ $(BUILD): mkdir -p $@ # 清理规则,执行make clean即可删除编译产物 .PHONY: clean clean: rm -rf $(BUILD) output
注意事项
Makefile中所有规则下方的命令行必须以Tab缩进,不能用空格替代,否则会触发语法错误。
内容的提问来源于stack exchange,提问作者Rockker
相关产品推荐
相关产品推荐

