Erlang的crypto模块与最新的openssl动态链接库不兼容的问题与解决方案

在2014新年伊始,增买了一台阿里云服务器,装的系统是CentOS 6.3 64位,装完Erlang后,出现了下面的情况:
./configure --without-javac --with-ssl=/usr/local/ssl --enable-hipe --enable-threads --enable-smp-support --enable-kernel-poll
make
make install


Eshell V5.10.4 (abort with ^G)
1> crypto:start().
** exception error: undefined function crypto:start/0
2>
=ERROR REPORT==== 5-Jan-2014::14:40:26 ===
Unable to load crypto library. Failed with error:
"load_failed, Failed to load NIF library: '/usr/local/lib/erlang/lib/crypto-3.2/priv/lib/crypto.so: undefined symbol: EC_GROUP_new_curve_GF2m'"
OpenSSL might not be installed on this system.
=ERROR REPORT==== 5-Jan-2014::14:40:26 ===
The on_load function for module crypto returned {error,
{load_failed,
"Failed to load NIF library: '/usr/local/lib/erlang/lib/crypto-3.2/priv/lib/crypto.so: undefined symbol: EC_GROUP_new_curve_GF2m'"}}
它提示我可能是没有安装openssl,但我可以确定是有装的,这是让我折腾纠结的开始。。。
于是就重装openssl,怀疑是erlang对最新版本的openssl支持不友好,一次次尝试之后,仍没有解决问题。

然后我单独去编译Erlang的crypto模块,出现了以下情况:
[root@AY140104155419164de9Z crypto]# pwd
/root/otp_src_R16B03/lib/crypto
[root@AY140104155419164de9Z crypto]# make
=== Entering application crypto
...
make[2]: Entering directory `/root/otp_src_R16B03/lib/crypto/c_src'
/usr/bin/install -c -d ../priv/obj/x86_64-unknown-linux-gnu
gcc -c -o ../priv/obj/x86_64-unknown-linux-gnu/crypto.o -Werror=return-type -Wall -Wstrict-prototypes -Wmissing-prototypes -Wdeclaration-after-statement -DUSE_THREADS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS -D_POSIX_THREAD_SAFE_FUNCTIONS -g -O2 -I/root/otp_src_R16B03/erts/x86_64-unknown-linux-gnu -fno-tree-copyrename -D_GNU_SOURCE -fPIC -DHAVE_DYNAMIC_CRYPTO_LIB -I/usr/include -I/usr/include -I/root/otp_src_R16B03/erts/emulator/beam -I/root/otp_src_R16B03/erts/include -I/root/otp_src_R16B03/erts/include/x86_64-unknown-linux-gnu -I/root/otp_src_R16B03/erts/include/internal -I/root/otp_src_R16B03/erts/include/internal/x86_64-unknown-linux-gnu -I/root/otp_src_R16B03/erts/emulator/sys/unix crypto.c
crypto.c: In function ‘ec_key_new’:
crypto.c:3018: warning: implicit declaration of function ‘EC_GROUP_new_curve_GF2m’
crypto.c:3018: warning: assignment makes pointer from integer without a cast
/usr/bin/install -c -d ../priv/lib/x86_64-unknown-linux-gnu
看到这些信息之后,开始猜测是最新版本的openssl的动态链接库有问题,
也请教了余峰老大,叫我在centos 6.2环境下测试一下,
于是在一台老服务器上编译当前最新版的erlang R16B03,没有出现问题,
但是,更新了OpenSSL后,同样的问题出现了。 
[Rolong] ~# yum -y install openssl
...
Resolving Dependencies
--> Running transaction check
---> Package openssl.x86_64 0:1.0.0-27.el6_4.2 will be updated
--> Processing Dependency: openssl = 1.0.0-27.el6_4.2 for package: openssl-devel-1.0.0-27.el6_4.2.x86_64
---> Package openssl.x86_64 0:1.0.1e-16.el6_5.1 will be an update
--> Running transaction check
---> Package openssl-devel.x86_64 0:1.0.0-27.el6_4.2 will be updated
---> Package openssl-devel.x86_64 0:1.0.1e-16.el6_5.1 will be an update
--> Finished Dependency Resolution
openssl被更新后就出问题了,所以新安装的系统,默认都是新版本的openssl,这种环境下安装Erlang都会遇到和上面一样的问题。

新版本的openssl编译出来的动态链接库的问题?于是我下载了几个版本(包括最新的)的openssl源码来安装尝试,都一样的在编译erlang的crypto模块时出现了新的错误,主要是提示了这一句:
/usr/bin/ld: /usr/local/ssl/lib/libcrypto.a(cryptlib.o): relocation R_X86_64_32 against `OPENSSL_ia32cap_P' can not be used when making a shared object; recompile with -fPIC
从这里知道了openssl默认编译出来的libcrypto.a是没有加-fPIC参数的,当重定位被引用的代码段数据对象时出错了,于是打开openssl源码的Makefile,做如下修改:


CC= gcc
CFLAG= -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -Wa,--noexecstack -m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM
DEPFLAG= -DOPENSSL_NO_EC_NISTP_64_GCC_128 -DOPENSSL_NO_GMP -DOPENSSL_NO_JPAKE -DOPENSSL_NO_MD2 -DOPENSSL_NO_RC5 -DOPENSSL_NO_RFC3779 -DOPENSSL_NO_SCTP -DOPENSSL_NO_STORE

# CFLAG加上-fPIC参数,以相对地址的方式编译链接库。修改后:

CC= gcc
CFLAG= -fPIC -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -Wa,--noexecstack -m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM
DEPFLAG= -DOPENSSL_NO_EC_NISTP_64_GCC_128 -DOPENSSL_NO_GMP -DOPENSSL_NO_JPAKE -DOPENSSL_NO_MD2 -DOPENSSL_NO_RC5 -DOPENSSL_NO_RFC3779 -DOPENSSL_NO_SCTP -DOPENSSL_NO_STORE
修改后重新编译链接,问题就解决了。

PS:如果安装了多个版本并且安装在不同位置的情况下,要确保编译crypto时是用到了你加了-fPIC后编译出来的openssl动态库,因为Makefile中设置了多个搜索路径,也可以按实际情况对Makefile稍作修改。

更具体说明请见:http://blog.csdn.net/zhongruixian/article/details/21076405

转载请注明出处,原文链接:http://blog.csdn.net/zhongruixian/article/details/17929831

你可能感兴趣的:(Erlang源码分析)