多源码树外置构建Makefile问题:跨目录源码目标文件路径不符预期
Makefile编译多目录源码到指定build目录问题解决
问题描述
我写了个简易Makefile,想把SRC_DIRS指定的多个目录下的.c文件编译成单个可执行文件。源码文件放在./src和../pmlin/src/master目录,要求中间文件输出到./build目录。
目前遇到的问题:./src下的文件能正确编译到./build目录,但../pmlin/src/master下的文件还是生成在原目录,没到预期的./build/pmlin/master路径。试了用pathsubst移除OBJS路径里的../,折腾几小时没解决,当前Makefile代码如下:
TARGET_EXEC = aslac-calibrator BUILD_DIR = ./build SRC_DIRS = ./src ../pmlin/src/master SRCS := $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.c)) OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) DEPS := $(OBJS:.o=.d) INC_DIRS := $(shell find $(SRC_DIRS) -type d) ../pmlin/src ../pmlin/src/devices INC_FLAGS := $(addprefix -I,$(INC_DIRS)) CPPFLAGS ?= $(INC_FLAGS) -MMD -MP $(TARGET_EXEC): $(OBJS) $(CC) $(OBJS) -o $@ $(LDFLAGS) $(BUILD_DIR)/%.c.o: %.c $(MKDIR_P) $(dir $@) $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ .PHONY: clean clean: $(RM) -r $(BUILD_DIR) -include $(DEPS) MKDIR_P ?= mkdir -p
解决方案
核心问题是原规则里的../会被Make解析为上层目录,导致目标路径实际等价于原源码目录,需要先清理掉路径里的../,再映射到build目录。修改后的Makefile如下:
TARGET_EXEC = aslac-calibrator BUILD_DIR = ./build SRC_DIRS = ./src ../pmlin/src/master # 遍历获取所有.c源码文件 SRCS := $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.c)) # 处理路径:先把源码路径拼到BUILD_DIR下,再移除开头的../,最后替换为.o后缀 OBJS := $(SRCS:%=$(BUILD_DIR)/%) OBJS := $(OBJS:../%=%) OBJS := $(OBJS:.c=.o) DEPS := $(OBJS:.o=.d) INC_DIRS := $(shell find $(SRC_DIRS) -type d) ../pmlin/src ../pmlin/src/devices INC_FLAGS := $(addprefix -I,$(INC_DIRS)) CPPFLAGS ?= $(INC_FLAGS) -MMD -MP $(TARGET_EXEC): $(OBJS) $(CC) $(OBJS) -o $@ $(LDFLAGS) # 通用模式规则,匹配所有.c文件到对应build目录下的.o文件 $(BUILD_DIR)/%.o: %.c $(MKDIR_P) $(dir $@) $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ .PHONY: clean clean: $(RM) -r $(BUILD_DIR) -include $(DEPS) MKDIR_P ?= mkdir -p
关键修改说明
- 调整OBJS生成逻辑:
原代码里$(SRCS:%=$(BUILD_DIR)/%.o)会把../pmlin/src/master/file.c变成./build/../pmlin/src/master/file.c.o,而./build/../等价于当前目录,所以文件还是生成在原路径附近。修改后先把源码路径拼到BUILD_DIR下,再用$(OBJS:../%=%)去掉开头的../,最后替换成.o,得到正确的./build/pmlin/src/master/file.o路径。 - 修改模式规则:
把$(BUILD_DIR)/%.c.o: %.c改成$(BUILD_DIR)/%.o: %.c,因为现在OBJS的后缀直接是.o,不需要额外的.c.o,确保规则能正确匹配所有目标文件。
内容的提问来源于stack exchange,提问作者nyholku
相关产品推荐
相关产品推荐

