我是在 Linux 上编译的方式
export NDK_ARM_GCC="/root/ndk/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc"
export PATH=$PATH:$NDK_ARM_GCC
export NDK_ARM_CFIG="--sysroot=/root/ndk/android-ndk-r17c/platforms/android-23/arch-arm -isystem /root/ndk/android-ndk-r17c/sysroot/usr/include -isystem /root/ndk/android-ndk-r17c/sysroot/usr/include/arm-linux-androideabi"
export PATH=$PATH:$NDK_ARM_CFIG
export NDK_ARM_AR="/root/ndk/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc-ar"
export PATH+$PATH:$NDK_ARM_AR
#include
int getNum();
#include"hello.h"
int getNum(){
return 12345;
}
$NDK_ARM_GCC $NDK_ARM_CFIG -fPIC -c hello.c -o hello.o
$NDK_ARM_AR rcs -o libhello.a hello.o
生成 libhello.a 文件
$NDK_ARM_GCC $NDK_ARM_CFIG -fPIC -shared hello.c -o libhello.so
生成 libhello.so 文件
sz libhello.a
sz libhello.so
# 这里面能够决定编译 Login.c
# 1.源文件在的位置。宏函数 my-dir 返回当前目录(包含 Android.mk 文件本身的目录)的路径。
# LOCAL_PATH 其实就是Android.mk文件本身的目录的路径
LOCAL_PATH := $(call my-dir)
$(info "LOCAL_PATH:======== ${LOCAL_PATH}")
# 2.清理
include $(CLEAR_VARS)
# TODO 预编译库的引入 == 提前编译好的库
LOCAL_MODULE := get
# LOCAL_SRC_FILES := libget.so
LOCAL_SRC_FILES := libget.a
# 预编译共享库的Makeifle脚本
# include $(PREBUILT_SHARED_LIBRARY)
include $(PREBUILT_STATIC_LIBRARY)
#引入其他makefile文件。CLEAR_VARS 变量指向特殊 GNU Makefile,可为您清除许多 LOCAL_XXX 变量
#不会清理 LOCAL_PATH 变量
include $(CLEAR_VARS)
# TODO end
# 3.指定库名字
#存储您要构建的模块的名称 每个模块名称必须唯一,且不含任何空格
#如果模块名称的开头已是 lib,则构建系统不会附加额外的前缀 lib;而是按原样采用模块名称,并添加 .so 扩展名。
LOCAL_MODULE := MyLoginJar
#包含要构建到模块中的 C 和/或 C++ 源文件列表 以空格分开
LOCAL_SRC_FILES := Login.c \
Test.c
# TODO 开始链接进来
# 静态库的链接
LOCAL_STATIC_LIBRARIES := get
# 动态库链接
#LOCAL_SHARED_LIBRARIES := get
# 导入 log
#LOCAL_LDLIBS := -llog
LOCAL_LDLIBS := -lm -llog
# 4.动态库
#构建动态库BUILD_SHARED_LIBRARY 最后要动态库
include $(BUILD_SHARED_LIBRARY)
编译期:编译期的时候,把静态库完整全部Copy一份去执行的。如果修改了静态库,需要重新编译。如果内部使用的库,不会给外部提供,采用静态库
app的gradle配置如下:
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.lu.ndk03"
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
// cppFlags ""
// abiFilters 'armeabi-v7a'
}
ndk {
// 打包生成的 APK 文件指挥包含 ARM 指令集的动态库 不加这个我那个手机导入静态库就崩溃
abiFilters "armeabi-v7a" /*, "arm64-v8a", "x86", "x86_64"*/
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
cmake_minimum_required(VERSION 3.4.1)
add_library(
native-lib
SHARED
native-lib.cpp
libhello.a
)
# 导入静态库 STATIC:静态 IMPORTED:导入
add_library(hello STATIC IMPORTED)
# 开始真正的导入
set_target_properties(hello PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libhello.a)
find_library(
log-lib
log)
target_link_libraries(
native-lib
${log-lib}
# 链接 hello 库
hello
)
#include
#include
#include
// 用 C 编译的 getNum 所以需要执行需要 C 环境
extern "C" {
// 自己定义的方法 会返回 12345
int getNum();
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_lu_ndk03_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
// 这里只是打印了一下 log 查看 getNum是否调用成功
jint result = getNum();
// 成功打印出 12345
__android_log_print(ANDROID_LOG_DEBUG, "lu", "hello的结果=%d", result);
return env->NewStringUTF(hello.c_str());
}
运行的时候,才会去加载,而且只加载一次(System.loadLIbary(xxxx.so)),当加载一次之后,在内存中存在副本,所有使用的地方都是公用的。比如地图的.so库等。
cmake_minimum_required(VERSION 3.4.1)
add_library(
native-lib
SHARED
native-lib.cpp
# libhello.a
)
# 导入静态库
#add_library(hello STATIC IMPORTED)
# 开始真正的导入
#set_target_properties(hello PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libhello.a)
# CMAKE_ANDROID_ARCH_ABI 代表 armeabi-v7a src/main
# add 添加自己的动态库
add_library(hello SHARED IMPORTED)
#${PROJECT_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}/libhello.so
set_target_properties(hello PROPERTIES IMPORTED_LOCATION so存储路径/libhello.so)
# find 只能找系统的
find_library(
log-lib
log)
target_link_libraries(
native-lib
${log-lib}
# 链接 hello 库
hello
)
MainActivity中
static {
// 要写在 总库 之前
System.loadLibrary("hello");
System.loadLibrary("native-lib");
}