Makefile中LINK.cc致main.o置于链接库后引发错误的修复方法
解决Makefile链接阶段的文件顺序问题
碰到链接顺序的问题是吧?我帮你捋清楚怎么改。
你的核心问题是现在生成的链接命令里,库(-lrabbitmq这些)跑到了目标文件(main.o、utils.o)前面,而GCC是按从左到右的顺序处理符号引用的——只有当目标文件出现在库的前面时,库才能正确解析目标文件里的未定义符号。
先看你当前Makefile的问题:你把所有链接库都塞进了LDFLAGS里,但你定义的LINK.cc规则是先展开LDFLAGS,再放目标文件,这就导致库的位置完全反了。
修复方案
Make其实有专门的变量用来存链接库——LDLIBS,这个变量的默认位置就是在目标文件之后,正好符合GCC的要求。我们只需要调整变量的使用:
- 把原来加到
LDFLAGS里的库移到LDLIBS中 - 调整
LINK.cc的定义和链接命令的顺序,确保目标文件在前,库在后
修改后的完整Makefile
program_NAME := myprogram program_C_SRCS := $(wildcard *.c) program_CXX_SRCS := $(wildcard *.cpp) program_C_OBJS := ${program_C_SRCS:.c=.o} program_CXX_OBJS := ${program_CXX_SRCS:.cpp=.o} program_OBJS := $(program_C_OBJS) $(program_CXX_OBJS) program_INCLUDE_DIRS := ./include /usr/local/include/upm program_LIBRARY_DIRS := /usr/local/lib/x86_64-linux-gnu /usr/local/lib/ program_LIBRARIES := rabbitmq upmc-rn2483 upmc-utilities upmc-rn2903 CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir)) # LDFLAGS只保留库目录的-L参数 LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir)) # 把链接库放到LDLIBS这个专门的变量里 LDLIBS += $(foreach library,$(program_LIBRARIES),-l$(library)) CC = gcc CXX = g++ # 调整LINK.cc,去掉原来的LDFLAGS,我们会在链接命令里正确放置 LINK.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) LINK.o = $(CC) $(TARGET_ARCH) .PHONY: all clean distclean all: $(program_NAME) # 链接命令:先目标文件,再LDFLAGS(库目录),最后LDLIBS(库) $(program_NAME): $(program_OBJS) $(LINK.cc) $(program_OBJS) $(LDFLAGS) $(LDLIBS) -o $(program_NAME) clean: @- $(RM) $(program_NAME) @- $(RM) $(program_OBJS) distclean: clean
为什么这样改?
LDLIBS是Make的标准变量,专门用于指定链接库,它的设计就是要放在目标文件之后,完美匹配GCC的链接顺序要求。- 把
LDFLAGS和LDLIBS分开:LDFLAGS放链接选项(比如-L、-Wl,xxx这类),LDLIBS放库(-lxxx),这也是Make的惯例,能避免顺序问题。 - 修改后的链接命令会先处理所有目标文件,再去加载库,这样库就能正确解析目标文件里的符号引用了。
现在运行make,生成的命令应该就和你想要的正确顺序一致了!
内容的提问来源于stack exchange,提问作者arcoxia tom
相关产品推荐
相关产品推荐

