You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

链接不同符号版本库失败:libdeezer依赖libcurl符号缺失问题

问题描述

我正在构建一个名为exampleprog(实际编译目标为NanoPlayer)的程序,该程序仅能依赖共享库libdeezer.so。libdeezer.so依赖libcurl等库,但构建时链接器无法找到libcurl的相关函数,make输出报错如下:

gcc -o NanoPlayer main.o -L../libdeezer/SDK/Bins/Platforms/Linux/x86_64 -Wl,-rpath=../libdeezer/SDK/Bins/Platforms/Linux/x86_64 -ldeezer -lcurl
/usr/bin/ld: ../libdeezer/SDK/Bins/Platforms/Linux/x86_64/libdeezer.so: undefined reference to `curl_multi_assign@CURL_OPENSSL_3'
[...]
/usr/bin/ld: ../libdeezer/SDK/Bins/Platforms/Linux/x86_64/libdeezer.so: undefined reference to `curl_global_cleanup@CURL_OPENSSL_3'
/usr/bin/ld: ../libdeezer/SDK/Bins/Platforms/Linux/x86_64/libdeezer.so: undefined reference to `curl_easy_recv@CURL_OPENSSL_3'

执行ldd libdeezer.so的输出为:

./libdeezer.so: /lib64/libcurl.so.4: no version information available (required by ./libdeezer.so)
    linux-vdso.so.1 (0x00007ffde5920000)
    libssl.so.1.0.0 => /lib64/libssl.so.1.0.0 (0x00007fba07993000)
    libcrypto.so.1.0.0 => /lib64/libcrypto.so.1.0.0 (0x00007fba077b4000)
    libcurl.so.4 => /lib64/libcurl.so.4 (0x00007fba07706000)
    [...]

使用的Makefile内容如下:

LIBDEEZER_DIR=../libdeezer/SDK
LIBDEEZER_INC_DIR=$(LIBDEEZER_DIR)/Include
LIBDEEZER_LIB_DIR=$(LIBDEEZER_DIR)/Bins/Platforms/Linux/x86_64

#Set tools and flags
CC=gcc
CFLAGS=-W -Wall -I$(LIBDEEZER_INC_DIR) -Wno-unused-parameter
LDFLAGS=-L$(LIBDEEZER_LIB_DIR) -Wl,-rpath=$(LIBDEEZER_LIB_DIR) -ldeezer -lcurl
EXEC=NanoPlayer

all: $(EXEC)

NanoPlayer: main.o
    $(CC) -o $@ $^ $(LDFLAGS)

# Build every source files
%.o: %.c
    $(CC) -o $@ -c $< $(CFLAGS)

.PHONY: clean mrproper

# Clean every temporary files
clean:
    rm -rf *.o

# Clean everything than can be generated
mrproper: clean
    rm -rf $(EXEC)

libcurl的符号定义如下:

~ readelf -sW /lib64/libcurl.so.4.8.0 | grep -E "curl_multi_assign|memcmp"
    95: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND memcmp@GLIBC_2.2.5 (3)
   508: 000000000004cfa0   108 FUNC    GLOBAL DEFAULT   14 curl_multi_assign

可见curl_multi_assign函数无符号版本,而memcmp等函数带有符号版本。已尝试用patchelf修改libcurl的soname,以及编译带--with-ssl选项的旧版本libcurl,但问题未解决。想问:能否修改libcurl的符号版本,或告知链接器使用无版本符号?

解决方案

方法1:让链接器忽略符号版本要求

直接通过链接器选项-Wl,--undefined-version告诉ld忽略未找到的符号版本,绑定到无版本符号。修改Makefile中的LDFLAGS:

LDFLAGS=-L$(LIBDEEZER_LIB_DIR) -Wl,-rpath=$(LIBDEEZER_LIB_DIR),--undefined-version -ldeezer -lcurl

这个选项会让链接器对所有未匹配到版本的符号,直接使用系统中无版本的对应符号,适配你当前libcurl的状态。

方法2:创建符号包装库(更稳妥)

如果方法1兼容性不佳,可手动创建小型包装库,将带版本的符号重定向到无版本符号:

  1. 创建curl_wrap.c文件:
#define _GNU_SOURCE
#include <dlfcn.h>

// 重定向带版本符号到系统libcurl的无版本符号
void curl_global_cleanup(void) {
    static void (*func)(void) = NULL;
    if (!func) func = dlsym(RTLD_NEXT, "curl_global_cleanup");
    func();
}

CURLMcode curl_multi_assign(CURLM *multi_handle, curl_socket_t sockfd, void *sockptr) {
    static CURLMcode (*func)(CURLM*, curl_socket_t, void*) = NULL;
    if (!func) func = dlsym(RTLD_NEXT, "curl_multi_assign");
    return func(multi_handle, sockfd, sockptr);
}

CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n) {
    static CURLcode (*func)(CURL*, void*, size_t, size_t*) = NULL;
    if (!func) func = dlsym(RTLD_NEXT, "curl_easy_recv");
    return func(curl, buffer, buflen, n);
}
// 按需添加其他报错的带版本符号
  1. 编译为共享库:
gcc -fPIC -shared -o libcurl_wrap.so curl_wrap.c -ldl
  1. 修改Makefile的LDFLAGS,优先链接包装库:
LDFLAGS=-L$(LIBDEEZER_LIB_DIR) -Wl,-rpath=$(LIBDEEZER_LIB_DIR) -L. -lcurl_wrap -ldeezer -lcurl

这样libdeezer.so会先找到包装库中的带版本符号,再由包装库调用系统libcurl的无版本符号。

方法3:替换匹配版本的libcurl

若上述方法都不满足需求,需找到或编译带有CURL_OPENSSL_3版本符号的libcurl:

  • 用objdump -x ../libdeezer/SDK/Bins/Platforms/Linux/x86_64/libdeezer.so | grep CURL_OPENSSL查看libdeezer.so要求的具体版本。
  • 下载对应版本的libcurl源码,编译时确保使用与libdeezer.so依赖的libssl.so.1.0.0匹配的OpenSSL版本,安装到本地目录后,在Makefile中指定该目录的-L和-rpath路径。

内容的提问来源于stack exchange,提问作者Gwendal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 14:17:05