执行make命令生成.so文件时遇‘undefined reference’错误求助
问题排查与解决方案
核心错误原因
你的链接错误源于Makefile中共享库的生成逻辑、参数配置存在多处问题,导致单个独立的.so文件无法找到跨文件的函数实现。以下是具体问题点和修正方案:
具体问题分析
头文件路径配置错误
CFLAGS中的-I /usr/lib完全无效,应该指向subfolder/includes目录,否则编译时无法识别自定义头文件,可能引发函数声明缺失或不匹配。共享库生成方式错误
当前规则将每个.c文件单独编译为.so,导致每个共享库仅包含单个源文件的代码。当某个.so中的函数调用另一个.so的函数时,由于未在生成共享库时处理依赖,必然出现未定义引用。LIBS参数配置错误
-L后未指定库搜索路径,直接跟-lpq会让链接器误将-lpq当作路径处理,无法找到PostgreSQL库;-Wl,-rpath后缺少具体的运行时库搜索路径,程序运行时可能找不到共享库。
可执行文件链接逻辑错误
直接将所有独立.so文件作为输入链接成可执行文件,不符合共享库的标准使用方式,应该链接整合后的共享库而非零散文件。
修正后的Makefile
APP := Test_app APP_INSTALL_DIR ?= /home # 区分主程序和子模块源文件 MAIN_SRC := main.c SUB_SRCS := $(wildcard subfolder/srcs/*.c) # 头文件路径 + 共享库必需的位置无关代码编译选项 CFLAGS := -I subfolder/includes -fPIC # 按需添加系统头文件路径(比如PostgreSQL的头文件路径) # CFLAGS += -I /usr/include/postgresql # 修正库参数:指定库搜索路径、运行时路径,链接必要系统库 LIBS := -L. -lpq -ldl -Wl,-rpath=. # 子模块目标文件与共享库 SUB_OBJS := $(SUB_SRCS:.c=.o) SUB_SO := libsub.so all: $(APP) # 编译子模块目标文件 %.o: %.c $(wildcard subfolder/includes/*.h) Makefile $(CC) -c -o $@ $(CFLAGS) $< # 将子模块所有目标文件打包为一个共享库 $(SUB_SO): $(SUB_OBJS) Makefile $(CC) -shared -o $@ $^ $(LIBS) # 编译主程序并链接共享库 $(APP): $(MAIN_SRC) $(SUB_SO) Makefile $(CC) -o $@ $(MAIN_SRC) $(CFLAGS) -lsub $(LIBS) install: $(APP) cp -rv $(APP) $(SUB_SO) $(APP_INSTALL_DIR) clean: rm -rf $(SUB_OBJS) $(APP) $(SUB_SO)
关键修正说明
- 添加
-fPIC:生成共享库必须使用位置无关代码,这是链接器的强制要求; - 合并子模块为单个共享库:将subfolder下的所有源文件编译为目标文件后打包成
libsub.so,确保所有函数实现都在同一个库中,解决跨文件引用问题; - 修正头文件与库路径:明确指定自定义头文件路径和库搜索路径,避免链接器找不到依赖;
- 标准化可执行文件链接:直接编译main.c并通过
-lsub链接生成的共享库,符合Linux共享库的使用规范。
如果function_name来自第三方系统库而非自定义代码,请确保对应的库已添加到LIBS中(例如添加-lxxx)。
内容的提问来源于stack exchange,提问作者Basavaraj Kittali
相关产品推荐
相关产品推荐

