ndk-build命令
1.0、参考
1.1、ndk-build命令的作用

ndk-build命令用于构建用于Android系统的静态库动态库可执行文件

1.2、ndk-build命令的实现原理

使用如下命令查看ndk-build命令的内容:

cat $(command -v ndk-build)

其内容如下:

#!/bin/sh
DIR="$(cd "$(dirname "$0")" && pwd)"
$DIR/build/ndk-build "$@"

这个脚本的作用就是调用$ANDROID_NDK_HOME/build/ndk-build脚本,并把传给ndk-build命令的所有参数全部传递给$ANDROID_NDK_HOME/build/ndk-build

$ANDROID_NDK_HOME/build/ndk-build脚本的作用是解析参数,并最终调用gmake命令:

$GNUMAKE -f $ANDROID_NDK_HOME/build/core/build-local.mk "$@"

$ANDROID_NDK_HOME/build/core/build-local.mk主要做4件事情:

  • 确定NDK_PROJECT_PATH变量的值:
    如果在执行ndk-build命令的时候指定了该变量的值,就使用该值;
    如果在执行ndk-build命令的时候没有指定该变量的值,就使用当前目录。
  • 确定NDK_APPLICATION_MK变量的值:
    如果在执行ndk-build命令的时候指定了该变量的值,就使用该值;
    如果在执行ndk-build命令的时候没有指定该变量的值,就使用$NDK_PROJECT_PATH/jni/Application.mk; 如果$NDK_PROJECT_PATH/jni/Application.mk不存在,就使用$ANDROID_NDK_HOME/build/core/default-application.mk
  • 确定APP_BUILD_SCRIPT变量的值:
    如果在执行ndk-build命令的时候指定了该变量的值,就使用该值;
    如果在执行ndk-build命令的时候没有指定该变量的值,就使用$NDK_PROJECT_PATH/jni/Android.mk; 如果$NDK_PROJECT_PATH/jni/Android.mk不存在,就报错。
  • 编译

注意:虽然我们编写的代码可能不涉及到jni,但是,在没有指定NDK_APPLICATION_MKAPP_BUILD_SCRIPT两个变量的情况下, 会去$NDK_PROJECT_PATH/jni目录下找Application.mkAndroid.mk,至于为什么是去jni目录下找,可能当时编写ndk-build命令的那个家伙实在不知道该使用一个什么名字的目录吧。

流程总结:

ndk-build [option]... [VARIABLE=VLAUE]...
    ⥥
$ANDROID_NDK_HOME/build/ndk-build "$@"
    ⥥
$GNUMAKE -f $ANDROID_NDK_HOME/build/core/build-local.mk "$@"
    ⥥
evaluate $(NDK_PROJECT_PATH)
    ⥥
evaluate $(NDK_APPLICATION_MK)
    ⥥
evaluate $(APP_BUILD_SCRIPT)
    ⥥
build start
1.3、ndk-build命令的使用格式

1.2、ndk-build命令的实现原理,我们知道:ndk-build命令实际上是对gmake命令的包装。 所以,ndk-build命令的使用格式与gmake命令的使用格式完全一样。如下:

ndk-build [option]... [VARIABLE=VLAUE]... [target]...

optionVARIABLE=VLAUEtarget三者之间可以随意互换位置。

optionVARIABLE=VLAUEtarget包括2部分:

  • $ANDROID_NDK_HOME/build/ndk-build$ANDROID_NDK_HOME/build/core/build-local.mkApplication.mkAndroid.mk中定义的。
  • gmake命令的支持的。
1.3.1、$ANDROID_NDK_HOME/build/core/build-local.mk中定义的变量
变量类型默认值说明
Vswitch0

0:不显示执行的命令

1:    显示执行的命令

NDK_LOGswitch0

0:不显示日志

1:    显示日志

NDK_DEBUGswitch1

0:不带调试符号

1:    带调试符号

NDK_HOST_32BITswitch0

0:64bit

1:32bit

NDK_PROJECT_PATHDIR_PATH当要构建的源码不在当前目录下,或者Application.mkAndroid.mk不在jni目录下的时候,需要通过此变量指定
NDK_APPLICATION_MKFILE_PATHApplication.mk不在jni目录下的时候,需要通过此变量指定
APP_BUILD_SCRIPTFILE_PATHAndroid.mk不在jni目录下的时候,需要通过此变量指定
GEN_COMPILE_COMMANDS_DBbooleanfalse是否生成JSON Compilation Database

使用示例:

ndk-build V=1 NDK_LOG=1 GEN_COMPILE_COMMANDS_DB=true
SOURCE_PATH=$HOME/libwebp-1.0.2
ndk-build NDK_PROJECT_PATH="$SOURCE_PATH" APP_BUILD_SCRIPT="$SOURCE_PATH/Android.mk" APP_PLATFORM=android-21
1.3.2、Application.mk中定义的变量 

使用示例:

ndk-build APP_PLATFORM=21 APP_ABI=armeabi-v7a
1.3.3、Android.mk中定义的变量 

使用示例:

ndk-build LOCAL_CFLAGS='-v -Os'
1.3.4、支持的target

clean任务用于删除构建后生成的libsobj目录:

ndk-build clean
1.4、ndk-build命令被Android Gradle Plugin调用 

Gradle Kotlin DSL ⤵︎

android {
    externalNativeBuild {
        ndkBuild {
            setPath("src/main/jni/Android.mk")
        }
    }
}

Gradle Groovy DSL ⤵︎

android {
    externalNativeBuild {
        ndkBuild {
            path 'src/main/jni/Android.mk'
        }
    }
}
1.5、ndk-build命令的注意事项

AndroidStudio 2.2 PreView3之后创建的Android工程,默认使用CMake进行构建的, 与ndk-build不一样,要注意这一点,你从GitHub上下载的新项目,留意一下。