Android源码分析(一)-----如何快速掌握Android编译文件

摘要:
这个文件的语法会把源代码组织成模块,每个模块属于下列类型之一:-APK程序:一般的Android程序,编译打包生成apk文件。

一 : Android.mk文件概述

主要向编译系统指定相应的编译规则。会被解析一次或多次。因此尽量减少源码中声明变量,因为这些变量可能会被多次定义从而影响到后面的解析。这个文件的语法会把源代码组织成模块,每个模块属于下列类型之一:

- APK程序:一般的Android程序,编译打包生成apk文件。
- JAVA库:java类库,编译打包生成jar包文件。
- CC++应用程序:可执行的C/C++应用程序。
- CC++静态库:编译生产C/C++静态库,并打包成.a文件。
- CC++共享库:编译生成共享库,并打包成.so文件,有且只有共享库才能被安装/复制到APK包中。

二 : 系统变量####

- LOCAL_PATH:这个变量用于给出当前文件的路径,必须在Android.mk的开头定义,可以这样使用LOCAL_PATH := $(call my-dir),这样这个变量不会被$(CLEAR_VARS)清除,因为每个Android.mk只需要定义一次(即使一个文件中定义了多个模块的情况下)。
- LOCAL_SRC_FILES:当前模块包含的所有源代码文件。
- LOCAL_MODULE:当前模块的名称,这个名称应当是唯一的,并且不能包含空格。模块间的依赖关系就是通过这个名称来引用的。
- LOCAL_MODULE_CLASS:标识所编译模块最后放置的位置。ETC表示放置在/system/etc.目录下,APPS表示放置在/system/app目录下,SHARED_LIBRARIES表示放置在/system/lib目录下。如果具体指定,则编译的模块不会放到编译系统中,最后会在out对应product的obj目录下的对应目录中。
- LOCAL_SRC_FILES:这是要编译的源代码文件列表。只要列出要传递给编译器的文件即可,编译系统会自动计算依赖关系。源代码文件路径都是相相对于LOCAL_PATH的,因此可以使用相对路径进行描述。
- LOCAL_JAVA_LIBRARIES:当前模块依赖的Java共享库,也叫Java动态库。例如framework.jar包。
- LOCAL_STATIC_JAVA_LIBRARIES:当前模块依赖的Java静态库,在Android里,导入的jar包和引用的第三方工程都属于Java静态库。
- LOCAL_STATIC_LIBRARIES:当前模块在运行时依赖的静态库的名称。
- LOCAL_SHARED_LIBRARIES:当前模块在运行时依赖的动态库的名称。
- LOCAL_C_INCLUDES:c或c++语言需要的头文件的路径。
- LOCAL_CFLAGS:提供给C/C++编译器的额外编译参数。
- LOCAL_PACKAGE_NAME:当前APK应用的名称。
- LOCAL_CERTIFICATE:签署当前应用的证书名称。
- LOCAL_MODULE_TAGS:当前模块所包含的标签,一个模块可以包含多个标签。标签的值可能是eng、user、debug、development、optional。其中,optional是默认标签。
- LOCAL_DEX_PREOPT:apk的odex优化开关,默认是false。

三 : mk文件模板####

  • 编译C/C++应用程序的模板:
     #Test Exe
     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)

BUILD_EXECUTABLE表示以一个可执行程序的方式进行编译。补充说明:include $(BUILD_PACKAGE)则是编译出一个apk,include $(BUILD_STATIC_JAVA_LIBRARY)则是编译出jar包。

  • 编译静态库的模板:
    `#Test Static Lib
     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表示编译一个静态库.a文件。静态库不会复制到的APK包中,但是能够用于编译共享库。

  • 编译动态库的模板:
     #Test Shared Lib
     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会变:
out/target/product/generic/obj/EXECUTABLE
out/target/product/generic/obj/STATIC_LIBRARY
out/target/product/generic/obj/SHARED_LIBRARY

每个模块的目标文件夹分别为:
可执行程序:XXX_intermediates
静态库: XXX_static_intermediates
动态库: XXX_shared_intermediates

另外,在Android.mk文件中,还可以指定最后的目标安装路径,用LOCAL_MODULE_PATH和LOCAL_UNSTRIPPED_PATH来指定。不同的文件系统路径用以下的宏进行选择:

- TARGET_ROOT_OUT:表示根文件系统out/target/product/xxxxx/root。
- TARGET_OUT:表示system文件系统out/target/product/xxxx/system。
- TARGET_OUT_DATA:表示data文件系统out/target/product/xxxx/data。
- TARGET_OUT_SHARED_LIBRARIES:表示out/target/product/xxxx/system/lib
- TARGET_OUT_APPS:表示out/target/product/xxxx/system/app
- ANDROID_PRODUCT_OUT:out/target/product/xxxx/
- TARGET_OUT_JAVA_LIBRARIES:out/target/product/xxxx/system/framework

四 : 常用函数####

- $(call my-dir):获取当前文件夹的路径。
- $(call all-java-files-under, <src>):获取指定目录下的所有java文件。
- $(call all-c-files-under, <src>):获取指定目录下的所有c文件。
- $(call all-Iaidl-files-under, <src>):获取指定目录下的所有AIDL文件。
- $(call all-makefiles-under, <folder>):获取指定目录下的所有Make文件。
- $(call intermediates-dir-for, <class>, <app_name>, <host or target>, <common?>):获取Build输入的目标文件夹路径。

五 : Settings模块Android.mk文件分析####

# 当前文件的路径
LOCAL_PATH:= $(call my-dir)
# 清除变量
include $(CLEAR_VARS)

# 列举所有需要编译的源文件
LOCAL_SRC_FILES := 
        $(call all-logtags-files-under, src)

# 模块名称--唯一
LOCAL_MODULE := settings-logtags

#依赖的java静态库
include $(BUILD_STATIC_JAVA_LIBRARY)

# Build the Settings APK
include $(CLEAR_VARS)

#依赖的java库
LOCAL_JAVA_LIBRARIES := bouncycastle core-oj telephony-common ims-common
#依赖的jar包,包括系统的和第三方的(放在libs目录)jar包
LOCAL_STATIC_JAVA_LIBRARIES := 
    android-support-v4 
    android-support-v13 
    android-support-v7-recyclerview 
    android-support-v7-preference 
    android-support-v7-appcompat 
    android-support-v14-preference 
    jsr305 
    settings-logtags
    
#user: 指该模块只在user版本下才编译
#eng: 指该模块只在eng版本下才编译
#tests: 指该模块只在tests版本下才编译
#optional:指该模块在所有版本下都编译
LOCAL_MODULE_TAGS := optional

#列举所有需要编译的源文件
LOCAL_SRC_FILES := 
        $(call all-java-files-under, src)

#列举所有需要的资源文件夹
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res 
    frameworks/support/v7/preference/res 
    frameworks/support/v14/preference/res 
    frameworks/support/v7/appcompat/res 
    frameworks/support/v7/recyclerview/res

#打包成apk的名称--包名
LOCAL_PACKAGE_NAME := Settings

#用于指定签名时使用的KEY
LOCAL_CERTIFICATE := platform

#编译后在ROM中的安装位置
#true,安装位置为system/priv-app
#false,安装位置为system/app
LOCAL_PRIVILEGED_MODULE := true

#混淆文件名
LOCAL_PROGUARD_FLAG_FILES := proguard.flags

LOCAL_AAPT_FLAGS := --auto-add-overlay 
    --extra-packages android.support.v7.preference:android.support.v14.preference:android.support.v17.preference:android.support.v7.appcompat:android.support.v7.recyclerview

ifneq ($(INCREMENTAL_BUILDS),)
    LOCAL_PROGUARD_ENABLED := disabled
    LOCAL_JACK_ENABLED := incremental
    LOCAL_DX_FLAGS := --multi-dex
    LOCAL_JACK_FLAGS := --multi-dex native
endif

#包含的其他mk文件
include frameworks/opt/setupwizard/library/common-full-support.mk
include frameworks/base/packages/SettingsLib/common.mk

#打包成apk
include $(BUILD_PACKAGE)

# Use the following include to make our test apk.
ifeq (,$(ONE_SHOT_MAKEFILE))
#获取当前目录下的所有Make文件
include $(call all-makefiles-under,$(LOCAL_PATH))
endif

免责声明:文章转载自《Android源码分析(一)-----如何快速掌握Android编译文件》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇docker学习笔记——docker网络配置word添加页码下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

定位多线程内存越界问题实践总结

最近定位了在一个多线程服务器程序(OceanBase MergeServer)中,一个线程非法篡改另一个线程的内存而导致程序core掉的问题。定位这个问 题花了整整一周的时间,期间历经曲折,尝试了各种内存调试的办法。往往感觉就要柳暗花明了,却发现又进入了另一个死胡同。最后,使用 强大的mprotect+backtrace+libsigsegv等工具成...

WINDOWS 的 MKLINK : 硬链接,符号链接 : 文件符号链接, 目录符号链接 : 目录联接

玩转WIN7的MKLINK引言: 换了新电脑,终于再次使用上啦WIN7 ,经过一个周每天重装N次系统,... ... ... ... 在xp系统下,junction命令要用微软开发的小程序 junction.exe实现,从http://live.sysinternals.com/可以下载。 现在Windows Vista之后的系统自带了mklink的功能。...

C#操作目录和文件

C#操作目录和文件 创建目录和文件 1、通过Path类的Combine方法可以合并路径。 string activeDir = @"C:myDir"; string newPath = System.IO.Path.Combine(activeDir, "mySubDirOne"); 2、目录的创建。 创建...

rootkit:实现隐藏进程

实现隐藏进程一般有两个方法: 1,把要隐藏的进程PID设置为0,因为系统默认是不显示PID为0的进程。 2,修改系统调用sys_getdents()。 Linux系统中用来查询文件信息的系统调用是sys_getdents,这一点可以通过strace来观察到,例如strace ls 将列出命令ls用到的系统调用,从中可以发现ls是通过getdents系统调用...

QT5 编译程序运行,报错丢失libgcc_s_sjlj1.dll。尝试重新安装该程序以解决此问题。

之前一直正常使用,最近在QT Creator中运行程序,直接程序异常结束,单独启动EXE程序时,报以上错误。 最后把问题锁定在libstdc++-6.dll库上,尝试把QT环境bin目录下的libstdc++-6.dll拿到程序运行目录下,临时解决此问题。 原因是最近安装过一个程序,这个程序在C:\Windows\System32下放了一个libstd...

python 目录与文件的时间操作

在Python中,文件操作主要来自os模块,主要方法如下: os.listdir(dirname):列出dirname下的目录和文件os.getcwd():获得当前工作目录os.curdir:返回当前目录('.')os.chdir(dirname):改变工作目录到dirname os.path.isdir(name):判断name是不是一个目录,name不...