Android.mk 简单分析记录

sancaiodm Android源码学习 2021-10-23 1984 0

LOCAL_PATH:= $(call my-dir)    //指定Android.mk文件所在的目录。
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := Settings
LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)       //集成带源码的APP使用此命令
include $(BUILD_PREBUILT)      //集成无源码的APK使用此命令
# Use the folloing include to make our test apk.
include $(call all-makefiles-under,$(LOCAL_PATH))

该Android.mk文件路径是package/app/Settings/Android.mk,来分析该文件

GNU Make‘功能’宏,必须通过使用'$(call  )'来调用,调用他们将返回文本化的信息。

------------------------------------------------------------------------------------------------------------------------------

(1) LOCAL_PATH:= $(call my-dir)       //指定Android.mk文件所在的目录。

一个Android.mk file首先必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件。

宏函数’my-dir’,由编译系统提供,用于返回当前路径(即包含Android.mk file文件的目录)。

------------------------------------------------------------------------------------------------------------------------------

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

(2.1) include $(CLEAR_VARS)

CLEAR_VARS指的是clear_vars.mk,由编译系统提供,它会让GNU MAKEFILE为你清除除LOCAL_PATH以外的所有LOCAL_XXX变量,如LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_SHARED_LIBRARIES,LOCAL_STATIC_LIBRARIES等。

这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的。

(2.2) include $(BUILD_PACKAGE)      # Tell it to build an APK

$(BUILD_PACKAGE)是用来编译生成package/app/下的apk。

还有其他几种编译情况:

include $(BUILD_STATIC_LIBRARY)   表示编译成静态库

include $(BUILD_SHARED_LIBRARY)  表示编译成动态库

include $(BUILD_EXECUTABLE)      表示编译成可执行程序         

至于例子的话,跳转到下面的"扩展"

------------------------------------------------------------------------------------------------------------------------------

(3) LOCAL_MODULE_TAGS := optional

解析:

LOCAL_MODULE_TAGS :=user eng tests optional

user:  指该模块只在user版本下才编译

eng:  指该模块只在eng版本下才编译

tests: 指该模块只在tests版本下才编译

optional:指该模块在所有版本下都编译

取值范围debug eng tests optional samples shell_ash shell_mksh。注意不能取值user,如果要预装,则应定义core.mk。

------------------------------------------------------------------------------------------------------------------------------

(4) LOCAL_SRC_FILES := $(call all-java-files-under, src)

(4.1) 如果要包含的是java源码的话,可以调用all-java-files-under得到。(这种形式来包含local_path目录下的所有java文件)

(4.2) 当涉及到C/C++时,LOCAL_SRC_FILES变量就必须包含将要编译打包进模块中的C或C++源代码文件。注意,在这里你可以不用列出头文件和包含文件,因为编译系统将会自动为你找出依赖型的文件;仅仅列出直接传递给编译器的源代码文件就好。

all-java-files-under宏的定义是在build/core/definitions.mk中。

------------------------------------------------------------------------------------------------------------------------------

(5) LOCAL_PACKAGE_NAME := Settings

package的名字,这个名字在脚本中将标识这个app或package。

------------------------------------------------------------------------------------------------------------------------------

(6) LOCAL_CERTIFICATE := platform

LOCAL_CERTIFICATE 后面是签名文件的文件名,说明Settings.apk是一个需要platform key签名的APK

------------------------------------------------------------------------------------------------------------------------------

(7) include $(BUILD_PACKAGE)

在(2.2)中已作解释

------------------------------------------------------------------------------------------------------------------------------

(8) include $(call all-makefiles-under,$(LOCAL_PATH))

加载当前目录下的所有makefile文件,all-makefiles-under会返回一个位于当前'my-dir'路径的子目录中的所有Android.mk的列表。

all-makefiles-under宏的定义是在build/core/definitions.mk中。

------------------------------------------------------------------------------------------------------------------------------

这个Android.mk文件最后就生成了Settings.apk。分析完上面的Android.mk文件后,来总结下各种LOCAL_XXX。

三种情况说明:

    必须定义, 在app或package的Android.mk中必须给定值。

    可选定义,在app或package的Android.mk中可以也可以不给定值。

    不用定义,在app或package的Android.mk中不要给定值,脚本自动指定值。

LOCAL_PATH,          当前路径,必须定义。
LOCAL_PACKAGE_NAME,  必须定义,package的名字,这个名字在脚本中将标识app或package。
LOCAL_MODULE_SUFFIX, 不用定义,module的后缀,=.apk。
#LOCAL_MODULE_SUFFIX   := $(COMMON_ANDROID_PACKAGE_SUFFIX)  //该模块的后缀,
LOCAL_MODULE,        不用定义,=$(LOCAL_PACKAGE_NAME)。
LOCAL_JAVA_RESOURCE_DIRS,     不用定义。
LOCAL_JAVA_RESOURCE_FILES,    不用定义。
LOCAL_MODULE_CLASS,  不用定义。
LOCAL_MODULE_TAGS,   可选定义。默认optional。取值范围user debug eng tests optional samples shell_ash shell_mksh。
LOCAL_ASSET_DIR,     可选定义,推荐不定义。默认$(LOCAL_PATH)/assets
LOCAL_RESOURCE_DIR,  可选定义,推荐不定义。默认product package和device package相应的res路径和$(LOCAL_PATH)/res。
LOCAL_PROGUARD_ENABLED,       可选定义,默认为full,如果是user或userdebug。取值full, disabled, custom。
full_android_manifest,        不用定义,=$(LOCAL_PATH)/AndroidManifest.xml。
LOCAL_EXPORT_PACKAGE_RESOURCES,    可选定义,默认null。如果允许app的资源被其它模块使用,则设置true。
LOCAL_CERTIFICATE,   可选定义,默认为testkey。最终
        private_key := $(LOCAL_CERTIFICATE).pk8
        certificate := $(LOCAL_CERTIFICATE).x509.pem

扩展:在一个Android.mk中可以生成多个可执行程序、动态库和静态库。

(1)编译APK应用程序模板。
关于编译APK应用程序的模板请参照《Android.mk编译APK范例

 

(2)编译JAVA库模板
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Any libraries that this library depends on
LOCAL_JAVA_LIBRARIES := android.test.runner
# The name of the jar file to create
LOCAL_MODULE := sample
# Build a static jar file.
include $(BUILD_STATIC_JAVA_LIBRARY)
  :LOCAL_JAVA_LIBRARIES := android.test.runner表示生成的JAVA库的jar文件名
 
(3)编译C/C++应用程序模板如下

LOCAL_PATH := $(call my-dir)
#include $(CLEAR_VARS)
LOCAL_SRC_FILES := main.c
LOCAL_MODULE := test_exe
#LOCAL_C_INCLUDES :=#LOCAL_STATIC_LIBRARIES :=#LOCAL_SHARED_LIBRARIES :=include $(BUILD_EXECUTABLE)

 :‘:=’是赋值的意思,'+='是追加的意思,‘$’表示引用某变量的值

LOCAL_SRC_FILES中加入源文件路径,LOCAL_C_INCLUDES中加入需要的头文件搜索路径
LOCAL_STATIC_LIBRARIES 加入所需要链接的静态库(*.a)的名称,
LOCAL_SHARED_LIBRARIES 中加入所需要链接的动态库(*.so)的名称,LOCAL_MODULE表示模块最终的名称,BUILD_EXECUTABLE 表示以一个可执行程序的方式进行编译。
(4)编译C\C++静态库

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
 helloworld.c
LOCAL_MODULE:= libtest_static
 #LOCAL_C_INCLUDES :=#LOCAL_STATIC_LIBRARIES :=#LOCAL_SHARED_LIBRARIES :=include $(BUILD_STATIC_LIBRARY)

 和上面相似,BUILD_STATIC_LIBRARY 表示编译一个静态库。

(5)编译C/C++动态库的模板

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := helloworld.c
LOCAL_MODULE := libtest_shared
TARGET_PRELINK_MODULES := false#LOCAL_C_INCLUDES :=#LOCAL_STATIC_LIBRARIES :=#LOCAL_SHARED_LIBRARIES :=include $(BUILD_SHARED_LIBRARY)

和上面相似,BUILD_SHARED_LIBRARY 表示编译一个共享库。

以上三者的生成结果分别在如下目录中,generic 依具体 target 会变(可能是dkb~~):
out/target/product/generic/obj/APPS
out/target/product/generic/obj/JAVA_LIBRARIES
out/target/product/generic/obj/EXECUTABLE
out/target/product/generic/obj/STATIC_LIBRARY
out/target/product/generic/obj/SHARED_LIBRARY

每个模块的目标文件夹分别为:

1)APK程序:XXX_intermediates
2)JAVA库程序:XXX_intermediates
3)C\C++可执行程序:XXX_intermediates
4)C\C++静态库: XXX_static_intermediates
5)C\C++动态库: XXX_shared_intermediates

转载声明:上文出自:https://www.cnblogs.com/chenbin7/archive/2013/01/05/2846863.html



include $(BUILD_PACKAGE)       //集成带源码的APP使用此命令
include $(BUILD_PREBUILT)      //集成无源码的APK使用此命令

LOCAL_SRC_FILES := $(call all-subdir-java-files)        //集成带源码的APP使用此命令
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk                  //集成无源码的APK使用此命令
LOCAL_MODULE_TAGS    := optional        //任意版本下都可以定义
LOCAL_PROGUARD_ENABLED := disabled        //不要使用代码混淆的工具进行混淆
# 编译 apk 文件
LOCAL_MODULE_CLASS := APPS
# 编译 jar 包
LOCAL_MODULE_CLASS := JAVA_LIBRAYIES
# 定义动态库文件
LOCAL_MODULE_CLASS := SHARED_LIBRAYIES
# 编译可执行文件
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_CERTIFICATE指apk的签名,可以有: testkey, media ,platform ,shared ,如果文件已经签过名,则使用PRESIGNED。
LOCAL_MODULE_PATH   指定模块在目标系统的安装路径。
LOCAL_PRODUCT_MODULE :=true   //向product分区中安装模块,需添加此编译标记
Androoid.dp中的写法 product_specific:true
LOCAL_MODULE_PATH := $(TARGET_OUT)/vendor/system/app   //vendor目录下,用户可以卸载并且恢复出厂设置时能够恢复
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)     //data/app目录下,用户可以卸载 恢复出厂设置时不能够恢复
$(TARGET_OUT)/priv-app这个路径下,apk不可卸载。
$(TARGET_OUT_DATA_APPS)这个路径下apk卸载后不再恢复
$(TARGET_OUT)/vendor/operator/app这个路径下apk卸载后恢
LOCAL_MULTILIB := both   //32位,64位都可使用
LOCAL_OVERRIDES_PACKAGES := HTMLViewer   //此APK替换掉HTMLViewer,
LOCAL_DEX_PREOPT := true /fase //默认情况下编译会生成apk 和 odex 两个文件,其中apk里面是不包含classes.dex文件的,因此不能直接安装
//即ROM中的system/priv-app/下的app,通过PackageManager拿到的ApplicationInfo,其privateFlags字段<<3标志位为1,即ApplicationInfo.PRIVATE_FLAG_PRIVILEGED。也就是说,LOCAL_PRIVILEGED_MODULE为true编译的app即所谓privileged app(特权app)
LOCAL_PRIVILEGED_MODULE = true 设置为true编译的app,
#混淆文件名
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
#关闭混淆
LOCAL_PROGUARD_ENABLED := disabled

PRODUCT_COPY_FILES += /
   vendor/bm/APPS/MobileQQ2011.apk:system/app/MobileQQ2011.apk/
   vendor/bm/APPS/Renren_Android_3.0.2.apk:system/app/Renren_Android_3.0.2.apk
这种相对不会很繁琐,不需要一级级的建立目录,在内置很多apk是比较方便。

在Android.mk文件中打印log

$(info   xxxxx)  //一般打印信息 

$(warning xxxxx)  //警告性级别信息输出

$(error xxxxx)     //输出错误信息,并终止编译

输出变量方式为:$(warning  $(var))   or    $(warning  $var) 

$(warning  $(LOCAL_PATH))  or  $(warning  "string$(LOCAL_PATH)")   or  $(warning this is $LOCAL_PACKAGE_NAME)

image.png


【2.1】

如果要引用自己创建的某mk文件,需要在build/target/product/core.mk目录下(不一定是此目录,视各自公司规定而定)中加入://文件存放位置的绝对路径

$(call inherit-product, $(SRC_TARGET_DIR)/product/mytest.mk)     

/build/target/product目录下,创建一个makefile文件取为mytest.mk
(2)在里面输入(TEST为我们要预置的APK文件名):

PRODUCT_PACKAGES := TEST   

【2.2】如是在我们的自己写的某mk文件中引用其mk文件我们可以如下写:

-include $(TOPDIR)vendor/odm/prebuilts/customname.mk




好的网文:

Android build系统中常用LOCAL_变量

Android预置Apk方法

Android 系统预设 App带jar包,os库处理


评论