- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我有:
/usr/lib/libsomething.so.1
在机器 A 上;/usr/lib/libsomething.so.2
在机器 B 上。两台机器都有 /usr/lib/libsomething.so
符号链接(symbolic link)到各自的库。
如果我使用 gcc
与 -lsomething
(甚至 /usr/lib/libsomething.so
)链接,它将遵循符号链接(symbolic link),机器 A 上的 ldd 会生成如下内容:
libsomething.so.1 => /usr/lib/libsomething.so.1
这意味着它将无法在机器 B 上找到该库。
现在我知道这些是主要版本号更改,并且我知道它们可能不兼容,但我愿意冒这个风险。我想告诉链接器的是寻找 libsomething.so
,并且不要遵循符号链接(symbolic link),这样 ldd
将显示
libsomething.so => /usr/lib/libsomething.so.1
在A但是
libsomething.so => /usr/lib/libsomething.so.2
在 B 上。然后加载程序将按照符号链接(symbolic link)到达那里的任何版本。
另外,我不想使用 dlopen 或其他任何东西延迟加载。我希望它在编译时链接到共享对象。
这可能吗?
最佳答案
制作使用任何可用版本的共享库的可执行文件当然是可能的。
问题是您将可执行文件链接到特定于版本的soname(libsomething.so.1
和libsomething.so.2
) 。您应该使用未版本化的soname libsomething.so
来完成此操作。
为了实现这一点,在构建机器上,您应该编译并安装soname(ELF SONAME
)等于libsomething.so
(没有版本)的库,以便链接器可以在构建可执行文件时选择此soname。
根据Shared Libraries HOWTO ,您可以在构建库时传递所需的未版本化的soname:
gcc -shared -Wl,-soname,libsomething.so -o libsomething.so.X objectsomething.o
然后,一旦您安装了库并运行 ldconfig
,您就可以:
/lib/libsomething.so
指向机器A上的/lib/libsomething.so.1
;/lib/libsomething.so
指向机器B上的/lib/libsomething.so.2
。加载程序(运行ldd
)将选择未版本化的符号链接(symbolic link),无论它指向何处:
libsomething.so =>/lib/libsomething.so (0xNNNNNNNN)
在机器 A 上;libsomething.so =>/lib/libsomething.so (0xNNNNNNNN)
在机器 B 上。Linux 动态加载器 (ld.so
) 根据可执行文件中写入的 soname 值来解析库 (ELF NEEDED
)。该值是在构建可执行文件时从库文件 (ELF SONAME
) 复制的。只要目标系统上存在与可执行文件中记录的soname匹配的符号链接(symbolic link),就会加载该符号链接(symbolic link)指向的库。
让我们运行一下您的设置并显示命令来验证假设。
我使用 Fedora 18 X86_64
进行测试,并为了清晰起见将输出调整为 i686
。
编译 libsomething.so.1
和 libsomething.so.2
。确保 SONAME
设置为未版本化的 libsomething.so
:
readelf -a libsomething.so.1 | grep SONAME
0xNNNNNNNN (SONAME) Library soname: [libsomething.so]
readelf -a libsomething.so.2 | grep SONAME
0xNNNNNNNN (SONAME) Library soname: [libsomething.so]
将库安装到各自计算机的 /lib/
目录下。在两台计算机上运行 ldconfig -v 并验证输出。
ldconfig -v 2>&1 | grep something
libsomething.so -> libsomething.so.1 (changed)
ldconfig -v 2>&1 | grep something
libsomething.so -> libsomething.so.2 (changed)
编译可执行文件并确保它引用相同的soname,但NEEDED
中没有版本。
readelf -a executable | grep NEEDED
0xNNNNNNNN (NEEDED) Shared library: [libsomething.so]
您的可执行文件现在依赖于未版本化的libsomething.so
。将可执行文件复制到两台计算机并针对两个副本运行 ldd
。
ldd executable
libsomething.so => /lib/libsomething.so (0xNNNNNNNN)
最后的输出在两台机器上是相同的,因为可执行文件是使用 soname 构建的,没有版本。这使得加载程序在目标机器上采用未版本化的符号链接(symbolic link)。根据机器的不同,符号链接(symbolic link)可以指向库 libsomething.so.1
或 libsomething.so.2
的不同实现。
关于GCC 链接到共享对象的链接器名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4685493/
我正在开发一个 voip 调用应用程序。我需要做的是在接到来电时将 Activity 带到前台。我在应用程序中使用 Twilio,并在收到推送消息时开始调用。 问题是我试图在接到任何电话时显示 Act
我是一名优秀的程序员,十分优秀!