Android编译之MAKE

Android编译之MAKE

目录

(一)make文件分类 

(二)makefile文件

(三)Make命令

(四) build/core/config.mk 

(五) buildspec.mk

(六) Android.mk说明

(七) MAKE调试技巧



(一)make文件分类 

1.  配置类

    主要用来配置product、board,以及根据你的Host和Target选择相应的工具以及设定相应的通用编译选项:

config文件

说明

build/core/config.mk  Config文件的概括性配置

build/core/envsetup.mk  generate目录构成等配置build/target/product 产品相关的配置

build/target/board  硬件相关的配置

build/core/combo  编译选项配置

这里解释下这里的board和product。board主要是设计到硬件芯片的配置, 比如是否提供硬件的某些功能,比如说GPU等等,或者芯片支持浮点运算等等。product是指针对当前的芯片配置定义你将要生产产品的个性配置,主要是 指APK方面的配置,哪些APK会包含在哪个product中,哪些APK在当前product中是不提供的。

config.mk是一个总括性的东西,它里面定义了各种module编译所需要使用的 HOST工具以及如何来编译各种模块,比如说 BUILT_PREBUILT就定义了如何来编译预编译模块。

envsetup.mk主要会读取由envsetup.sh写入环境变量中的一些变量来配置 编译过程中的输出目录,

combo里面主要定义了各种Host和Target结合的编译器和编译选项。

2. 模块组织类

    这类文件主要定义了如何来处理Module的Android.mk,以及采用何种方式来生成目标模块,这些模块生成规则都定义在config.mk里面。我们可以看看:

CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk

BUILD_HOST_STATIC_LIBRARY:=$(BUILD_SYSTEM)/host_static_library.mk

BUILD_HOST_SHARED_LIBRARY:=$(BUILD_SYSTEM)/host_shared_library.mk

BUILD_STATIC_LIBRARY:=$(BUILD_SYSTEM)/static_library.mk

BUILD_RAW_STATIC_LIBRARY :=$(BUILD_SYSTEM)/raw_static_library.mk

BUILD_SHARED_LIBRARY:=$(BUILD_SYSTEM)/shared_library.mk

BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk

BUILD_RAW_EXECUTABLE:=$(BUILD_SYSTEM)/raw_executable.mk

BUILD_HOST_EXECUTABLE:=$(BUILD_SYSTEM)/host_executable.mk

BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk

BUILD_HOST_PREBUILT:=$(BUILD_SYSTEM)/host_prebuilt.mk

BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk

BUILD_MULTI_PREBUILT:=$(BUILD_SYSTEM)/multi_prebuilt.mk

BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk

BUILD_STATIC_JAVA_LIBRARY:=$(BUILD_SYSTEM)/static_java_library.mk

BUILD_HOST_JAVA_LIBRARY:=$(BUILD_SYSTEM)/host_java_library.mk

BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk

BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk

BUILD_KEY_CHAR_MAP :=$(BUILD_SYSTEM)/key_char_map.mk 

     除了CLEAR_VARS是清楚本地变量之外,其他所有的都对应了一种模块的生成规则, 每一个本地模块最后都会include其中的一种来生成目标模块。大部分上面的.mk都会包含base_rules.mk,这是对模块进行处理的基础文 件,建议要写本地模块的都去看看,看明白了为什么 Android.mk要这么写就会大致明白了。

3.单个模块编译类

   本地模块的Makefile文件就是我们在Android里面几乎上随处可见的 Android.mk。Android进行编译的时候会通过下面的函数来遍历所有子目录中的Android.mk,一旦找到就不会再往层子目录继续寻找 (所有你的模块定义的顶层Android.mk必须包含自己定义的子目录中的 Android.mk)。 subdir_makefiles += /  $(shellbuild/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk) 不同类型的本地模块具有不同的语法,但基本上是相通的,只有个别变量的不同,如何添加模块在前面的帖子已经说过了,大家可以参考。 Android通过LOCAL_MODULE_TAGS来决定哪些本地模块会不会编译进 系统,通过PRODUCT和LOCAL_MODULE_TAGS来决定哪些应用包会编译进系统,如果用户不指定LOCAL_MODULE_TAGS,默认 它的值是user。此外用户可以通过buildspec.mk来指定你需要编译进系统的模块。用户也可以通过mm来编译指定模块,或者通过make clean-module_name来删除指定模块。 

4.系统生成类

   这主要指的是build/core/Makefile这个文件,它定义了生成各种img 的方式,包括ramdisk.img   userdata.img system.img  update.zip  recover.img等。我们可以看看这些img都是如何生成的,对应着我们常用的几个make goals。在实际的过程中,我们也可以自己编辑out目录下的生成文件,然后手工打包相应生成相应的img,最常用的是加入一些需要集成进的prebuilt file。所有的Makefile都通过build/core/main.mk这个文件组织在一起,它定义了一个默认goals:droid,当我们在 TOP目录下敲Make实际上就等同于我们执行make droid。当Make include所有的文件,完成对所有make文件的解析以后就会寻找生成droid的规则,依次生成它的依赖,直到所有满足的模块被编译好,然后使用相 应的工具打包成相应的img。

(二)makefile文件 

控制整个android系统编译的make文件。其内容如下:

### DO NOT EDIT THIS FILE ###

 include build/core/main.mk

### DO NOT EDIT THIS FILE ###

可以看出,实际上控制编译的文件是:build/core/main.mk 

(三)Make命令

make droid:等同于make命令。droid是默认的目标名称。

make all:  make all将make所有make droid会编译的项目。同时,将编译LOCAL_MODULE_TAGS定义的不包括android tag的模块。这将确保所有的在代码树里面同时有Android.mk文件的模块。

clean-$(LOCAL_MODULE)和clean-$(LOCAL_PACKAGE_NAME):删除某个模块的目标文件。例如:clean-libutils将删除所有的libutils.so以及和它相关的中间文件;clean-Home将删除Home应用。

make clean:删除本次配置所编译输出的结果文件。类似于:rm –rf ./out/<configuration>

make clobber:删除所有配置所编译输出的结果文件。类似于:rm –rf ./out/

make dataclean:类似于:rm -rf $(PRODUCT_OUT)/data/*, data-qemu/*, userdata-qemu.img

make dataclean deletes contents of the data directory inside the current combo directory. This is especially useful on the simulator and emulator, where the persistent data remains present between builds.

make showcommands:在编译的时候显示脚本的命令,而不是显示编译的简报。用于调试脚本。

make LOCAL_MODULE:编译一个单独得模块(需要有Android.mk文件存在)。

make targets:将输出所有拟可以编译的模块名称列表。

CONT.

+1

printconfig –Prints current configuration set by choosecombo commands

croot –cd to top of tree

–Runs make from top of tree Useful for running make from within subdirectories; if TOP environment variable is set, command uses that variable; if variable is not set, command looks up tree from current directory and attempts to find top of tree

mm –Builds all modules incurrent directory

mmm –Builds all modules insupplied directories

sgrep –grep for regex you provide in all .c, .cpp, .h, .java, and .xml filesbelow the current directory

cgrep

jgrep

mgrep

Local modules –Use the following command to make a specific module:

m MODULE_NAME

+1

Howto:get kernel log by real time:  

    cat /proc/kmsg &   或者   dmesg -c  

Howto:make boot.img quickly  

   make bootimage    或者    make kernel  

Howto:config kernel option 
   in android root dir :     make kernelconfig  

    but NOT in kernel dir :   make menuconfig 

+1

Howto:make lk(appsboot.mbn)

     make aboot

(会调用下面的位置

./build/core/main.mk   

.PHONY: bootimage
bootimage: $(INSTALLED_BOOTIMAGE_TARGET)
.PHONY: aboot
aboot: $(INSTALLED_BOOTLOADER_TARGET)

)
 (L)ittle (K)ernel bootloader的mk文件是

/bootable/bootloader/lk/AndroidBoot.mk 

linux kernel的mk文件是

/kernel/AndroidKernel.mk

两者在/device/qcom/msm7627_sku2/AndroidBoard.mk中被包含进来。

注:还有一些命令,从make文件里面应该可以找到。本文不做探讨

(四) build/core/config.mk

config.mk文件的主要内容如下:

 Ø  头文件的定义;(各种include文件夹的设定)在定义头文件的部分,还include了pathmap.mk,如下:

 include $(BUILD_SYSTEM)/pathmap.mk 该文件设置include目录和frameworks/base下子目录等的信息。

 Ø  编译系统内部mk文件的定义;

 Ø  设定通用的名称;

 Ø  Include必要的子配置文件;  buildspec.mk  envsetup.mk   BoardConfig.mk   /combo/select.mk   /combo/javac.mk

 Ø  检查BUILD_ENV_SEQUENCE_NUMBER版本号;

    In order to make easier for people when the build system changes, when it is necessary to make changes to buildspec.mk or to rerun the environment setup scripts, they contain a version number in the variable BUILD_ENV_SEQUENCE_NUMBER. If this variable does not match what the build system expects, it fails printing an error message explaining what happened. If you make a change that requires an update, you need to update two places so this message will be printed.

   In config/envsetup.make, increment the CORRECT_BUILD_ENV_SEQUENCE_NUMBER definition.

   In buildspec.mk.default, update the BUILD_ENV_SEQUENCE_DUMBER definition to match the one in config/envsetup.make

   The scripts automatically get the value from the build system, so they will trigger the warning as well.

 Ø  设置常用工具的常量;< Generic tools.>

 Ø  设置目标选项;< Set up final options.>

 Ø  遍历并设置SDK版本;

(五) buildspec.mk

      默认情况下,buildspec.mk文件是不存在的,表示使用的多少默认选项。 Android只提供了buildspec.mk文件的模板文件build/buildspec.mk.default。如果需要使用 buildspec.mk文件,请将该文件拷贝到根目录下面,并命名为buildspec.mk。同时,需要将模板文件里面 的一些必要的配置项启用或者修改为你所需要的目标选项。 buildspec.mk文件主要配置下面的选项: Ø  TARGET_PRODUCT:设置编译之后的目标(产品)类型;可以设置的值在:build/target/product/中定义。比如,product目录下有下面几个mk文件:  

      AndroidProducts.mk

      core.mk

      full.mk

      generic.mk

      languages_full.mk   

      languages_small.mk  

      sdk.mk   

      sim.mk

 那么,在这里可以设置的值就为上面几个mk文件的前缀名称(generic等)。

Ø  TARGET_BUILD_VARIANT:设置image的类型;

     包括三个选项:user、userdebug、eng。

      usr:出厂时候面向用户的image;

      userdebug:打开了一些debug选项的image;

      eng:为了开发而包含了很多工具的image .

Ø  CUSTOM_MODULES:设置额外的总是会被安装到系统的模块;这里设置的模块名称采用的是简单目标名,比如:Browser或者MyApp等。这些名字在LOCAL_MODULE或者在LOCAL_PACKAGE_NAME里面定义的。

    LOCAL_MODULE is the name of what's supposed to be generated from your Android.mk. For exmample, for libkjs, the LOCAL_MODULE is "libkjs" (the build system adds the appropriate suffix -- .so .dylib .dll). For app modules, use LOCAL_PACKAGE_NAME instead of LOCAL_MODULE. We're planning on switching to ant for the apps, so this might become moot.

 Ø  TARGET_SIMULATOR:设置是否要编译成simulator ;

 Ø  TARGET_BUILD_TYPE:设置是debug还是release版本 ; Set this to debug or release if you care.  Otherwise, it   defaults to release for arm and debug for the simulator.

 Ø  HOST_BUILD_TYPE:设置Host目标是debug版还是release版;

 Ø  DEBUG_MODULE_ModuleName:配置单个模块的版本是debug还是release;

 Ø  TARGET_TOOLS_PREFIX:工具名前缀,默认为NULL

 Ø  HOST_CUSTOM_DEBUG_CFLAGS/ TARGET_CUSTOM_DEBUG_CFLAGS:增加额外的编译选项LOCAL_CFLAGS。 LOCAL_CFLAGS:If you have additional flags to pass into the C or C++ compiler, add them here. For example: LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1

 Ø  CUSTOM_LOCALES:增加额外的LOCALES到最总的image; Any locales that appear in CUSTOM_LOCALES but not in the locale list for the selected product will be added to the end of PRODUCT_LOCALES.

 Ø  OUT_DIR:编译之后文件保存路径。默认为/out目录;

 Ø  ADDITIONAL_BUILD_PROPERTIES:指定(增加)额外的属性文件;

 Ø  NO_FALLBACK_FONT:设置是否只支持英文(这将减少image的大小)。

 Ø  WEBCORE_INSTRUMENTATION:webcore支持;

 Ø  ENABLE_SVG:SVG支持;

 Ø  BUILD_ENV_SEQUENCE_NUMBER:编译系列号;

(六) Android.mk说明

Android编译系统的makefile文件Android.mk写法如下
(1)Android.mk文件首先需要指定LOCAL_PATH变量,用于查找源文件。由于一般情况下
Android.mk和需要编译的源文件在同一目录下,所以定义成如下形式:
LOCAL_PATH:=$(call my-dir)
上面的语句的意思是将LOCAL_PATH变量定义成本文件所在目录路径。
(2)Android.mk中可以定义多个编译模块每个编译模块都是以include $(CLEAR_VARS)开始
以include $(BUILD_XXX)结束。
include $(CLEAR_VARS)
CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除除LOCAL_PATH以外的所有LOCAL_XXX变量, 如LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_SHARED_LIBRARIES,LOCAL_STATIC_LIBRARIES等。
include $(BUILD_STATIC_LIBRARY)表示编译成静态库
include $(BUILD_SHARED_LIBRARY)表示编译成动态库。

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


include $(BUILD_JAVA_LIBRARY)表示编译成xxx.jar(如手机中/system/framework下存的全是jar,典型的framework.jar,core.jar,ext,.jar) include $(BUILD_STATIC_JAVA_LIBRARY) ??????


        模块的各种类型在(一)make文件分类 1.  配置类2. 模块组织类中有介绍,也可以参见out/target/product/msm7627_sku2/obj目录,这里是中间文件的生成位置,下面的每个目录名代表着一类模块(或者说android系统中的文件类型,如apk,so,a ,可执行程序等)。
STATIC_LIBRARIES:最终放到手机系统中的.a文件(其实就是.o文件的集合,第三方可能将不想公开的代码编译成这个提供给方案公司)

SHARED_LIBRARIES:最终放到手机系统中的.so文件(如sensor的hal层代码就是这种文件,我的是/system/lib/hw/sensors.msm7k.so)

EXECUTABLES:最终放到手机系统中的可执行文件,一般没有扩展名(如一些daemon文件,一般放到/system/bin下,如我的oem_rapi_wifimac,)

更多参考  Android编译系统makefile(Android.mk)写法

(3)举例

如下的Android.mk内容
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE  := sensors.ami  #最终模块名前缀
LOCAL_MODULE_PATH  := $(TARGET_OUT_SHARED_LIBRARIES)/hw #指定最终生成的文件位置放在/system/lib/hw下
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := -DLOG_TAG=\"Sensors\" #宏定义,可以在c/cpp代码中使用#ifdef  Sensors
LOCAL_SRC_FILES :=                         \
                sensors_amit.c                 \
                nusensors.cpp             \
                InputEventReader.cpp    \
                SensorBase.cpp            \
                AmiSensor.cpp                
LOCAL_SHARED_LIBRARIES := liblog libcutils
LOCAL_PRELINK_MODULE := false

include $(BUILD_SHARED_LIBRARY) #编译成共享库,.so

源码最终被编译成sensors.ami.so这个共享库模块。

      另外源码的位置原则上来讲是可以放到任何目录下的,因为可以在android.mk中指定需要的库以及最终生成文件的位置,只是为了代码树逻辑上更合理,有些源文件有固定的位置。

(七) MAKE调试技巧

有下面两个调试技巧:

1.$(error yuebao===============>test)

Android.mk或Makefile运行到这个语句make会停止,并在中断报错

2.$(waring $(BUILD_PACKAGE))  
可以打印信息在终端

更多参考可见:

http://groups.google.com/group/android-building/msg/56676963a5616b57

android make 介绍 Make 文件说明 整个 Build 系统的入口文件是源码树根目录下名称为“Makefile”的文件,当在源代码根目录上调用 make 命令 时,make 命令首先将读取该文件。 Makefile 文件的内容只有一行:“include build/core/main.mk”。该行代码的作用很明显:包含 build/core/main.mk 文 件。在 main.mk 文件中又会包含其他的文件,其他文件中又会包含更多的文件,这样就引入了整个 Build 系统。 这些 Make 文件间的包含关系是相当复杂的,图 3 描述了这种关系,该图中黄色标记的文件(且除了 $开头的文件) 都位于 build/core/ 目录下。 Android 源码中包含了许多的模块,模块的类型有很多种,例如:Java 库,C/C++ 库,APK 应用,以及可执行文件 等 。并且,Java 或者 C/C++ 库还可以分为静态的或者动态的,库或可执行文件既可能是针对设备(本文的“设备”指 的是 Android 系统将被安装的设备,例如某个型号的手机或平板)的也可能是针对主机(本文的“主机”指的是开发 Android 系统的机器,例如装有 Ubuntu 操作系统的 PC 机或装有 MacOS 的 iMac 或 Macbook)的。不同类型的模块 的编译步骤和方法是不一样,为了能够一致且方便的执行各种类型模块的编译,在 config.mk 中定义了许多的常量, 这其中的每个常量描述了一种类型模块的编译方式,这些常量有: BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk BUILD_RAW_STATIC_LIBRARY := $(BUILD_SYSTEM)/raw_static_library.mk BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk BUILD_RAW_EXECUTABLE:= $(BUILD_SYSTEM)/raw_executable.mk BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk BUILD_PHONY_PACKAGE:= $(BUILD_SYSTEM)/phony_package.mk BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk BUILD_HOST_
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值