Cmake和NdkBuild方式链接交叉编译的动态库-->杂记

断了今生、忘了曾经 提交于 2020-02-26 03:24:48

                                       前提介绍:

                                           a.加上extern "C"后,会指示编译器这部分代码按C语言(而不是C++)的方式进行编译

                                           b.https://developer.android.google.cn/ndk/guides/android_mk:官方Android.mk介绍指南

                                           c.看动态库的依赖库有哪些: $ndk64Readelf  -d libplay.so

                                           d.看动态库定义的方法:$ndkNm64 -D libplay.soo 

                                           e.compile 4 steps :(gcc xxx.c -o xxx)
                                            gcc -E xxx.c -o xxx.i 预处理
                                            gcc -S xxx.i -o xxx.s 汇编
                                            gcc -c xxx.s  -o xxx.o 机器代码编译
                                            gcc -C xxx.o -o xxx.a  链接(为了可执行)
                                            run it : ./xxx.a  or ./xxx
                                            EScC 

 

export zzm="zengzeming"

export ndkClang="/zengzeming/ndk/android-ndk-r21-beta2/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang"

export ndkLink="--sysroot=/zengzeming/ndk/android-ndk-r21-beta2/toolchains/llvm/prebuilt/linux-x86_64/sysroot"

export ndkAr="/zengzeming/ndk/android-ndk-r21-beta2/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar"

export ndkNm="/zengzeming/ndk/android-ndk-r21-beta2/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-nm"

export ndkClang64="/zengzeming/ndk/android-ndk-r21-beta2/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang++"

export ndkAr64="/zengzeming/ndk/android-ndk-r21-beta2/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar"

export ndkNm64="/zengzeming/ndk/android-ndk-r21-beta2/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-nm
"
export ndk64Readelf="/zengzeming/ndk/android-ndk-r21-beta2/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-readelf"

export shell="/bin/bash"
~                       

1.Cmake
# 导入动态库-->版本有区别,两种方式可尝试导入动态库
#add_library(play SHARED IMPORTED)
#set_target_properties(play PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}/libplay.so)#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -L${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}")  #c编译器
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/jniLibs/${CMAKE_ANDROID_ARCH_ABI}") #c++编译器
#message("-------------------------->${CMAKE_SOURCE_DIR}/libs/${CMAKE_ANDROID_ARCH_ABI}")

三方动态库不在src/main/jniLinbs下面,需要重新在app的build.gradle下指定三方库的目录如:

sourceSets {
    main {
        jniLibs.srcDirs = ['src/main/jni/jniLibs']
    }
}

如果测试自己交叉编译的动态库有用到libc++_shared.so,运行时又找不到,需要在app build.gradle下做如下配置(cmake):

externalNativeBuild{
    cmake{
        arguments "-DANDROID_STL=c++_shared" //配置
        abiFilters "arm64-v8a"
    }
}

(ndkBuild):在Application.mk下面配置(和Android.mk所在目录一致):

APP_STL := c++_shared

target_link_libraries{

-Wl,--start-grop

这里的静态库可以不用按照链接下顺序来摆放

-Wl,--end-grop

}

2.Android.mk

把三方库放在src/main/jniLibs下,报more than one file .....lib/arm64-v8a/...so 就把库放在其他位置,应该是Android studio 自己编译配置的路径有冲突问题,就把库放其他位置就行(我测试的是Android8.0)

交叉编译要加上-soname 指定链接so库名字,不加可能会报找不到库。$ndkClang64 $ndkLink  -fPIC-shared  -Wl,-soname,libplay.so   play.c  -o libplay.so

(-Wl选项告诉编译器将后面的参数传递给链接器。)还有注意编译方式extern "C"以c方式编译。以防报未定义问题  

3.linux上简单编译c/c++的杂记:

ar rcs -o libadd.a add.o(二进制打包成静态库)格式:(ar rcs -o [目标文件] [源文件][源文件])

gcc main.c -o main -L . -ladd(链接静态库)格式:-L链接库的目录 -l库的名字(和动态库链接是一样的)

ar t lib..  查看静态库包含哪些o文件

ldd 查看链接了哪些库

clang -shared -fPIC hello.c -o libhello.so(打包动态库)(ldconfig:了一个动态链接库,若想使其被系统共享,可以执行一下”ldconfig 目录名”这个命令。
         此命令的功能在于让ldconfig将指定目录下的动态链接库被系统共享起来,
         意即:在缓存文件/etc/ld.so.cache中追加进指定目录下的共享库。)

readelf -d .so看库的依赖库有哪些

nm -D .so看so里面的源文件涉及到的函数

4.看手机的cpu架构:adb shell getprop ro.product.cpu.abi

5.mk官方参考:https://developer.android.google.cn/ndk/guides/android_mk

6.编译普通的ffmpeg脚本(ffmpeg源码目录下执行 sh xxx.sh  或者/bin/bash xxx.sh):

#!/bin/bash
#define my var 

NDKPATH=/zengzeming/ndk/android-ndk-r21-beta2

PREFIX=/zengzeming/ffmpeg/ffmpeg-4.2.2/ffmpegCompileOutFiles/arm64-v8a

COMPILETOOLSPATH=/zengzeming/ndk/android-ndk-r21-beta2/toolchains/llvm/prebuilt/linux-x86_64/bin

SYSROOTPATH=/zengzeming/ndk/android-ndk-r21-beta2/toolchains/llvm/prebuilt/linux-x86_64/sysroot


./configure \
--prefix=$PREFIX \
--enable-cross-compile \
--target-os=android \
--arch=aarch64 \
--cross-prefix=$COMPILETOOLSPATH/aarch64-linux-android29- \
--ar=$COMPILETOOLSPATH/aarch64-linux-android-ar \
--nm=$COMPILETOOLSPATH/aarch64-linux-android-nm \
--ranlib=$COMPILETOOLSPATH/aarch64-linux-android-ranlib \
--sysroot=$SYSROOTPATH \
--extra-cflags="-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -Wa,--noexecstack -Wformat -Werror=format-security   -O0 -fno-limit-debug-info -fno-experimental-isel  -fPIC"  \
--disable-shared \
--enable-static \
--enable-small  \
--disable-programs \
--disable-avdevice \
--disable-encoders \
--disable-muxers \
--disable-filters \

make clean

make install

7.带有rtmp的ffmpeg 脚本(ffmpeg源码目录下执行 sh xxx.sh  或者/bin/bash xxx.sh)

#!/bin/bash

#define my var 

NDKPATH=/zengzeming/ndk/android-ndk-r21-beta2

PREFIX=/zengzeming/ffmpeg/ffmpeg-4.2.2/ffmpegCompileOutFiles/arm64-v8a_rtmp

COMPILETOOLSPATH=/zengzeming/ndk/android-ndk-r21-beta2/toolchains/llvm/prebuilt/linux-x86_64/bin

SYSROOTPATH=/zengzeming/ndk/android-ndk-r21-beta2/toolchains/llvm/prebuilt/linux-x86_64/sysroot

RTMPPATH=/zengzeming/ffmpeg/rtmp/rtmpSource/rtmpdump1/arm64-v8a

./configure \
--prefix=$PREFIX \
--enable-cross-compile \
--target-os=android \
--arch=aarch64 \
--cross-prefix=$COMPILETOOLSPATH/aarch64-linux-android29- \
--ar=$COMPILETOOLSPATH/aarch64-linux-android-ar \
--nm=$COMPILETOOLSPATH/aarch64-linux-android-nm \
--strip=$COMPILETOOLSPATH/aarch64-linux-android-strip \
--ranlib=$COMPILETOOLSPATH/aarch64-linux-android-ranlib \
--sysroot=$SYSROOTPATH \
--extra-cflags="-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -Wa,--noexecstack -Wformat -Werror=format-security   -O0 -fno-limit-debug-info -fno-experimental-isel  -fPIC -I$RTMPPATH//include/librtmp"  \
--extra-ldflags="-L$RTMPPATH/lib"
--extra-libs="-lrtmp"
--disable-shared \
--enable-static \
--enable-small  \
--enable-librtmp \
--disable-programs \
--disable-avdevice \
--disable-encoders \
--disable-muxers \
--disable-filters \

make clean

make install

8.rtmp脚本编译(ibrtmp结合ffmpeg可操作直播流,也是在源码下执行 sh xxx.sh  或者/bin/bash xxx.sh):

     #!/bin/bash

     make clean  && make install \  
     SYS=android \
     prefix=/zengzeming/ffmpeg/rtmp/rtmpSource/rtmpdump/arm64-v8a  \
     CRYPTO=  \
     SHARED=  \
     XDEF=-DNO_SSL \
     CC=$ndkClang64 \
     LD= $ndkLd \
     XCFLAGS=$ndkLink \
     XLDFLAGS=$ndkLink \
     AR=$ndkAr64   


 


 

  

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!