Makefile链接错误及utils.c未编译问题求助
问题分析与解决方案
1. 关于IBS的疑问
你猜的完全没错!IBS几乎可以肯定是LIBS漏写了字母L——在Makefile的约定俗成用法里,LIBS就是用来定义链接阶段需要引入的库文件的变量,IBS本身没有任何通用的Makefile含义,这明显是笔误导致的。
2. 为什么utils.c没有被编译?
你的Makefile存在几个关键问题,直接导致make没有处理utils.c:
问题1:find命令的逻辑优先级错误
在SRCS的定义中:
SRCS := $(shell find $(SRC_DIRS) -name *.cpp -or -name *.c -or -name *.s)
find命令里-and的优先级高于-or,这会让实际的匹配逻辑跑偏。正确的写法应该用括号把所有文件名匹配条件括起来,同时给文件名模式加引号避免shell提前展开:
SRCS := $(shell find $(SRC_DIRS) \( -name "*.cpp" -o -name "*.c" -o -name "*.s" \))
问题2:目标文件生成路径不匹配
你的.c.o规则里:
$(BUILD_DIR)/%.c.o: %.c $(MKDIR_P) $(dir $@) $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@.o $(CC) $(LD_FLAGS) $@.o -o $@ $LIBS
这里的目标是$(BUILD_DIR)/%.c.o,但实际生成的文件是$@.o(比如build/src/main.c.o.o),和OBJS变量里定义的路径完全不匹配。make会误以为目标已经“完成”,自然不会去处理utils.c这类其他源文件。
另外,这个规则里还多写了链接命令——链接只需要在生成最终可执行文件时做一次,每个源文件编译完就链接纯属画蛇添足。
问题3:链接变量名不一致
你定义了LD_FLAGS,但在最终可执行文件的规则里用的是$(LDFLAGS)(少了下划线),这会导致链接阶段根本加载不到你指定的库路径。
修正后的Makefile
下面是修复了所有问题的版本:
TARGET_EXEC ?= app.out BUILD_DIR ?= ./build SRC_DIRS ?= ./src # 正确查找所有源文件 SRCS := $(shell find $(SRC_DIRS) \( -name "*.cpp" -o -name "*.c" -o -name "*.s" \)) OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) DEPS := $(OBJS:.o=.d) INC_DIRS := $(shell find $(SRC_DIRS) -type d) INC_FLAGS := $(addprefix -I,$(INC_DIRS)) -I/usr/local/include/upm # 统一变量名,把LIBS整合到链接参数里 CPPFLAGS ?= $(INC_FLAGS) -MMD -MP LDFLAGS := -L/usr/local/lib/upm -L/usr/lib/rabbitmq LIBS := -lrabbitmq -lupmc-rn2483 -lupmc-rn2903 -lupmc-utilities # 生成最终可执行文件的规则 $(BUILD_DIR)/$(TARGET_EXEC): $(OBJS) $(MKDIR_P) $(dir $@) $(CC) $(OBJS) -o $@ $(LDFLAGS) $(LIBS) # C源文件编译规则 $(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
修正说明:
- 修复了
find命令的逻辑,确保能正确扫到所有.c/.cpp/.s文件 - 移除了编译规则里的冗余链接命令,只在生成最终可执行文件时统一链接
- 统一了链接变量名为
LDFLAGS,并在链接命令中加入$(LIBS) - 修正了目标文件的生成路径,让
OBJS里的路径和实际生成的文件完全匹配
现在执行make,应该会正常编译main.c和utils.c,并正确链接所有依赖库了。
内容的提问来源于stack exchange,提问作者arcoxia tom
相关产品推荐
相关产品推荐

