Android源码分析(一)-----如何快速掌握Android编译文件
程序员文章站
2022-05-14 12:04:48
一 : Android.mk文件概述 主要向编译系统指定相应的编译规则。会被解析一次或多次。因此尽量减少源码中声明变量,因为这些变量可能会被多次定义从而影响到后面的解析。这个文件的语法会把源代码组织成模块,每个模块属于下列类型之一: 二 : 系统变量 三 : mk文件模板 编译C/C++应用程序的模 ......
一 : android.mk文件概述
主要向编译系统指定相应的编译规则。会被解析一次或多次。因此尽量减少源码中声明变量,因为这些变量可能会被多次定义从而影响到后面的解析。这个文件的语法会把源代码组织成模块,每个模块属于下列类型之一:
- apk程序:一般的android程序,编译打包生成apk文件。 - java库:java类库,编译打包生成jar包文件。 - c\c++应用程序:可执行的c/c++应用程序。 - c\c++静态库:编译生产c/c++静态库,并打包成.a文件。 - c\c++共享库:编译生成共享库,并打包成.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