• Android64位库编译遇到的问题和处理方法


    小舟从此逝,江海度余生
    小舟从此逝

    Android64位库适配的必要性

    随着处理器的升级换代,64位处理器渗透到更多的行业,在手机很通用的64位处理器,在安防领域逐渐扩大开来,同行业的厂商的sdk逐渐开始支持64位,这对于我们设备开发者来讲,如果没有任何一个库使用的是64位的话,还可以在应用的兼容模式下跑32位的库,但是很不巧,遇到了一个厂商只能提供64位的库,要使用他的功能就必须把所有的库都转化成64位,而对于使用大量32位库的老项目来讲,这是一个工作量巨大的事情,所以还在使用32位库的项目尽早适配64位吧

    Android64位库编译需要的环境

    ubuntu系统(也可以是windows ndk环境,windows下最大的问题就是需要自己写Android.mk, 以及处理源码结构)
    ndk下载并解压 (根据系统来下对应的ndk版本,建议使用比较通用的版本,比如ndk 14e,如果用太新的,可能会出现各种意想不到问题)
    https://github.com/android/ndk/wiki/Unsupported-Downloads

    源码,尽量使用通用的源码(通用,采坑的人多,遇到问题也容易找到答案)

    一个列子:openssl库

    为了便于说明问题,以openssl为列,编译一个库,抛转引玉

    第一步下载源码,解压

    git clone git://git.openssl.org/openssl.git

    第二步配置编译选项

    	./Configure linux-aarch64 --cross-compile-prefix=aarch64-linux-gnu-
    	root@software-wrt:/home/yuehy/test# file /usr/local/lib/libssl.so.3 
    	/usr/local/lib/libssl.so.3: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[sha1]=00c552de16d1f6b4bb314073353e27b92a90cd57, not stripped
    

    单纯从信息来看 ARM aarch64 是arm64位
    但问题在于,链接的库都不是Android的库

    	~/test$ readelf -d /usr/local/lib/libssl.so.3 
    
    	Dynamic section at offset 0x8fbd0 contains 33 entries:
    	标记        类型                         名称/值
    	0x0000000000000001 (NEEDED)             共享库:[libcrypto.so.3]
    	0x0000000000000001 (NEEDED)             共享库:[libpthread.so.0]
    	0x0000000000000001 (NEEDED)             共享库:[libc.so.6]
    	0x0000000000000001 (NEEDED)             共享库:[ld-linux-aarch64.so.1]
    	0x000000000000000e (SONAME)             Library soname: [libssl.so.3]
    

    但是从链接信息来看链接是带有版本号的库,这种链接库在Android应用里面是没办法找到的,所以这种库是没办法在Android里面使用的

    正确的库,使用的是Android系统的链接库,正确的编译姿势是,使用ndk里面Android64位对应的编译器,链接Android64位的基础库,使用64位Android的头文件

    附上正确的编译语句

    	CPPFLAGS="-I/usr/local/android-ndk-r14b/platforms/android-21/arch-arm64/usr/include" LDFLAGS="-Wl,-rpath-link=/usr/local/android-ndk-r14b/platforms/android-21/arch-arm64/usr/lib -L/usr/local/android-ndk-r14b/platforms/android-21/arch-arm64/usr/lib"  LIBS="-ldl"  ./Configure linux-aarch64 --cross-compile-prefix=/usr/local/android-ndk-r14b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android- --prefix=/home/yuehy/test/openssl/out no-asm shared no-async
    

    说明
    CPPFLAGS :一般是加载头文件的路径 同 --extra-cflags

    LDFLAGS :一般是库的链接路径 如-Wl,-rpath-link= 是配置优先链接库路径 编译的部分选项也可以在这里配置 如-shared -fPIC -DPIC 等 同--extra-ldflags

    --sysroot= 一般是ndk的sysroot目录

    --cross-compile-prefix:一般是编译使用的通用头,如本列中使用的--cross-compile-prefix=/usr/local/android-ndk-r14b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-
    系统编译的时候会自动加上gcc,g++,clang等,完整的路径会是这样/usr/local/android-ndk-r14b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc

    **--host=aarch64-linux-gnu **
    **--target-os=android **
    **--arch=aarch64 **
    配置编译的目标系统

    **配置soname -Wl,-soname -Wl,libsqlite3.so **

    --prefix=/home/out 配置生成文件的输出路径

    --enable-cross-compile 开启交叉编译

    第三步 编译

    make

    可能会遇到如下问题

    	engines/dasync-dso-e_dasync.o: In function `dasync_aes128_cbc_hmac_sha1_ctrl':
    	e_dasync.c:(.text+0x2c0): undefined reference to `memcpy'
    	engines/dasync-dso-e_dasync.o: In function `wait_cleanup':
    	e_dasync.c:(.text+0x568): undefined reference to `close'
    	 e_dasync.c:(.text+0x570): undefined reference to `close'
    	 engines/dasync-dso-e_dasync.o: In function `dasync_aes128_cbc_ctrl':
    	 e_dasync.c:(.text+0x13ec): undefined reference to `memcpy'
    	 engines/dasync-dso-e_dasync.o: In function `dummy_pause_job':
    	 e_dasync.c:(.text+0x14a8): undefined reference to `write'
    	 e_dasync.c:(.text+0x14c0): undefined reference to `read'
    	 e_dasync.c:(.text+0x14f8): undefined reference to `pipe'
    	 e_dasync.c:(.text+0x1550): undefined reference to `close'
    	 e_dasync.c:(.text+0x1558): undefined reference to `close'
    	 engines/dasync-dso-e_dasync.o: In function `bind_engine':
    	 e_dasync.c:(.text+0x1694): undefined reference to `strcmp'
    	 collect2: error: ld returned 1 exit status
    	 Makefile:21363: recipe for target 'engines/dasync.so' failed
    	 make[1]: *** [engines/dasync.so] Error 1
    	 make[1]: Leaving directory '/home/yuehy/test/openssl'
    	 Makefile:3277: recipe for target 'build_sw' failed
    	 make: *** [build_sw] Error 2
    

    在编译的标志里面去掉 nostdlib 去掉-D__ANDROID_API__=21 就可以正常编译通过

    编译中遇到的问题,一般来说如下几个方面检查
    1. 头文件路径不正确导致
    2. 库的链接路径不对
    3. 编译的附加选项配置不正确 如nostdlib -ldl之类
    4. 如果前三步没问题,那你遇见的的问题就是大家都会遇见的问题,建议谷歌

    第四步,库的名称问题

    生成的库名字叫libssl.so.3 ,这倒是可以改,但是

      0x000000000000000e (SONAME)             Library soname: [libssl.so.3]
    

    soname是连接库的时候的标识,而Android是不认这种带版本号的库的
    解决方法:修改Makefile的选项

    	 #SHLIBS=libcrypto.so.3 libssl.so.3
    	SHLIBS=libcrypto.so libssl.so
    	#SHLIB_INFO="libcrypto.so.3;libcrypto.so;" "libssl.so.3;libssl.so;"
    	SHLIB_INFO="libcrypto.so;libcrypto.so;" "libssl.so;libssl.so;"
    
    
    	 $(CC) $(LIB_CFLAGS) -L. $(LIB_LDFLAGS) -Wl,-soname=libssl.so \
    					-o libssl.so -Wl,--version-script=libssl.ld \
    					
    					
    	#libssl.so: libssl.so.3
    	#       rm -f libssl.so && \
    	#       ln -s libssl.so.3 libssl.so
    	libssl.so: crypto/libssl-shlib-packet.o ssl/libssl-shlib-bio_ssl.o \
    				 ssl/libssl-shlib-d1_lib.o ssl/libssl-shlib-d1_msg.o \
    				 ssl/libssl-shlib-d1_srtp.o ssl/libssl-shlib-methods.o \
    				 ssl/libssl-shlib-pqueue.o ssl/libssl-shlib-s3_cbc.o \
    				 ssl/libssl-shlib-s3_enc.o ssl/libssl-shlib-s3_lib.o \
    				 ssl/libssl-shlib-s3_msg.o ssl/libssl-shlib-ssl_asn1.o \
    				 ssl/libssl-shlib-ssl_cert.o ssl/libssl-shlib-ssl_ciph.o \
    				 ssl/libssl-shlib-ssl_conf.o ssl/libssl-shlib-ssl_err.o \
    				 ssl/libssl-shlib-ssl_err_legacy.o ssl/libssl-shlib-ssl_init.o \
    				 ssl/libssl-shlib-ssl_lib.o ssl/libssl-shlib-ssl_mcnf.o \
    				 ssl/libssl-shlib-ssl_rsa.o ssl/libssl-shlib-ssl_rsa_legacy.o \
    				 ssl/libssl-shlib-ssl_sess.o ssl/libssl-shlib-ssl_stat.o \
    				 ssl/libssl-shlib-ssl_txt.o ssl/libssl-shlib-ssl_utst.o \
    				 ssl/libssl-shlib-t1_enc.o ssl/libssl-shlib-t1_lib.o \
    				 ssl/libssl-shlib-t1_trce.o ssl/libssl-shlib-tls13_enc.o \
    				 ssl/libssl-shlib-tls_depr.o ssl/libssl-shlib-tls_srp.o \
    				 ssl/record/libssl-shlib-dtls1_bitmap.o \
    				 ssl/record/libssl-shlib-rec_layer_d1.o \
    				 ssl/record/libssl-shlib-rec_layer_s3.o \
    				 ssl/record/libssl-shlib-ssl3_buffer.o \
    				 ssl/record/libssl-shlib-ssl3_record.o \
    				 ssl/record/libssl-shlib-ssl3_record_tls13.o \
    				 ssl/record/libssl-shlib-tls_pad.o \
    				 ssl/statem/libssl-shlib-extensions.o \
    				 ssl/statem/libssl-shlib-extensions_clnt.o \
    

    修改所有的libcrypto.so.3 为libcrypto.so

    ~/test/openssl$ readelf -d libssl.so
    
    	Dynamic section at offset 0x87c68 contains 30 entries:
    	  标记        类型                         名称/值
    	 0x0000000000000001 (NEEDED)             共享库:[libcrypto.so]
    	 0x0000000000000001 (NEEDED)             共享库:[libdl.so]
    	 0x0000000000000001 (NEEDED)             共享库:[libc.so]
    	 0x000000000000000e (SONAME)             Library soname: [libssl.so]
    

    现在就是一个可以正常使用的Android库了

    编译curl Android64位库

    编译指令

    	 CPPFLAGS="-I/usr/local/android-ndk-r14b/platforms/android-21/arch-arm64/usr/include" LDFLAGS="-Wl,-rpath-link=/usr/local/android-ndk-r14b/platforms/android-21/arch-arm64/usr/lib -L/usr/local/android-ndk-r14b/platforms/android-21/arch-arm64/usr/lib" LIBS="-ldl"  CC=/usr/local/android-ndk-r14b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc  ./configure   --target=aarch64-linux-gnu --host=aarch64-linux-gnu   --enable-shared --without-nss --disable-dict --disable-ftp --disable-imap --disable- ldap --disable-ldaps --disable-pop3 --disable-proxy --disable-rtsp --disable-smtp --disable-telnet --disable-tftp --disable-zlib --without-ca-bundle --without-gnutls --without-libidn --without-librtmp --without-libssh2 --without-nss --without-zlib --with- ssl=/home/yuehy/test/openssl/out
    

    配置不带版本号的库

    修改 configure文件

    带版本号的库 原始配置

    	 linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
    	  version_type=linux # correct to gnu/linux during the next big refactor
    	  need_lib_prefix=no
    	  need_version=no
    	  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    	  soname_spec='$libname$release$shared_ext$major'
    	  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
    

    不带版本号的库

    	# This must be glibc/ELF.
    	linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
    	  version_type=linux # correct to gnu/linux during the next big refactor
    	  need_lib_prefix=no
    	  need_version=no
    	  library_names_spec='$libname$shared_ext'
    	  soname_spec=''
    	  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
    	  shlibpath_var=LD_LIBRARY_PATH
    	  shlibpath_overrides_runpath=no
    

    libsqlite3.so Android64位库

    编译指令

         /usr/local/android-ndk-r14b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc -shared  -fPIC -DPIC -I/usr/local/android-ndk-r14b/platforms/android-21/arch-arm64/usr/include  -L/usr/local/android-ndk-r14b/platforms/android-21/arch-arm64/usr/lib .libs/sqlite3.o  -lz -lm -ldl  -g -O2   -Wl,-soname -Wl,libsqlite3.so -o lib/libsqlite3.so
    

    libevent.so Android64位库

    编译指令

    	 CPPFLAGS=-I/usr/local/android-ndk-r14b/platforms/android-21/arch-arm64/usr/include LDFLAGS=-L/usr/local/android-ndk-r14b/platforms/android-21/arch-arm64/usr/lib  CC=/usr/local/android-ndk-r14b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc ./configure --prefix=/home/yuehy/test/libevent-2.1.12-stable/out --host=aarch64-linux-gnu --disable-openssl --enable-shared
    

    修改confdefs.h

    带版本号的库

    	# This must be glibc/ELF.
    	linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
    	  version_type=linux # correct to gnu/linux during the next big refactor
    	  need_lib_prefix=no
    	  need_version=no
    	  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    	  soname_spec='$libname$release$shared_ext$major'
    	  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
    	  shlibpath_var=LD_LIBRARY_PATH
    	  shlibpath_overrides_runpath=no
    
    	  # Some binutils ld are patched to set DT_RUNPATH
    	  if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
    	  $as_echo_n "(cached) " >&6
    	else
    	  lt_cv_shlibpath_overrides_runpath=no
    		save_LDFLAGS=$LDFLAGS
    		save_libdir=$libdir
    		eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
    			 LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
    		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    	/* end confdefs.h.  */
    

    不带版本号的库

    	# This must be glibc/ELF.
    	linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
    	  version_type=linux # correct to gnu/linux during the next big refactor
    	  need_lib_prefix=no
    	  need_version=no
    	  library_names_spec='$libname$shared_ext'
    	  soname_spec=''
    	  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
    	  shlibpath_var=LD_LIBRARY_PATH
    	  shlibpath_overrides_runpath=no
    
    	  # Some binutils ld are patched to set DT_RUNPATH
    	  if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
    	  $as_echo_n "(cached) " >&6
    	else
    	  lt_cv_shlibpath_overrides_runpath=no
    		save_LDFLAGS=$LDFLAGS
    		save_libdir=$libdir
    		eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
    			 LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
    		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    	/* end confdefs.h.  */
    

    编译libspeex.so Android64位库

    编译指令

        Android 64 
    	LDFLAGS=I/usr/local/android-ndk-r14b/platforms/android-21/arch-arm64/usr/lib CPPFLAGS=L/usr/local/android-ndk-r14b/platforms/android-21/arch-arm64/usr/include
    	CC=/usr/local/android-ndk-r14b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc ./configure --host=aarch64-linux-gnu  --target=aarch64-linux-gnu 
    

    编译libsrtp.so Android64位库

    编译选项

    编译指令

    	linux 64
    	CC=aarch64-linux-gnu-gcc ./configure --host=arm-linux
    	android 
    	CPPFLAGS=-I/usr/local/android-ndk-r14b/platforms/android-21/arch-arm64/usr/include LDFLAGS=-L/usr/local/android-ndk-r14b/platforms/android-21/arch-arm64/usr/lib CC=/usr/local/android-ndk-r14b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc ./configure --host=aarch64-linux-android
    

    生成静态库 make
    生成动态库 make libsrtp2.so

  • 相关阅读:
    针对性博文
    spring事务
    Redis_主从模式_哨兵模式_Cluster集群模式
    Redis AOF、RDB持久化
    Redis 高可用分布式集群
    Redis 基础
    Oracle优化学习
    Mysql:索引实战
    Mysql:性能优化
    js 二维数组定义
  • 原文地址:https://www.cnblogs.com/baldermurphy/p/16273117.html
Copyright © 2020-2023  润新知