如何将c/c++代码通过NDK交叉工具链移植到Android平台上?

这段时间一直在做代码移植代码的工作,即将c/c++代码编译成Android平台的so库,于是写一篇文章记录下。

预备知识: GCC命令

一、下载NDK

如果有Android Studio可以直接在下载即可,如果没有则需要NDK,我用的是23版本的。下载好不要安装,直接解压到制定目录即可。

二、配置工具链

安装路径+ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/bin下,有四个命令组:

  • aarch64-linux-android
  • arm-linux-androideabi
  • i686-linux-android
  • x86_64-linux-android

cpu架构-系统版本-Android版本-编译器。如果你想编译32的就选arm-linux-androideabi组的命令,如果编译64位,就选aarch64-linux-android组的命令。命令列表如下:
在这里插入图片描述
aarch64-linux-android21-clang++,表示cpu架构为64,Linux系统,最低适配Android版本21,采用的是clang++编译进行编译。

目前Android支持ABI有下面这些,和上面的命令是对应的。

ABI支持的指令集备注
armeabi-v7a
  • armeabi
  • Thumb-2
  • VFPv3-D16
与 ARMv5/v6 设备不兼容。
arm64-v8a● AArch64
x86
  • x86 (IA-32)
  • MMX
  • SSE/2/3
  • SSSE3
不支持 MOVBE 或 SSE4。
x86_64
  • x86-64
  • MMX
  • SSE/2/3
  • SSSE3
  • SSE4.1、4.2
  • POPCNT6

通过下面命令配置工具链环境:

  • 打开terminal输入
    export PATH$PATH=安装路径+/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/bin

  • 输入aarch64-linux-android21-clang++ -v

Android (7714059, based on r416183c1) clang version 12.0.8 (https://android.googlesource.com/toolchain/llvm-project c935d99d7cf2016289302412d708641d52d2f7ee)
Target: aarch64-unknown-linux-android23
Thread model: posix
InstalledDir: /Users/*/Library/Android/sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/bin
Found candidate GCC installation: /Users/*/Library/Android/sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/bin/../lib/gcc/aarch64-linux-android/4.9.x
Selected GCC installation: /Users/*/Library/Android/sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/bin/../lib/gcc/aarch64-linux-android/4.9.x
Candidate multilib: .;@m64
Selected multilib: .;@m64

如果得到上面的信息说明配置环境成功,接下来就是进入编译的过程。

如果你想查看so文件的信息可以用readelf命令,
命令存放在/Users/*/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/arm-linux-androideabi/bin
再次使用export PATH=$PATH:/Users/banma-2643/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/arm-linux-androideabi/bin

三、编译C++代码

  • Asr.h文件
#include <iostream>
class Asr
{
public:
    int China;
    int Usa;
    int Japan;
    Asr();
    ~Asr();

public:
    void start();
    std::string getTest();
    int printCountry();
};
  • Asr.cpp 文件
#include <iostream>
#include "Asr.h"

Asr::Asr() : China(1), Japan(2), Usa(3)
{
}

Asr::~Asr()
{
}

void Asr::start()
{
    std::cout << "this is static lib!";
}

std::string Asr::getTest()
{
    return "test";
}

int Asr::printCountry()
{
    return China + Japan + Usa;
}
  • Main.cpp 文件
#include <iostream>
#include "Asr.h"

using namespace std;

int main()
{
    std::cout << "gcc Demo";
    cout << endl;

    Asr *a = new Asr();
    a->start();
    std::cout << a->getTest() << std::endl;
    std::cout << a->printCountry();
}

执行clang++ Asr.cpp Main.cpp 命令得到a.out,然后执行./a.out得到下面结果:

gcc Demo
this is static lib!test
6

如果不会使用命令,可以参考: GCC命令

接下来我们将Asr.cpp编译成so库,并在Android中使用Asr.h来访问它。
● 编译64 so库
执行 aarch64-linux-android21-clang++ -fPIC -shared C++/src/Asr.cpp -o libAsr.so

备注:so库的文件名一定要以lib开头,Android平台库默认是lib开头。

四、在Android中集成

新建项目

新建一个Android 工程,添加C++ module,并新建jniLibs,工程目录如下:
在这里插入图片描述
libAsr.so放在arm64-v8a目录下,将Asr.h放在main/cpp目录下。现在配置CmakeLists.txtbuild.gradle

配置CmakeLists.txt

cmake_minimum_required(VERSION 3.18.1)

project("ndkdemo")

include_directories(../cpp/)

add_library( # Sets the name of the library.
ndkdemo

# Sets the library as a shared library.
SHARED

# Provides a relative path to your source file(s).
ndkdemo.cpp)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}")

find_library( # Sets the name of the path variable.
log-lib

# Specifies the name of the NDK library that
# you want CMake to locate.
log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
ndkdemo
Asr
# Links the target library to the log library
# included in the NDK.
${log-lib})

include_directories(../cpp/)用于设置头文件,set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}")设置so文件。

配置 build.gradle

由于我只编译了arm64-v8a,所以我必须设置 abiFilters "arm64-v8a",如果你编译了所有的arm版本,这样就不用设置了。

android {
    ……
    defaultConfig {
        ……
        externalNativeBuild {
            cmake {
                arguments '-DANDROID_STL=c++_static'
                cppFlags ""
                abiFilters "arm64-v8a"/*,"arm64-v8a"*/ /*todo 缺少对应的64位so ,需要解决64位兼容问题*/
            }
        }
        ndk {
            abiFilters "arm64-v8a"
        }
    }
}

在实际的过程中,发现缺失libc++_shared.so,找到对应arm下libc++_shared.so复制到对应的文件夹下就行了。还有一种缺失libc++_shared.so,需要设置arguments '-DANDROID_STL=c++_shared'

参考:




 如何将c/c++代码通过NDK交叉工具链移植到Android平台上?_android移植clang-CSDN博客

  • 18
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值