欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-12-27 23:27:22
一 : 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