4

我有 Ubuntu 14.04。它带有 openssl 1.0.1f。我想安装另一个 openssl 版本(1.0.2),我想自己编译。

我配置如下:

LDFLAGS='-Wl,--export-dynamic -L/home/myhome/programs/openssl/i/lib 
-L/home/myhome/programs/zlib/i/lib'

CPPFLAGS='-I/home/myhome/programs/openssl/i/include 
-I/home/myhome/programs/zlib/i/include'

./config --prefix=/home/myhome/programs/openssl/i \
zlib-dynamic shared --with-zlib-lib=/home/myhome/programs/zlib/i/lib \
--with-zlib-include=/home/myhome/programs/zlib/i/include

make 

make install

安装后,当我检查二进制文件时ldd openssl,结果是:

...
libssl.so.1.0.0 => /home/myhome/programs/openssl/i/lib/libssl.so.1.0.0 (0x00007f91138c0000)
libcrypto.so.1.0.0 => /home/myhome/programs/openssl/i/lib/libcrypto.so.1.0.0 (0x00007f9113479000)
...

看起来不错。但是当我检查 ldd 时libssl.so,结果是:

...
libcrypto.so.1.0.0 => /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007fac70930000)
...

它仍然使用系统版本的 libcrypto。我尝试了不同的构建方式,但结果始终保持不变。

我的问题是如何以某种方式配置构建,它可以硬编码共享库的所有二进制和库依赖项,而无需使用LD_LIBRARY_PATH,或类似的东西。

4

2 回答 2

2

我的问题是如何以某种方式配置构建,它可以硬编码共享库的所有二进制和库依赖项,而无需使用LD_LIBRARY_PATH,或类似的东西。

OpenSSL 支持RPATH开箱即用的 BSD 目标(但不支持其他目标)。从配置:

# Unlike other OSes (like Solaris, Linux, Tru64, IRIX) BSD run-time
# linkers (tested OpenBSD, NetBSD and FreeBSD) "demand" RPATH set on
# .so objects. Apparently application RPATH is not global and does
# not apply to .so linked with other .so. Problem manifests itself
# when libssl.so fails to load libcrypto.so. One can argue that we
# should engrave this into Makefile.shared rules or into BSD-* config
# lines above. Meanwhile let's try to be cautious and pass -rpath to
# linker only when --prefix is not /usr.
if ($target =~ /^BSD\-/)
    {
    $shared_ldflag.=" -Wl,-rpath,\$(LIBRPATH)" if ($prefix !~ m|^/usr[/]*$|);
    }

对 OpenSSL 1.0.2 执行此操作的最简单方法似乎是将其添加为CFLAG

./config -Wl,-rpath=/usr/local/ssl/lib

对 OpenSSL 1.0.2 执行此操作的下一个最简单方法似乎是添加配置行并将rpath. 例如,我正在研究 Debian x86_64。Configure所以我在编辑器中打开文件,复制linux-x86_64,命名它linux-x86_64-rpath,并进行以下更改以添加-rpath选项:

"linux-x86_64-rpath",   "gcc:-m64 -DL_ENDIAN -O3 -Wall -Wl,-rpath=/usr/local/ssl/lib::
-D_REENTRANT::-Wl,-rpath=/usr/local/ssl/lib -ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:
${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",

上面,字段 2 和 6 已更改。它们对应于$cflag$ldflag在 OpenSSL 的构建系统中。

然后,使用新配置进行配置:

$ ./Configure linux-x86_64-rpath shared no-ssl2 no-ssl3 no-comp \
    --openssldir=/usr/local/ssl enable-ec_nistp_64_gcc_128

最后,在 之后make,验证设置卡住:

$ readelf -d ./libssl.so | grep -i rpath
 0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]
$ readelf -d ./libcrypto.so | grep -i rpath
 0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]
$ readelf -d ./apps/openssl | grep -i rpath 
 0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]

一旦你执行make install, thenldd将产生预期的结果:

$ ldd /usr/local/ssl/lib/libssl.so
    linux-vdso.so.1 =>  (0x00007ffceff6c000)
    libcrypto.so.1.0.0 => /usr/local/ssl/lib/libcrypto.so.1.0.0 (0x00007ff5eff96000)
    ...

$ ldd /usr/local/ssl/bin/openssl 
    linux-vdso.so.1 =>  (0x00007ffc30d3a000)
    libssl.so.1.0.0 => /usr/local/ssl/lib/libssl.so.1.0.0 (0x00007f9e8372e000)
    libcrypto.so.1.0.0 => /usr/local/ssl/lib/libcrypto.so.1.0.0 (0x00007f9e832c0000)
    ...

OpenSSL在其 wiki 上有一个编译和安装。现在已将其添加到 wiki 的编译和安装 | 使用 RPATH

于 2015-04-26T20:35:05.437 回答
2

现在是 2019 年,OpenSSL 可能发生了一些变化,所以我将描述我是如何解决这个问题的,如果其他人可能会发现它很有用(如果我需要再次为自己弄清楚这个命令行参数)。

我想以一种可以交叉编译的方式构建 OpenSSL(使用 docker 容器,因为我正在处理非常古老的 Linux 内核和现代编译器),但提供一个不依赖于绝对路径的安装,就像这种情况一样使用 rpath 正如我在 jww 的回答中所描述的那样。

我发现我可以以这种方式运行 OpenSSL 的配置脚本来实现我想要的(从 bash 提示符):

./Configure linux-x86 zlib shared -Wl,-rpath=\\\$\$ORIGIN/../lib

这会导致生成的 Makefile 以一种使加载程序首先在“./../lib”(相对于可执行文件或共享对象的位置)中查找依赖项的方式构建可执行文件和共享对象,然后在LD_LIBRARY_PATH 等。这种古怪的字符组合正确地通过了 bash 命令行、脚本和 Makefile 组合,以根据链接器的要求($ORIGIN/../lib)创建 -rpath 参数。

(显然,选择对您有意义的其他选项。这里的关键在-Wl,-rpath=\\\$\$ORIGIN/../lib选项中)。

因此,如果我使用前缀“--prefix=/opt/spiffness”调用 ./Configure,然后决定将“spiffness”重命名为“guttersnipe”,那么一切仍将正常工作,因为路径是相对的而不是绝对的.

我没有尝试将参数传递到 ./config 以查看它是否在那里工作,因为我的用例有点特殊,但我怀疑它会。如果我不尝试使用 dockerized 容器进行交叉编译,我更喜欢使用 ./config 而不是 ./Configure,因为它可以很好地检查当前环境以查看要创建的二进制文件类型。

我希望这是有用的。

于 2019-05-17T09:40:38.370 回答