当使用rpath时,C++可执行文件无法找到动态链接的共享库

C++ executable cannot find the dynamically-linking shared libraries when using rpath

本文关键字:动态 链接 共享 rpath 可执行文件 C++      更新时间:2023-10-16
大家好,我用和一些poco库为Ubuntu 16.04(g++5.4.0)创建了一个c++应用程序。我需要在以前的Ubuntu 14.04(g++4.8.4)中安装该应用程序。因此,我决定将共享库与可执行文件一起分发。关于libstdc++.so库的分发,我静态地遵循了链接libstdc++的帖子:有什么问题吗?我正在使用以下makefile来构建可执行文件:
CC := g++ 
# Folders
SRCDIR := src
BUILDDIR := build
TARGETDIR := /usr/bin
# Targets
EXECUTABLE := my_app
TARGET := $(TARGETDIR)/$(EXECUTABLE)
SRCEXT := cpp
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
CFLAGS := -c -Wall -std=c++14
INC := -I include
LDFLAGS := '-Wl,-rpath,$$ORIGIN/../share/my_app_data/libs' -L/usr/share/my_app_data/libs
LDLIBS := -lPocoNet -lPocoFoundation -lPocoJSON 
$(TARGET): $(OBJECTS)
@echo " Linking..."
sudo $(CC) $^ -o $@ $(LDFLAGS) $(LDLIBS) 
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
@mkdir -p $(BUILDDIR)
$(CC) $(CFLAGS) $(INC) -c -o $@ $<
clean:
@echo " Cleaning..."; 
sudo $(RM) -r $(BUILDDIR) $(TARGET)

.PHONY: clean

我在/usr/bin中安装了可执行文件,在/usr/share/my_app_data/libs中安装了libs文件夹。当我给出readelf -d my_app时,我在两个Ubuntu版本中都得到了以下内容:

Tag        Type                         Name/Value
0x0000000000000001 (NEEDED)             Shared library: [libPocoFoundation.so.48]
0x0000000000000001 (NEEDED)             Shared library: [libPocoJSON.so.48]
0x0000000000000001 (NEEDED)             Shared library: [libPocoNet.so.48]
0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
0x000000000000000f (RPATH)              Library rpath: [$ORIGIN/../share/my_app_data/libs]

运行my_app时,找不到共享库。我使用文件夹/usr/share/my_app_data/libs更新/etc/ld/so.conf,然后找到与poco相关的库。然而,它找不到libstdc++.so.6,即使libs文件夹中存在libstdc+.so.6.21文件,并且我得到了以下打印输出:

my_app: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by my_app)
my_app: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by my_app)
my_app: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by /usr/share/my_app_data/libs/libPocoFoundation.so.48)
my_app: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by /usr/share/my_app_data/libs/libPocoFoundation.so.48)
my_app: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by /usr/share/my_app_data/libs/libPocoJSON.so.48)
my_app: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by /usr/share/my_app_data/libs/libPocoJSON.so.48)
my_app: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by /usr/share/my_app_data/libs/libPocoNet.so.48)
my_app: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by /usr/share/my_app_data/libs/libPocoNet.so.48)

libs文件夹中ls -l的输出为:

-rwx---rwx 1 root root 2092592 Dec  13 23:06 libPocoFoundation.so.48
-rwx---rwx 1 root root  348488 Dec  13 23:06 libPocoJSON.so.48
-rwx---rwx 1 root root 1225968 Dec  13 23:06 libPocoNet.so.48
lrwxrwxrwx 1 root root      19 Dec  13 23:07 libstdc++.so.6 -> libstdc++.so.6.0.21
-rw----rwx 1 root root 1566440 Dec  13 23:06 libstdc++.so.6.0.21

file libs/*的输出为:

libs/libPocoFoundation.so.48:      ELF 64-bit LSB  shared object, x86-64, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=9b5472754fa836e7be0893d6ed306f63b2cbc4aa, stripped
libs/libPocoJSON.so.48:            ELF 64-bit LSB  shared object, x86-64, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=fb57d0459e72415f90a1fc32b7bb2f695b49c5d7, stripped
libs/libPocoNet.so.48:             ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=175c019baa1ec16d908737443294ed3cf03d3315, stripped
libs/libstdc++.so.6:               symbolic link to `libstdc++.so.6.0.21' 
libs/libstdc++.so.6.0.21:          ELF 64-bit LSB  shared object, x86-64, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=b6d9d56d8e8afa9d4b46a60eda985d45dcd51524, stripped

ldd my_app的输出为:

linux-vdso.so.1 =>  (0x00007ffcbd394000)
libPocoFoundation.so.48 => /usr/bin/./../share/my_app_data/libs/libPocoFoundation.so.48 (0x00007feddb89a000)
libPocoJSON.so.48 => /usr/bin/./../share/my_app_data/libs/libPocoJSON.so.48 (0x00007feddb645000)
libPocoNet.so.48 => /usr/bin/./../share/my_app_data/libs/libPocoNet.so.48 (0x00007feddb317000)
libstdc++.so.6 => /usr/bin/./../share/my_app_data/libs/libstdc++.so.6 (0x00007fedd9f99000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fedd9c7f000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fedd9a68000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fedd96a3000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fedd9485000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fedd9280000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fedd9078000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fedd8180000)
libidn.so.11 => /usr/lib/x86_64-linux-gnu/libidn.so.11 (0x00007fedd7f4d000)
librtmp.so.0 => /usr/lib/x86_64-linux-gnu/librtmp.so.0 (0x00007fedd7d33000)
libgssapi_krb5.so.2 => /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2 (0x00007fedd7aeb000)
liblber-2.4.so.2 => /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2 (0x00007fedd78dc000)
libldap_r-2.4.so.2 => /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2 (0x00007fedd768b000)
libgnutls.so.26 => /usr/lib/x86_64-linux-gnu/libgnutls.so.26 (0x00007fedd73cc000)
libgcrypt.so.11 => /lib/x86_64-linux-gnu/libgcrypt.so.11 (0x00007fedd714c000)
libkrb5.so.3 => /usr/lib/x86_64-linux-gnu/libkrb5.so.3 (0x00007fedd6e81000)
libk5crypto.so.3 => /usr/lib/x86_64-linux-gnu/libk5crypto.so.3 (0x00007fedd6c51000)
libcom_err.so.2 => /lib/x86_64-linux-gnu/libcom_err.so.2 (0x00007fedd6a4d000)
libkrb5support.so.0 => /usr/lib/x86_64-linux-gnu/libkrb5support.so.0 (0x00007fedd6842000)
libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007fedd6626000)
libsasl2.so.2 => /usr/lib/x86_64-linux-gnu/libsasl2.so.2 (0x00007fedd640b000)
libgssapi.so.3 => /usr/lib/x86_64-linux-gnu/libgssapi.so.3 (0x00007fedd61cd000)
libtasn1.so.6 => /usr/lib/x86_64-linux-gnu/libtasn1.so.6 (0x00007fedd5fb8000)
libp11-kit.so.0 => /usr/lib/x86_64-linux-gnu/libp11-kit.so.0 (0x00007fedd5d76000)
libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007fedd5b71000)
libkeyutils.so.1 => /lib/x86_64-linux-gnu/libkeyutils.so.1 (0x00007fedd596c000)
libheimntlm.so.0 => /usr/lib/x86_64-linux-gnu/libheimntlm.so.0 (0x00007fedd5763000)
libkrb5.so.26 => /usr/lib/x86_64-linux-gnu/libkrb5.so.26 (0x00007fedd54da000)
libasn1.so.8 => /usr/lib/x86_64-linux-gnu/libasn1.so.8 (0x00007fedd5239000)
libhcrypto.so.4 => /usr/lib/x86_64-linux-gnu/libhcrypto.so.4 (0x00007fedd5006000)
libroken.so.18 => /usr/lib/x86_64-linux-gnu/libroken.so.18 (0x00007fedd4df0000)
libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007fedd4be8000)
libwind.so.0 => /usr/lib/x86_64-linux-gnu/libwind.so.0 (0x00007fedd49be000)
libheimbase.so.1 => /usr/lib/x86_64-linux-gnu/libheimbase.so.1 (0x00007fedd47b0000)
libhx509.so.5 => /usr/lib/x86_64-linux-gnu/libhx509.so.5 (0x00007fedd4567000)

我还发现,通过在一个库中给出ldd e.x.libPocoFoundation.so.48我得到

libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 

因此,my_app可执行文件显示了libstdc++.So.6的正确路径,而共享库则没有。由于这些库不包含使用chrpath的rpath,是否有另一种方法可以使它们显示

libstdc++.so.6 => /usr/share/npt-data/libs/libstdc++.so.6 

从Natty Narwhal开始,Ubuntu附带的链接器默认使用as-needed。这意味着主可执行文件中没有符号的库将不会被链接。您可以通过添加Wl,--no-as-needed来快速覆盖它。

https://wiki.ubuntu.com/NattyNarwhal/ToolchainTransition