linux4 NDK交叉编译
600 Words|Read in about 3 Min|本文总阅读量次
在当前编译平台下,编译出来的程序能运行在另一种目标平台上,但是编译平台本身却不能运行该程序。而我们在linux服务器编译的库可以直接在Android工程中编译。
交叉编译
1.编译简单的交叉编译
1#ubuntu下载命令
2sudo apt-get install xxx
3#centOs下载命令
4sudo yum install xxx
5# 下载文件命令,两者都可用
6sudo wget xxx(下载地址)
7# NDK下载地址
8sudo wget https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip?
9hl=zh_cn
查看手机 CPU架构(arm64-v8a架构)
笔者用得是root过的红米5手机,Android8.1,Api版本27。
1picasso:/ $ cat /proc/cpuinfo
2# arm64的
3Processor : AArch64 Processor rev 14 (aarch64)
error01:stdio.h: No such file or directory
1yangyang@iZbp1788g5aoi5p9z8e0ugZ:~/other$ export NDK_GCC="/home/yangyang/NDK/android-ndk-r17c/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc"
2yangyang@iZbp1788g5aoi5p9z8e0ugZ:~/other$ $NDK_GCC ndk01.c -o ndk01_exe ndk01.c:1:19: fatal error: stdio.h: No such file or directory
3 #include <stdio.h>
4 ^
5compilation terminated.
注:这里需要写全路径,不能写成~/NDK/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc会提示找不到路径
error02: undefined reference to ‘main’
1/home/yangyang/NDK/android-ndk-r17c/platforms/android-27/arch-arm64
2
3/home/yangyang/NDK/android-ndk-r17c/sysroot/usr/include
4
5/home/yangyang/NDK/android-ndk-r17c/sysroot/usr/include/aarch64-linux-android
6
7export NDKPATH="--sysroot=/home/yangyang/NDK/android-ndk-r17c/platforms/android-27/arch-arm64 -isystem /home/yangyang/NDK/android-ndk-r17c/sysroot/usr/include -isystem /home/yangyang/NDK/android-ndk-r17c/sysroot/usr/include/aarch64-linux-android"
8
9yangyang@iZbp1788g5aoi5p9z8e0ugZ:~/other$ $NDK_GCC $NDKPATH ndk01.c -o ndk_EXE
10/home/yangyang/NDK/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: error: /tmp/ccetB5z2.o: incompatible target
11/home/yangyang/NDK/android-ndk-r17c/platforms/android-28/arch-arm64/usr/lib/crtbegin_dynamic.o:crtbegin.c:function _start_main: error: undefined reference to 'main'
12/home/yangyang/NDK/android-ndk-r17c/platforms/android-28/arch-arm64/usr/lib/crtbegin_dynamic.o:crtbegin.c:function _start_main: error: undefined reference to 'main'
13collect2: error: ld returned 1 exit status
上述问题,可能是两种情况引起的。
第一种情况:配置的NDK_GCC和NDKPATH中的工具链版本不一致(32不能匹配64)。
第二种情况:需要增加请在编译命令中加上**-shared** 或加在LD_FLAGS 后。
1yangyang@iZbp1788g5aoi5p9z8e0ugZ:~/other$ $NDK_GCC $NDKPATH ndk01.c -o ndk_EXE
2yangyang@iZbp1788g5aoi5p9z8e0ugZ:~/other$ ls -al
3-rw-rw-r-- 1 yangyang yangyang 82 Mar 6 10:31 ndk01.c
4-rwxrwxr-x 1 yangyang yangyang 7832 Mar 6 11:17 ndk_EXE
手机中验证如下
error03:position-independent executables (-fPIE)
1vince:/data # ./ndk_EXE
2"./ndk_EXE": error: Android 5.0 and later only support position-independent executables (-fPIE).
服务器编译的时候加上pie
1yangyang@iZbp1788g5aoi5p9z8e0ugZ:~/other$ $NDK_GCC -pie $NDKPATH ndk01.c -o ndk_EXE
在手机中继续验证
1$ adb push C:\Users\Admin\Desktop\ndk_EXE /data
2C:\Users\Admin\Desktop\ndk_EXE: 1 file pushed. 1.3 MB/s (7832 bytes in 0.006s)
31|vince:/data # ls -al ndk_EXE
4-rw-rw-rw- 1 root root 7832 2022-03-06 17:42 ndk_EXE
5vince:/data # chmod +x ndk_EXE
6vince:/data # ./ndk_EXE
7->>>hello world!
每次配置环境变量比较麻烦,一般直接在linux服务器中添加到内部环境变量中。
1#【i686-xx x86=32】
2export NDK_GCC_x86="/home/yangyang/NDK/android-ndk-r17c/toolchains/x86-4.9/prebuilt/linux-x86_64/bin/i686-linux-android-gcc"
3#【x86_64-xx x86_64=64】
4export NDK_GCC_x64="/home/yangyang/NDK/android-ndk-r17c/toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin/x86_64-linux-android-gcc"
5#【arm32 == arm-linuxandroideabi-gcc】
6export NDK_GCC_arm="/home/yangyang/NDK/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc"
7#【arm64 == aarch64-linux-android-gcc】
8export NDK_GCC_arm_64="/home/yangyang/NDK/android-ndk-r17c/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc"
1export NDK_CFIG_x86="--sysroot=/home/yangyang/NDK/android-ndk-r17c/platforms/android-27/arch-x86/ -isystem /home/yangyang/NDK/android-ndk-r17c/sysroot/usr/include -isystem /home/yangyang/NDK/android-ndk-r17c/sysroot/usr/include/i686-linux-android"
2
3export NDK_CFIG_x64="--sysroot=/home/yangyang/NDK/android-ndk-r17c/platforms/android-27/arch-x86_64/ -isystem /home/yangyang/NDK/android-ndk-r17c/sysroot/usr/include -isystem /home/yangyang/NDK/android-ndk-r17c/sysroot/usr/include/x86_64-linux-android"
4
5export NDK_CFIG_arm="--sysroot=/home/yangyang/NDK/android-ndk-r17c/platforms/android-27/arch-arm/ -isystem /home/yangyang/NDK/android-ndk-r17c/sysroot/usr/include -isystem /home/yangyang/NDK/android-ndk-r17c/sysroot/usr/include/arm-linux-androideabi"
6
7export NDK_CFIG_arm_64="--sysroot=/home/yangyang/NDK/android-ndk-r17c/platforms/android-27/arch-arm64/ -isystem /home/yangyang/NDK/android-ndk-r17c/sysroot/usr/include -isystem /home/yangyang/NDK/android-ndk-r17c/sysroot/usr/include/aarch64-linux-android"
1#方法1:让/etc/profile文件修改后立即生效 ,可以使用如下命令:
2. /etc/profile
3#注意: . 和 /etc/profile 有空格
4#方法2:让/etc/profile文件修改后立即生效 ,可以使用如下命令:
5source /etc/profile
2.交叉编译动态库
1yangyang@iZbp1788g5aoi5p9z8e0ugZ:~/other$ $NDK_GCC_arm_64 $NDK_CFIG_arm_64 -fPIC -shared get.c -o libgetndkso.so
2
3yangyang@iZbp1788g5aoi5p9z8e0ugZ:~/other$ file libgetndkso.so
4libgetndkso.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, not stripped
查看是否为get函数
1yangyang@iZbp1788g5aoi5p9z8e0ugZ:~/other$ nm -D libgetndkso.so |awk '{if($2 == "T"){print $3}}'
2get
3.交叉编译静态库
1export NDK_AR_x86="/home/yangyang/NDK/android-ndk-r17c/toolchains/x86-4.9/prebuilt/linux-x86_64/bin/i686-linux-android-ar"
2export NDK_AR_x64="/home/yangyang/NDK/android-ndk-r17c/toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin/x86_64-linux-android-ar"
3export NDK_AR_arm="/home/yangyang/NDK/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar"
4export NDK_AR_arm_64="/home/yangyang/NDK/android-ndk-r17c/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar"
1yangyang@iZbp1788g5aoi5p9z8e0ugZ:~/other$ $NDK_GCC_arm_64 $NDK_CFIG_arm_64 -fPIC -c get.c -o getndka.o
2yangyang@iZbp1788g5aoi5p9z8e0ugZ:~/other$ $NDK_AR_arm_64 rcs -o libgetndka.a getndka.o
4.Android Studio编译验证
配置文件
cmake
静态库
1cmake_minimum_required(VERSION 3.10.2)
2
3project("mycrosscompile")
4
5file(GLOB allCPP *.cpp)
6
7add_library( # Sets the name of the library.
8 native-lib
9 SHARED
10 ${allCPP} )
11
12find_library( # Sets the name of the path variable.
13 log-lib
14 log )
15
16## 导入静态库,这里的import是一个标识
17add_library(getStaticNdk STATIC IMPORTED)
18
19set_target_properties(getStaticNdk PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libgetndka.a)
20
21target_link_libraries( # Specifies the target library.
22 native-lib
23 ${log-lib}
24 getStaticNdk)
动态库
关于动态库,笔者还会增加额外的新篇幅来阐述,这里简单的当一个demo编译。
2 files found with path ‘lib/arm64-v8a/libgetndkso.so’. If you are using jniLibs and CMake IMPORTED targets, see https://developer.android.com/r/tools/jniLibs-vs-imported-targets
1cmake_minimum_required(VERSION 3.10.2)
2
3project("mycrosscompile")
4
5file(GLOB allCPP *.cpp)
6
7add_library( # Sets the name of the library.
8 native-lib
9 SHARED
10 ${allCPP} )
11
12find_library( # Sets the name of the path variable.
13 log-lib
14 log )
15
16## 导入静态库,这里的import是一个标识
17#add_library(getStaticNdk STATIC IMPORTED)
18
19#set_target_properties(getStaticNdk PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libgetndka.a)
20
21## 导入动态库,这里的import是一个标识
22add_library(getSharedNdk SHARED IMPORTED)
23
24set_target_properties(getSharedNdk PROPERTIES IMPORTED_LOCATION
25 ${CMAKE_SOURCE_DIR}/../jniLibs/arm64-v8a/libgetndkso.so)
26
27target_link_libraries( # Specifies the target library.
28 native-lib
29 ${log-lib}
30 getSharedNdk)
build.gradle
1android {
2 compileSdkVersion 30
3 buildToolsVersion "30.0.3"
4
5 defaultConfig {
6 applicationId "com.example.mycrosscompile"
7 minSdkVersion 21
8 targetSdkVersion 30
9 versionCode 1
10 versionName "1.0"
11
12 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
13 externalNativeBuild {
14 //===========新增
15 cmake {
16 //cppFlags''
17 abiFilters "arm64-v8a"
18 }
19 //===========
20 }
21 //===========新增
22 ndk{
23 abiFilters "arm64-v8a"
24 }
25 //===========
26 }
4.关于手机没有root权限
网上有好多刷机工具可选择。笔者用得是红米5的手机,直接可以在官网下载开发版本红米5 Plus。下载完成之后,根据官网提示手动选择自动安装包,选择下载的开发版本即可。
没有手动更新选项,需要连续点击MIUI的LOGO10次。
下载完成后,通过应用权限中开启root权限,稍等片刻即会有root权限。如果应用权限需要通过解锁工具,点击这里下载。