• NDK交叉编译及so库导入Android项目


    个人博客

    http://www.milovetingting.cn

    前言

    记录NDK交叉编译及so库导入Android项目的简单步骤,以备后续用到时查看。

    环境

    在Linux和Mac环境下,分别编译输出so库。

    Red Hat Enterprise Linux 8 64 位 使用GCC编译(也可以用CLANG,这里演示用GCC)

    macOS Big Sur 11.3.1 使用CLANG编译(也可以用GCC,这里演示用CLANG)

    下载NDK

    这里只演示下载NDK17,项目中Mac用到的NDK版本为NDK21

    下载NDK

    wget https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip
    

    NDK18及之后的NDK版本,建议使用CLANG编译。

    解压NDK

    unzip android-ndk-r17c-linux-x86_64.zip
    

    解压后得到android-ndk-r17c文件夹

    编写头文件及c文件

    GCC编译

    #include "get.h"
    
    int get(){
      return 666;
    }
    
    #include "get.h"
    
    int get(){
      return 666;
    }
    

    CLANG编译

    #include <stdio.h>
    
    int hi();
    
    
    #include "hi.h"
    
    int hi(){
      return 888;
    }
    
    

    配置NDK

    Linux(使用GCC编译)

    编辑Home/用户 目录下的.bashrc

    vim /home/wangyz/.bashrc
    

    添加以下内容

    # 配置NDK的目录
    export NDK_HOME=/home/wangyz/NDK/android-ndk-r17c
    # 将NDK目录加入PATH中
    export PATH=$PATH:$NDK_HOME
    
    # x86 CPU架构的gcc
    export NDK_GCC_x86=$NDK_HOME/toolchains/x86-4.9/prebuilt/linux-x86_64/bin/i686-linux-android-gcc
    
    # x86_64 CPU架构的gcc
    export NDK_GCC_x64=$NDK_HOME/toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin/x86_64-linux-android-gcc
    
    # ARM CPU架构的gcc
    export NDK_GCC_ARM=$NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc
    
    # ARM64 CPU架构的gcc
    export NDK_GCC_ARM_64=$NDK_HOME/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc
    
    # x86 CPU架构 配置sysroot,isystem,否则会找不到头文件
    export NDK_GCC_CONFIG_x86="--sysroot=$NDK_HOME/platforms/android-21/arch-x86 -isystem $NDK_HOME/sysroot/usr/include -isystem $NDK_HOME/sysroot/usr/include/i686-linux-android"
    
    # x86_64 CPU架构 配置sysroot,isystem,否则会找不到头文件
    export NDK_GCC_CONFIG_x64="--sysroot=$NDK_HOME/platforms/android-21/arch-x86_64 -isystem $NDK_HOME/sysroot/usr/include -isystem $NDK_HOME/sysroot/usr/include/x86_64-linux-android"
    
    # ARM CPU架构 配置sysroot,isystem,否则会找不到头文件
    export NDK_GCC_CONFIG_ARM="--sysroot=$NDK_HOME/platforms/android-21/arch-arm -isystem $NDK_HOME/sysroot/usr/include -isystem $NDK_HOME/sysroot/usr/include/arm-linux-androideabi"
    
    # ARM64 CPU架构 配置sysroot,isystem,否则会找不到头文件
    export NDK_GCC_CONFIG_ARM_64="--sysroot=$NDK_HOME/platforms/android-21/arch-arm64 -isystem $NDK_HOME/sysroot/usr/include -isystem $NDK_HOME/sysroot/usr/include/aarch64-linux-android"
    

    Mac(使用CLANG编译)

    修改~/.bash_profile

    vim ~/.bash_profile
    

    添加以下内容

    # NDK目录
    export NDK_HOME=/Users/ringle/Library/Android/sdk/ndk/21.1.6352462
    
    # CLANG目录
    export CLANG=${NDK_HOME}/toolchains/llvm/prebuilt/darwin-x86_64/bin
    
    # 添加到PATH中
    export PATH=${PATH}:${NDK_HOME}:${CLANG}
    

    编译

    这里编译ARM64构架的so

    GCC

    $NDK_GCC_ARM_64 $NDK_GCC_CONFIG_ARM_64 -fPIC -shared get.c -o libndk-linux.so
    

    CLANG

    aarch64-linux-android21-clang -fPIC -shared hi.c -o libndk-mac.so
    

    导入Android Studio

    复制so到项目中

    在app/src/main 目录下新建jniLibs目录,再新建arm64-v8a目录,将编译生成的libndk-linux.so及libndk-mac.so复制到目录下

    配置cmake

    在app/src/main 目录下新建cpp目录,新建CMakeLists.txt,配置如下:

    
    # For more information about using CMake with Android Studio, read the
    # documentation: https://d.android.com/studio/projects/add-native-code.html
    
    # Sets the minimum version of CMake required to build the native library.
    
    cmake_minimum_required(VERSION 3.10.2)
    
    # Declares and names the project.
    
    project("ndk")
    
    # 包含所有CPP文件
    file(GLOB allCPP *.cpp)
    
    # Creates and names a library, sets it as either STATIC
    # or SHARED, and provides the relative paths to its source code.
    # You can define multiple libraries, and CMake builds them for you.
    # Gradle automatically packages shared libraries with your APK.
    
    add_library( # Sets the name of the library.
            native-lib
    
            # Sets the library as a shared library.
            SHARED
    
            # Provides a relative path to your source file(s).
            ${allCPP})
    
    # Searches for a specified prebuilt library and stores the path as a
    # variable. Because CMake includes system libraries in the search path by
    # default, you only need to specify the name of the public NDK library
    # you want to add. CMake verifies that the library exists before
    # completing its build.
    
    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)
    
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}")
    
    # 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.
            native-lib
    
            # Links the target library to the log library
            # included in the NDK.
            ${log-lib}
            # 链接libndk-mac
            ndk-mac
            # 链接libndk-linux
            ndk-linux
            )
    

    配置gradle

    配置app模块下的build.gralde文件

    
    android {
    
        defaultConfig {
            //...
            
            externalNativeBuild {
                cmake {
                    abiFilters "arm64-v8a"
                }
            }
            ndk {
                abiFilters "arm64-v8a"
            }
        }
    
        externalNativeBuild {
            cmake {
                path "src/main/cpp/CMakeLists.txt"
                version "3.10.2"
            }
        }
    }
    

    引用so中的方法

    在cpp目录下,新建native-lib.cpp

    #include <jni.h>
    #include <string>
    #include <android/log.h>
    
    #define TAG "Wangyz"
    
    #define LOG_I(...) __android_log_print(ANDROID_LOG_INFO, TAG,  __VA_ARGS__);
    
    extern "C" int get();
    
    extern "C" int hi();
    
    extern "C" JNIEXPORT jstring JNICALL
    Java_com_wangyz_ndk_MainActivity_stringFromJNI(
            JNIEnv *env,jobject /* this */) {
        int a = get();
        LOG_I("hello:%d", a);
    
        int b = hi();
        LOG_I("hi:%d", b);
    
        return env->NewStringUTF("hello");
    }
    

    Activity中调用

    
    public class MainActivity extends AppCompatActivity {
    
        // Used to load the 'native-lib' library on application startup.
        static {
            System.loadLibrary("ndk-mac");
            System.loadLibrary("ndk-linux");
            System.loadLibrary("native-lib");
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // Example of a call to a native method
            TextView tv = findViewById(R.id.sample_text);
            tv.setText(stringFromJNI());
        }
    
        /**
         * A native method that is implemented by the 'native-lib' native library,
         * which is packaged with this application.
         */
        public native String stringFromJNI();
    }
    
    Android代码搬运工一枚,欢迎留言讨论交流!
    个人主页:http://www.milovetingting.cn
  • 相关阅读:
    [KMP] 对最长前后缀匹配表生成步骤的理解
    [服务器日志] 对恶意挖矿的简易处理
    [linux] 使用yum命令时,解析不了yum源,Cannot find a valid baseurl for repo: base/7/x86_6
    [linux] 即使有root权限, 仍然无法修改文件 [E212 cant open file for writing.]
    五、数据挖掘流程简明笔记
    centos安装chrome及chromedriver
    六、手写实现KNN算法
    Ali266首次商用落地,助力优酷码率最高节省40%
    AliSSR 语音超分算法:让在线会议语音更明亮更自然
    如何在云端重塑内容生产?来看这场虚拟人主持的发布会
  • 原文地址:https://www.cnblogs.com/milovetingting/p/14759843.html
Copyright © 2020-2023  润新知