之前的测试,使用的都是非常老的 NDK —— NDK-r10b,好像是2014年发布的。

使用新的 NDK-r23e 后,代码中的makefile等也无需做什么调整,可以直接使用。

但还是碰到个跟跨系统环境 有关的大坑:

我是在 win10 环境下载的 NDK-r23e.zip,并且是在win10环境解压的,

然后在wsl中使用 ndk-build 就出现莫命其妙的错误提示!

一直以为是因为自己不熟悉ndk的原因,百度、bing 各种搜索都没有找到解法,

愣是卡了两天。。。

直到今天,win10环境写 shell 脚本在 wsl 中运行莫名其妙提示有语法错误,

才想到是换行符不同,然后才想到可能是 跨操作系统解压 导致新的NDK-r23e调用出错。

然后换到 wsl 中解压,真的就没问题了。。。

想来有可能是压缩包内的文件软链和换行符不同造成的。

加上 ndk 从某个版本开始弃用了gcc,换成 clang ,让人误以为跟这个也有关,总觉得切NDK版本后代码里面需要调整一些地方。。。

新/旧 NDK 都支持 makefile(ndk-build) 和 cmake 两种代码编译方式

makefile(ndk-build) 编译方式:

需要在源码目录中建立 jni 文件夹,里面放 Android.mk 和 Application.mk

Android.mk 内容:

LOCAL_PATH 		:= $(call my-dir)
include			$(CLEAR_VARS)
LOCAL_MODULE    := 项目名称


# 编译输出类型,参考: https://android-doc.github.io/ndk/guides/android_mk.html
ifeq ($(BUILD_MODULE_AS_APK),1)

	#编译为 .so,然后再用 apktool 打包为apk

	LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM
	LOCAL_SRC_FILES :=	src/xxx.c \
						src/yyyy.c
	LOCAL_CFLAGS += -DBUILD_MODULE_AS_APK=$(BUILD_MODULE_AS_APK)
	LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
	LOCAL_STATIC_LIBRARIES := android_native_app_glue
	LOCAL_OUTPUT_TYPE = $(BUILD_SHARED_LIBRARY)
else

	#编译为 command line tool

	LOCAL_SRC_FILES := main_cli.c
	LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
	LOCAL_OUTPUT_TYPE = $(BUILD_EXECUTABLE)
endif


include $(LOCAL_OUTPUT_TYPE)
$(call import-module,android/native_app_glue)

Application.mk 内容:

APP_ABI		:= arm64-v8a # x86 #all
 APP_PLATFORM:= android-10
#APP_PLATFORM:= android-16

编译步骤:

cd  代码根目录(即包含 jni 文件夹的目录)

然后执行 $NDK_DIR/ndk-build 即可

第二种,cmake 编译方式

仅需编写 CMakeLists.txt :

#指定CMake最低的编译版本
CMAKE_MINIMUM_REQUIRED(VERSION 3.14)

# 定义一个工程名
PROJECT(MAKE_SO)

#搜集src目录下的所有的 源文件
AUX_SOURCE_DIRECTORY(${PROJECT_SOURCE_DIR}/src SRC_LIST) #找到src目录下所有源文件赋值给SRC_LIST
#另一种写法
#FILE(GLOB SRC_LIST "${PROJECT_SOURCE_DIR}/src/*.c" "${PROJECT_SOURCE_DIR}/src/*.cpp")

#指定头文件目录
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)

#指定 so的生成目录 lib
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

# 打印
MESSAGE(STATUS "srclist: " ${SRC_LIST})
#-- srclist: /home/ubuntu/learnC/learnCMakeList/make-so/src/main.c/home/ubuntu/learnC/learnCMakeList/make-so/src/sum.c

#生成动态库 默认生成静态库,SHARED指定动态库
ADD_LIBRARY(make_so SHARED ${SRC_LIST})

以及一个 build.sh 文件:

#!/bin/bash
rm -rf build
mkdir build
cd build
#设置交叉编译的参数
NDK_ROOT=/mnt/d/downloads/android-ndk-r23b
echo ${NDK_ROOT}
cmake \
-DANDROID_NDK=${NDK_ROOT} \
-DCMAKE_TOOLCHAIN_FILE=${NDK_ROOT}/build/cmake/android.toolchain.cmake \
-DANDROID_ABI="arm64-v8a" \
-DANDROID_NATIVE_API_LEVEL=19 \
..
make

编译得到的 .so 打包为 apk  并签名参考:build-apk-with-c: 纯C语言开发无java、无dex的安卓apk应用的示例