Android.mk文件中的内容详解

一、简介

在官网对 Android.mk 的介绍中写道:
Android.mk 文件位于项目 jni/ 目录的子目录中,用于向构建系统描述源文件和共享库。

二、基础知识

这里介绍一些Android.mk 文件所含内容的基本信息。举例如下:

# 注释内容使用 "#" 号
 
# := 是赋值
# $() 是取值
# call 是调用一个系统提供的宏函数,此处是 my-dir
LOCAL_PATH := $(call my-dir)
 
# 我们也可以使用 ifeq 和 ifneq 进行条件判断
ifeq ($(HOST_OS, linux))
    ...(省略)
else
    ...(省略)
endif
 
# 使用 := 是赋值,当某一行很长时,可以使用反斜杠 \ 换行
LOCAL_SRC_FILES := adb.c \
                   utils.c
 
# 使用 += 是附加
LOCAL_SRC_FILES += $(USB_SRCS)

对于一些文件中必须存在的变量,作出解释如下:

Android.mk 文件必须先定义 LOCAL_PATH 变量:

LOCAL_PATH := $(call my-dir)

此变量表示源文件在开发树中的位置。在上述命令中,构建系统提供的宏函数 my-dir 将返回当前目录(Android.mk 文件本身所在的目录)的路径。

下一行要声明 CLEAR_VARS 变量,其值由构建系统提供。

include $(CLEAR_VARS)

CLEAR_VARS 变量指向一个特殊的 GNU Makefile,后者会为您清除许多 LOCAL_XXX 变量。
例如 LOCAL_MODULELOCAL_SRC_FILESLOCAL_STATIC_LIBRARIES
请注意,GNU Makefile 不会清除 LOCAL_PATH。此变量必须保留其值,因为系统在单一 GNU Makefile 执行上下文(其中的所有变量都是全局变量)中解析所有构建控制文件。在描述每个模块之前,您必须声明(重新声明)此变量。

最后一行帮助系统将一切连接到一起:

include $(BUILD_PACKAGE)

BUILD_PACKAGE是用来编译生成 package/app/ 下的apk

三、NDK 定义的 include 变量

构建系统在解析 Android.mk 文件前定义了 GNU Make 变量。在某些情况下,NDK 可能会多次解析 Android.mk 文件,每次使用其中某些变量的不同定义。

CLEAR_VARS

CLEAR_VARS 变量由Build System提供。并指向一个指定的GNU Makefile。

include $(CLEAR_VARS)

由它负责清理很多LOCAL_xxx,但不清理LOCAL_PATH
这个清理动作是必须的,因为所有的编译控制文件由同一个GNU Make解析和执行,其变量是全局的。所以清理后才能避免相互影响

BUILD_EXECUTABLE

BUILD_EXECUTABLE 收集 LOCAL_XXX 变量中提供的模块的所有相关信息,以及确定如何根据所列出的源文件构建目标可执行文件。

include $(BUILD_EXECUTABLE)

表示编译成可执行程序
请注意:使用此脚本要求您至少已经为 LOCAL_MODULELOCAL_SRC_FILES 赋值
注意:大多数 Android 应用不包含可执行文件,但它们对于创建单元测试和其他调试工具很有用

BUILD_SHARED_LIBRARY

BUILD_SHARED_LIBRARY 收集 LOCAL_XXX 变量中提供的模块的所有相关信息,以及确定如何根据所列出的源文件构建目标共享库。

include $(BUILD_SHARED_LIBRARY)

表示编译成动态库
注意,使用此脚本要求您至少已经为 LOCAL_MODULE 和 LOCAL_SRC_FILES 赋值
共享库变量会导致构建系统生成扩展名为 .so 的库文件

BUILD_STATIC_LIBRARY

BUILD_STATIC_LIBRARY 是用于构建静态库的 BUILD_SHARED_LIBRARY 的变体。构建系统不会将静态库复制到您的项目/软件包中,但可以使用静态库构建共享库。

include $(BUILD_STATIC_LIBRARY)

表示编译成静态库
静态库变量会导致构建系统生成扩展名为 .a 的库

BUILD_PACKAGE

BUILD_PACKAGE 用来编译生成package/app/下的apk。

include $(BUILD_PACKAGE)

四、目标信息变量

本部分介绍构建系统每次解析 Android.mk 时定义的变量。

TARGET_ARCH

构建系统解析此 Android.mk 文件时指向的 CPU 系列。
此变量将是下列其中一项:arm、arm64、x86 或 x86_64。

PLATFORM_VERSION

构建系统解析此 Android.mk 文件时指向的Android版本号的识别。

ifeq ($(PLATFORM_VERSION), 8.1.0)
    # ... do something ...
else
    # ... do something ...
endif

TARGET_PLATFORM

构建系统解析此 Android.mk 文件时指向的 Android API 级别号。
例如,Android 5.1 系统映像对应于 Android API 级别 22:android-22。

ifeq ($(TARGET_PLATFORM),android-22)
    # ... do something ...
endif

TARGET_ARCH_ABI

构建系统解析此 Android.mk 文件时指向的 ABI。
下表显示了用于每个受支持 CPU 和架构的 ABI 设置:

CPU 和架构设置
ARMv7armeabi-v7a
ARMv8 AArch64arm64-v8a
i686x86
x86-64x86_64

示例演示如何检查 ARMv7 是否为目标 CPU 与 ABI 的组合如下:

ifeq ($(TARGET_ARCH_ABI), armeabi-v7a)
  # ... do something ...
endif

未来的新目标 ABI 将使用不同的值

TARGET_ABI

目标 Android API 级别与 ABI 的串联,特别适用于要针对实际设备测试特定目标系统映像的情况。
例如,要检查在 Android API 级别 22 上运行的 64 位 ARM 设备

ifeq ($(TARGET_ABI),android-22-arm64-v8a)
  # ... do something ...
endif

五、模块描述变量

此部分中的变量会向构建系统描述咱们的模块。每个模块描述都应遵守以下基本流程:

  1. 使用 CLEAR_VARS 变量初始化或取消定义与模块相关的变量。
  2. 为用于描述模块的变量赋值。
  3. 使用 BUILD_XXX 变量设置 NDK 构建系统,使其将适当的构建脚本用于该模块。

LOCAL_PATH

LOCAL_PATH 用于指定当前文件的路径。必须在 Android.mk 文件开头定义此变量。

LOCAL_PATH := $(call my-dir)

CLEAR_VARS 所指向的脚本不会清除此变量。因此,即使 Android.mk 文件描述了多个模块,也只需定义此变量一次

LOCAL_MODULE

LOCAL_MODULE 用于存储模块名称。指定的名称在所有模块名称中必须唯一,并且不得包含任何空格。
必须先定义该名称,然后才能添加任何脚本(CLEAR_VARS 的脚本除外)。
无需添加 lib 前缀或 .so.a 文件扩展名;构建系统会自动执行这些修改。在整个 Android.mk 和 Application.mk 文件中,请用未经修改的名称引用模块。
例如,以下行会导致生成名为 libfoo.so 的共享库模块:

LOCAL_MODULE := "foo"

如果希望生成的模块使用除“lib + LOCAL_MODULE 的值”以外的名称,可以使用 LOCAL_MODULE_FILENAME 变量为生成的模块指定自己选择的名称

LOCAL_MODULE_FILENAME

LOCAL_MODULE_FILENAME 可选变量能够替换构建系统为其生成的文件默认使用的名称。
例如,如果 LOCAL_MODULE 的名称为 foo,可以强制系统将其生成的文件命名为 libnewfoo,如下:

LOCAL_MODULE := foo
LOCAL_MODULE_FILENAME := libnewfoo

对于共享库模块,此示例将生成一个名为 libnewfoo.so 的文件
注意:无法替换文件路径或文件扩展名

LOCAL_SRC_FILES

LOCAL_SRC_FILES 包含构建系统生成模块时所用的源文件列表。只列出构建系统实际传递到编译器的文件,因为构建系统会自动计算所有相关的依赖项。

LOCAL_SRC_FILES += src/com/chris/xxx.java \

请注意,可以使用相对(相对于 LOCAL_PATH)和绝对文件路径
建议避免使用绝对文件路径;相对路径可以提高 Android.mk 文件的移植性
注意:务必在构建文件中使用 Unix 样式的正斜杠 (/),构建系统无法正确处理 Windows 样式的反斜杠 ()

LOCAL_STATIC_JAVA_LIBRARIES

LOCAL_STATIC_JAVA_LIBRARIES 表示把引用的外部Java库直接编译打包到本模块中,在runtime时可以直接从本模块中找到相关的东西。

LOCAL_STATIC_JAVA_LIBRARIES := \
			chris.a.xxx \
			chris.b.yyy \

指定依赖的静态java类库,最终会打包到apk里面
当前模块依赖的java静态库,在android里,导入的jar包和引用的第三方工程都属于java静态库

LOCAL_JNI_SHARED_LIBRARIES

LOCAL_JNI_SHARED_LIBRARIES 变量主要是用在JNI的编译中,如果你要在你的Java代码中引用JNI中的共享库 *.so,此变量就是共享库的名字。
那么你要注意的一点是:在你的Project根目录下的Android.mk中要定义此变量用来引用你要使用的JNI中的共享库 *.so

LOCAL_JNI_SHARED_LIBRARIES := \
				libxxx_jni \

定义了要包含的so库文件的名字,如果程序没有采用jni,则不需要

LOCAL_REQUIRED_MODULES

LOCAL_REQUIRED_MODULES 指定模块运行所依赖的模块(模块安装时将会同步安装它所依赖的模块)

LOCAL_REQUIRED_MODULES:= \
				libxxx \

LOCAL_RESOURCE_DIR

LOCAL_RESOURCE_DIR 指定编译的资源文件文件路径。

LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/res

LOCAL_PACKAGE_NAME

LOCAL_PACKAGE_NAME 指定当前APK应用的名称(编译的apk的名称),如下:

LOCAL_PACKAGE_NAME := ChrisChenAppServer

LOCAL_MODULE_TAGS

LOCAL_MODULE_TAGS 指定编译版本,版本有 eng、user、tests 版本参与编译;optional值所有版本都参与编译。

LOCAL_MODULE_TAGS:= user / eng / tests / optional  可选定义

user: 指该模组只在 user 版本下才编译
eng: 指该模组只在 eng 版本下才编译
tests: 指该模组只在 tests 版本下才编译
optional:指该模组在所有版本下都编译

LOCAL_CERTIFICATE

LOCAL_CERTIFICATE 使用平台文件签名,用于设置不同的签名方式。由它指定用哪个key签名,未指定的默认用testkey。

LOCAL_CERTIFICATE:= testkey / platform / shared / media 可选定义

build/target/product/security目录中有四组默认签名供Android.mk在编译APK使用:

  1. testkey:普通APK,默认情况下使用。
  2. platform:该APK完成一些系统的核心功能。经过对系统中存在的文件夹的访问测试,这种方式编译出来的APK所在进程的UID为system。
  3. shared:该APK需要和home/contacts进程共享数据。
  4. media:该APK是media/download系统中的一环。

LOCAL_PRIVATE_PLATFORM_APIS

LOCAL_PRIVATE_PLATFORM_APIS 指定使用sdk的hide的api来编译。

LOCAL_PRIVATE_PLATFORM_APIS := true

设置后,会使用sdk的hide的api来编译

六、NDK 提供的函数宏

此处介绍 NDK 提供的 GNU Make 函数宏。使用 $(call <function>) 可以对其进行求值;其返回文本信息。

my-dir

my-dir 返回最后包括的 makefile 的路径,通常是当前 Android.mk 的目录。
my-dir 可用于在 Android.mk 文件开头定义 LOCAL_PATH。

LOCAL_PATH := $(call my-dir)

由于 GNU Make 的工作方式,这个宏实际返回的是构建系统解析构建脚本时包含的最后一个 makefile 的路径。因此,包括其他文件后就不应调用 my-dir。

其他内容可参考官网对 Android.mk 的介绍

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值