Android现在JNI相关的代码编译成so主要有两种方式,一种是传统的ndk-build,还有就是CMakeLists.txt,接下来总结下Android.mk、Application.mk、CMakeLists.txt文件的语法。
Android.mk
-
配置环境变量,定义当前模块的相对路径
LOCAL_PATH := $(call my-dir)
-
清空当前环境变量,除 LOCAL_PATH外的所有环境变量
include $(CLEAR_VARS)
-
编译生成的目标文件的文件名
LOCAL_MODULE := test
-
编译该模块所需的源文件,多个源文件使用连接符 "" 连接
LOCAL_SRC_FILES := test.c
-
编译所生成的目标文件的格式
include $(BUILD_EXECUTABLE) 二进制可执行文件 include $(SHARED_LIBRARIES) 动态库文件 include $(STATIC_LIBRARY) 静态库文件 include $(JAVA_LIBRARIES) jar包 include $(PACKAGE) apk
-
外部头文件路径申明
LOCAL_C_INCLUDES += ../../depend/
-
源文件路径声明
LOCAL_SRC_ROOT = ../../src LOCAL_SRC_DIR += global general helper
-
查找cpp源文件
LOCAL_SRC_PATH := $(patsubst %, $(LOCAL_SRC_ROOT)/%, $(LOCAL_SRC_DIR)) LOCAL_SRC_PATH += ../../src LOCAL_SRC_FILES += $(foreach dir, ${LOCAL_SRC_PATH}, $(wildcard $(dir)/*.cpp))
-
在工程中引入系统库
#system lib LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
-
引入第三方so库
#这种一般是编译好的so去链接,不需要去重新编译 LOCAL_LDFLAGS += -L../../depend/platformsdk LOCAL_LDLIBS += -lplatformsdk
-
引入第三方源码库
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:= libtest3 LOCAL_C_ALL_FILES := src/test1.cpp LOCAL_SRC_FILES := $(LOCAL_C_ALL_FILES) LOCAL_MODULE_PATH := $(LOCAL_PATH)/lib include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE:= test3 LOCAL_C_ALL_FILES := src/main.cpp LOCAL_SHARED_LIBRARIES += liblog LOCAL_SRC_FILES := $(LOCAL_C_ALL_FILES) LOCAL_MODULE_PATH := $(LOCAL_PATH)/bin include $(BUILD_EXECUTABLE)
-
代码中如何引入第三方头文件
#include "/inc/base/test.h" //这种引入头文件写起来比较麻烦 //可以在Android.mk文件修改下头文件路径 LOCAL_C_INCLUDES := $(LOCAL_PATH)/inc/base //然后代码中可以这样引入 include <test.h>
-
引入第三方静态库
LOCAL_LDFLAGS := $(LOCAL_PATH)/lib/libtest2.a
Application.mk
# 编译成什么类型的cpu的so文件
APP_ABI := armeabi
# 如何连接c++标准库
# stlport_static 静态链接
# stlport_shared 动态链接
# system 系统默认
# gnustl_static gnustl_shared Android上的GNU c++库,对应 GNU/LINUX 系统中的 libstdc++
# 这个库和gcc 仅仅绑定,但是后期不在更新,最新NDK不再支持,逐渐要废弃
APP_STL := gnustl_shared
#优化选项 此变量是可选的, release/debug debug 便于调试未被优化的二进制机器码
APP_OPTIM := release
APP_CPPFLAGS := frtti
APP_CPPFLAGS := -std=c++11
APP_CPPFLAGS := fpermissive
APP_CPPFLAGS := fexceptions
# SDK 使用的最低版本
APP_PLATFORM := android-11
CMakeLists.txt
-
set 设置路径
# set 可以设置单个文件路径或几个文件路径 以及设置路径 set(SRC_LIST hello.cpp) set(SRC_LIST hello.cpp add.cpp sub.cpp) set(SRC_LIST include/dsp)
-
日志打印
message("cmake path : ${CMAKE_SOURCE_DIR}")
-
设置头文件路径
include_directories(src/include src/include/depend)
-
设置链接库搜索目录
#添加共享库搜索路径 link_directories(src/depend src/platform)
-
批量添加cpp文件
set(CPP_SRC src/dsp) # 将目录下所有的cpp文件全都赋予 ALL_CPP file (GLOB ALL_CPP $(CPP_SRC)/*.cpp $(CPP_SRC)/alarm/*.cpp $(CPP_SRC)/android/*.cpp)
-
生成共享库文件
add_library( #生成共享库文件名字 mysdk # 共享库还是静态库 SHARED/STATIC SHARED #源码路径 ${ALL_CPP} )
-
为生成的库/可执行文件生成共享库链接
target_link_libraries( mysdk android log dsl platform )
-
生成可执行文件
add_executable(hello hello.cpp)
-
指定 .so 动态库的目录位置
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
-
指定生成版本号 VERSION 指动态库版本,SOVERSION指API版本
set_target_properties(math PROPERITIES VERSION 1.2 SOVERSION 1)
-
指定 cmake 最低编译版本
CMAKE_MINIMUM_REQUIRED(VERSION 3.14)
-
指定cpu架构
# 需要在build.gradle 中指定 android { defaultConfig { ... ndk { abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" } } externalNativeBuild { cmake { path "src/main/cpp/CMakeLists.txt" version "3.10.2" } } }