一,前言
我喜欢新的东西,所以就第二轮学习linux驱动,都要去下载最新的官方源码。结果就遇到坑了。
二,问题记录
我的环境是ubuntu14.04 64bit(之前因为qemu2.8的STM特制版本只能在14及以下才能编译过,所以系统我就用了老版本的ubuntu)于是问题就来了。
make编译uboot到了最后出现了报错。
tools/sunxi_toc0.o: In function `toc0_verify_header':
sunxi_toc0.c:(.text+0x467): undefined reference to `RSA_set0_key'
sunxi_toc0.c:(.text+0x47e): undefined reference to `RSA_get0_n'
sunxi_toc0.c:(.text+0x49c): undefined reference to `RSA_get0_e'
1)分析:我很久不用了,所以第一反应arm-gcc中缺少openssl的库?
答:后来网上搜索了这类报错,说是要升级openssl版本即可。此时我就混乱了,不是在编译arm代码,那么好像说的是编译PC代码。后来用V=1打印了信息,才明白tools文件夹下编译用的是PC编译器。
2)升级:那么就升级openssl,再重新编译安装。
我下载了3.x版本安装完继续报错,接着我看doc文件夹中openssl相关使用的版本是1.1.1,所以又下载了1.1.1安装完后依然报错,而且错误一样。
3)规避问题:关闭配置
我看了makefile,应该只要把CONFIG_FIT_SIGNATURE选择为N即可,但是选了N依然会调用此库。
ifneq ($(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_ARMADA_38X)$(CONFIG_ARMADA_39X)$(CONFIG_FIT_SIGNATURE),)
HOSTCFLAGS_kwbimage.o += \
$(shell pkg-config --cflags libssl libcrypto 2> /dev/null || echo "")
HOSTLDLIBS_mkimage += \
$(shell pkg-config --libs libssl libcrypto 2> /dev/null || echo "-lssl -lcrypto")
4)找到根本问题:库的路径不对
通过分析报错应该就是库的路径不对,我自己写了个简单的带openssl api的main函数,然后用此方法编译,也提示缺少api定义。所以100%是路径不对。一种解决方法是使用-L的绝对路径,但是我不想改makefile我认为他没问题。
5)解决问题:gcc编译默认的库路径是什么?
答:当时我一直认为是/usr/lib。但是将so软连接到/usr/lib根本不起作用。于是我突然想到找一个其他的我用过的比如libpthread.so的路径,结果找到它是放在了/usr/lib/x86_64-linux-gnu下,于是我也将软链接放在此路径下,问题解决。网上搜索了这是64bit的特有路径,而以前一直用32bit的ubuntu。
三,更新openssl的方法
1,下载1.1.1.x,然后在root权限下编译和安装
./config && make && make install
2,重定向位置,设置库路径到ld.so.conf否则无法使用库
ln -sf /usr/local/bin/openssl /usr/bin/openssl
ln -s /usr/local/include/openssl /usr/include/openssl
echo "/usr/local/lib64/" >> /etc/ld.so.conf
ldconfig
3,此时已安装成功,查看版本。必须先加入了ld.so.conf,否则查看版本报错。
openssl version -v
4,为了c代码能正常编译动态库文件,需要添加到系统默认的查找库文件的路径/usr/lib/x86_64-linux-gnu,采用软链接的方法,先备份之前的软链接,再创建新的软链接到1.1版本。然后就可以顺利编译代码了。
mv /usr/lib/x86_64-linux-gnu/libssl.so /usr/lib/x86_64-linux-gnu/libssl.so.bak
mv /usr/lib/x86_64-linux-gnu/libcrypto.so /usr/lib/x86_64-linux-gnu/libcrypto.so.bak
ln -s /usr/local/lib64/libcrypto.so.1.1 /usr/lib/x86_64-linux-gnu/libcrypto.so
ln -s /usr/local/lib64/libssl.so.1.1 /usr/lib/x86_64-linux-gnu/libssl.so
5, /etc/ld.so.conf加入后看起来查版本号的时候so已经起作用了,但是为什么编译的时候不行呢?
答:/etc/ld.so.conf里面的路径是runtime时候搜索的路径。并不适用于gcc编译时候搜索路径。
四,小结
本次为什么值得记录,一个就是熟悉下更新库有哪些必要的步骤,第二个就是gcc make的默认路径需要了解清楚,这个很重要,当然不想改makefile,也可以在环境变量LIBRARY_PATH中添加路径。
关键是我之前还没搞明白的就是编译路径和运行时搜索路径其实是不同的。所以值得记录。
开发时,设置LIBRARY_PATH,以便gcc能够找到编译时需要的动态链接库。发布时,设置LD_LIBRARY_PATH,以便程序加载运行时能够自动找到需要的动态链接库。