在当前编译平台下,编译出来的程序能运行在另一种目标平台上,但是编译平台本身却不能运行该程序。而我们在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权限。如果应用权限需要通过解锁工具,点击这里下载。

本文所有实例代码下载

猜你喜欢

linux1 基础学习

linux2 权限和管理

linux3 Vim和shell脚本