详解Android.mk

一、概述
在源码树中,一个模块的所有文件通常位于同一个文件夹中。为了将当前模块添加到整个build系统中,每个模块都需要一个专门的Make文件,该文件的名称为"Android.mk"。Build系统会扫描名称为"Android.mk"的文件,并根据该文件内容编译出相应的产物。

在Android Build系统中,编译是以模块(而不是文件)作为单位的,每个模块都有一个唯一的名称,一个模块的依赖对象只能是另外一个模块,而不能是其它类型的对象。

对于已经编译好的库使用 BUILD_PREBUILT 或 BUILD_MULTI_PREBUILT。

二、基本使用
Android.mk中可以定义多个编译模块,每个编译模块都是以include $(CLEAR_VARS)开始,以include $(BUILD_XXX)结束。

###############################################################################
# Drive
LOCAL_PATH := $(call my-dir)
 
my_archs := arm arm64 x86 x86_64
my_src_arch := $(call get-prebuilt-src-arch, $(my_archs))
 
include $(CLEAR_VARS)
LOCAL_MODULE := Drive
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_BUILT_MODULE_STEM := package.apk
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
#LOCAL_PRIVILEGED_MODULE :=
LOCAL_CERTIFICATE := PRESIGNED
#LOCAL_OVERRIDES_PACKAGES :=
LOCAL_DPI_VARIANTS := xxxhdpi xxhdpi xhdpi hdpi mdpi
LOCAL_DPI_FILE_STEM := $(LOCAL_MODULE)_$(my_src_arch)_%.apk
LOCAL_SRC_FILES := $(LOCAL_MODULE)_$(my_src_arch).apk
#LOCAL_REQUIRED_MODULES :=
LOCAL_MODULE_TARGET_ARCH := $(my_src_arch)
 
# When built, explicitly put it in the data partition except d2a
ifneq ($(TARGET_PRODUCT), tissot)
  LOCAL_MIUI_DATA_APP := $(TARGET_OUT_DATA)/miui/app
  LOCAL_MODULE_PATH := $(LOCAL_MIUI_DATA_APP)
  LOCAL_REPLACE_PREBUILT_APK_INSTALLED := $(LOCAL_PATH)/$(LOCAL_SRC_FILES)
endif
 
include $(BUILD_PREBUILT)
LOCAL_PATH := $(call my-dir)

每个Android.mk文件必须以定义LOCAL_PATH为开始,它用于在开发tree中查找源文件。宏my-dir则由编译系统提供,返回包含Android.mk的目录路径。

include $(CLEAR_VARS)

CLEAR_VARS变量由build system提供,定义在/build/core/config.mk中:CLEAR_VARS:=$(BUILD_SYSTEM)/clear_vars.mk),该语句的意思把build/core/clear_vars.mk文件包含进来,即由它负责清理很多LOCAL_xxx,但不清理LOCAL_PATH。因为所有的编译文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的,所以我们需要清空这些变量。但是LOCAL_PATH要求在每个模块中都要设置,所以无需清空。

LOCAL_MODULE := Drive

指示当前编译出来的模块名,必须,唯一且不能包含空格。如果未设置,则默认使用LOCAL_PACKAGE_NAME。如果再没有编译失败。

LOCAL_MODULE_CLASS

标识所编译模块最后放置的位置。
值可以是APPS,JAVA_LIBRARIES,SHARED_LIBRARIES,STATIC_LIBRARIES,EXECUTABLES
LOCAL_MODULE_CLASS := ETC #表示放于system/etc目录
LOCAL_MODULE_CLASS := EXECUTABLES #放于/system/bin
LOCAL_MODULE_CLASS := SHARED_LIBRARIES #放在/system/lib下
当遇到include $(BUILD_PREBUILT)的预编译选项时,需要在自己编写的Android.mk中明确指定LOCAL_MODULE_CLASS的值如ETC/APP等,从而帮助系统确认LOCAL_MODULE_PATH的路径。

LOCAL_MODULE_TAGS

在什么情况下去编译模块。当前模块所包含的标签,默认optional
//user : 模块只在user下编译
eng : 模块在eng模式下编译
tests: test状态下编译
optional: 此模块在所有版本下都编译

LOCAL_MODULE_SUFFIX  := $(COMMON_ANDROID_PACKAGE_SUFFIX)

后缀名,在build/core/config.mk 中定义

# Set the extensions used for various packages
COMMON_PACKAGE_SUFFIX := .zip
COMMON_JAVA_PACKAGE_SUFFIX := .jar
COMMON_ANDROID_PACKAGE_SUFFIX := .apk
LOCAL_BUILT_MODULE_STEM

编译目标要生成的文件名,带后缀。如果本地模块指定了LOCAL_MODULE_STEM话,他的值就是$(LOCAL_MODULE_STEM)$(LOCAL_MODULE_SUFFIX) 。

如果没有指定了的话就是$(LOCAL_MODULE)$(LOCAL_MODULE_SUFFIX)。java的执行文件则为package.apk

LOCAL_BUILT_MODULE 编译链接后的目标文件(文件路径+文件名)
LOCAL_BUILT_MODULE := ( b u i l t m o d u l e p a t h ) / (built_module_path)/ (builtmodulepath)/(LOCAL_BUILT_MODULE_STEM)

LOCAL_PRIVILEGED_MODULE

决定编译后在Rom中的安装位置,如果不设置或false,则为/system/app,设置为true,则在/system/priv-app

LOCAL_CERTIFICATE := PRESIGNED

表示apk使用原来的签名,即三方签名,若要使用系统签名,则LOCAL_CERTIFICATE := platform ,使apk可以获得系统权限。

#LOCAL_OVERRIDES_PACKAGES :=

让预置的apk覆盖原生的apk,被替换的apk是不应该被打包到系统镜像里面去的。不会生成对应的输出文件。

如:LOCAL_OVERRIDES_PACKAGES := WebViewGoogle Browser Browser2

LOCAL_SRC_FILES := $(LOCAL_MODULE)_$(my_src_arch).apk

当前模块所包含的源码文件

LOCAL_REQUIRED_MODULES

指定模块运行所依赖的模块

如:LOCAL_REQUIRED_MODULES := WebViewStub BookmarkProvider PartnerBookmarksProvider

LOCAL_MIUI_DATA_APP := $(TARGET_OUT_DATA)/miui/app

LOCAL_MODULE_PATH := $(LOCAL_MIUI_DATA_APP)

指定最后的目标安装路径:
TARGET_ROOT_OUT:表示根文件系统。
TARGET_OUT:表示 system文件系统。
TARGET_OUT_DATA:表示 data文件系统。

include $(BUILD_PREBUILT)

处理一个已经编译好的文件。

三、针对思考

1、/system/app目录和/system/priv-app目录的区别

从android 4.4开始,在system目录下新增了priv-app目录,该目录下的app一般都是系统核心应用,可以使用signatureOrSystem级别的权限 。例如:Settings里就定义了一些signatureOrSystem的权限:


Android 8.0以后,随着Privileged Permission Whitelisting的增加,priv-app略有变化。 除了处于priv-app目录之外,还必须将您的应用添加到白名单中以获得各种系统权限。例如:GMS中的/etc/permissions/privapp-permissions-google.xml

https://source.android.com/devices/tech/config/perms-whitelist

android 定义权限的时候有一个protectionLevel 属性,它有如下四种值。

normal :对用户隐私或者安全都不会带来影响,只要申请了就可以使用
dangerous :需要在manifest中声明且发送请求用户授权的intent,赋予某个组件中的其中一个权限,自动赋予组内其他所有权限,可用命令adb shell pm list permissions -d -g查看
signature:只有和定义了这个权限的apk用相同的私钥签名的应用才可以申请该权限。
signatureOrSystem:
只有和定义了这个权限的apk用相同的私钥签名的应用才可以申请该权限。
任意app只要标记了privileged(可暂理解为放到了/system/priv-app)就可以使用signatureOrSystem级别的权限
install 权限: normal ,signature ,signatureOrSystem

runtime权限:dangerous

https://developer.android.com/guide/topics/manifest/permission-element

https://www.jianshu.com/p/64041fa3e8e1

2、给三方app使用系统签名

在AndroidManifest.xml中添加android:sharedUserId=“android.uid.system”
在Android.mk文件中添加LOCAL_CERTIFICATE := platform
通过share user id,拥有同一个user id的多个apk可以配置成运行在同一个进程中。如上1.配置,让程序运行在系统进程中,这样就有权限调用那些系统权限的函数了。

程序运行在系统进程中还要有目标系统的platform key,build/target/product/security目录下的platform.pk8(私钥)和platform.x509.pem(公钥),如上2.就是用这两个key来签名

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系统中的一环。

四、主要make文件说明
main.mk
最主要的Make文件,首先对编译环境进行检查,同时引入其它的Make文件。

envsetup.mk
配置build系统需要的环境变量,例如:TARGET_PRODUCT,TARGET_BUILD_VARIANT,HOST_OS,HOST_ARCH 等。当前编译的主机平台信息(例如操作系统,CPU 类型等信息)就是在这个文件中确定的。另外,该文件中还指定了各种编译结果的输出路径。根据当前编译器的平台选择平台相关的 Make 文件。

dumpvar.mk
在build开始之前,显示此次Build的配置信息

config.mk
整个build系统的配置文件,最重要的make文件之一。该文件主要包含以下主要内容:

定义了许多常量来负责不同模块的编译

定义编译参数以及常见文件后缀,例如 .zip,.jar.apk。

根据BoardConfig.mk文件,配置产品相关参数

设置一些常用工具的路径,例如 flex,e2fsck,dx。

definitions.mk
最重要的make文件之一,在其中定义了大量函数,这些函数都是build系统其它文件所用到的。例如:my-dir,all-subdir-makefiles,find-subdir-files,sign-package 等,关于这些函数的说明请参见每个函数的代码注释。

distdir.mk
针对dist目标的定义。dist目标用来拷贝文件到指定路径

dex_preopt.mk
针对启动jar包的预先优化

五、其它主要Make目标
make clean 执行清理,等同于rm -rf out/
make sdk 编译出android的sdk
make update-api
更新 API,在 framework API 改动之后,需要首先执行该命令来更新 API,公开的 API 记录在 frameworks/base/api 目录下。
make dist
执行 Build,并将 MAKECMDGOALS 变量定义的输出文件拷贝到 /out/dist 目录。
make all 编译所有内容,不管当前产品的定义中是否会包含
make help 帮助信息,显示主要的 make 目标
make snod 从已经编译出的包快速重建系统镜像
make libandroid_runtime 编译所有JNI framework内容
make framework 编译所有Java framework内容
make services 编译系统服务和相关内容
make 编译一个指定模块,local_target为模块的名称
make clean 清理一个指定模块的编译结果
make dump-products 显示所有产品的编译配置信息,例如:产品名,产品支持的地区语言,产品中会包含的模块等信息
make bootimage 生成boot.img
make recoveryimage 生成recovery.img
make userdataimage 生成userdata.img
make cacheimage 生成cache.img

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android.mkAndroid提供的一种makefile文件,用来指定诸如编译生成so库名、引用的头文件目录、需要编译的.c/.cpp文件和.a静态库文件等。它的作用是帮助开发者在Android项目中管理和编译NDK代码。在一个Android子项目中,可以存在一个或多个Android.mk文件。如果只有一个Android.mk文件,可以直接参考NDK的sample目录下的hello-jni项目。如果需要编译的模块比较多,可以将对应的模块放置在相应的目录中,并在每个目录中定义对应的Android.mk文件。最后,在根目录放置一个Android.mk文件,通过include $(call all-subdir-makefiles)来包含所有子目录中的Android.mk文件。Android.mk文件可以用来组织源文件成模块,包括静态库和动态库。静态库可以通过include $(BUILD_STATIC_LIBRARY)来编译生成,动态库可以通过include $(BUILD_SHARED_LIBRARY)来编译生成。掌握Android.mk的语法规范对于熟练掌握JNI开发是必要的。\[2\]\[3\] #### 引用[.reference_title] - *1* [Android.mk解析与使用](https://blog.csdn.net/hejnhong/article/details/120585740)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Android.mk语法规范](https://blog.csdn.net/liukun321/article/details/8848417)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Android.mk用法详解](https://blog.csdn.net/fengruoying93/article/details/111241803)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值