使用RPATH构建OpenSSL?

时间:2015-04-24 22:58:05

标签: linux openssl ldd rpath

我有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或类似的东西。

2 个答案:

答案 0 :(得分:1)

  

我的问题是如何以某种方式配置构建,它可以硬编码共享库的所有二进制和库依赖项而不使用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已更改。它们对应于OpenSSL构建系统中的$cflag$ldflag

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

$ ./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后,ldd将产生预期结果:

$ 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上有Compilation and Installation。这已经添加到了Compilation and Installation | Using RPATHs

的wiki中

答案 1 :(得分:0)

现在是2019年,OpenSSL可能已经发生了一些变化,所以我将描述我如何解决这个问题,其他人可能会发现它很有用(并且万一我需要再次找出该命令行参数以供参考)我自己)。

我想以一种可以交叉编译的方式构建OpenSSL(使用docker容器,因为我处理的是陈旧的Linux内核,而现代的编译器),但是提供了不依赖绝对路径的安装,就像我在jww的答案中所描述的那样使用rpath就是这种情况。

我发现我可以通过这种方式运行OpenSSL的Configure脚本来实现我想要的功能(从bash提示符):

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

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

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

因此,如果我使用前缀'--prefix = / opt / spiffness'调用./Configure,后来又决定将'spiffness'重命名为'guttersnipe',则由于路径是相对的,所以一切仍然可以正常工作而不是绝对的。

由于我的用例有点特殊,所以我没有尝试将参数传递到./config来查看它是否在这里工作,但是我怀疑是可以的。如果我不打算与dockerized容器进行交叉编译,我宁愿使用./config而不是./Configure,因为这样做可以很好地检查当前环境以查看要创建哪种二进制文件。

我希望这是有用的。