Android Build System

개발 조회 수 7067 추천 수 0 2017.06.09 09:51:06

Android Build System

Link :

The Android Build system are described at:

You use build/ to set up a "convenience environment" for working on the Android source code. This file should be source'ed into your current shell environment. After doing so you can type 'help' (or 'hmm') for a list of defined functions which are helpful for interacting with the source.


The build system uses some pre-set environment variables and a series of 'make' files in order to build an Android system and prepare it for deployment to a platform.

Android make files end in the extension '.mk' by convention, with the main make file in any particular source directory being named ''.

There is only one official file named 'Makefile', at the top of the source tree for the whole repository. You set some environment variables, then type 'make' to build stuff. You can add some options to the make command line (other targets) to turn on verbose output, or perform different actions.

The build output is placed in 'out/host' and 'out/target' Stuff under 'out/host' are things compiled for your host platform (your desktop machine). Stuff under 'out/target/product/<platform-name>' eventually makes it's way to a target device (or emulator).

The directory 'out/target/product/<platform-name>/obj' is used for staging "object" files, which are intermediate binary images used for building the final programs. Stuff that actually lands in the file system of the target is stored in the directories root, system, and data, under 'out/target/product/<platform-name>'. Usually, these are bundled up into image files called system.img, ramdisk.img, and userdata.img.

This matches the separate file system partitions used on most Android devices.

Some Details

What tools are used

During the build you will be using 'make' to control the build steps themselves. A host toolchain (compiler, linker and other tools) and libraries will be used to build programs and tools that will run on the host. A different toolchain is used to compile the C and C++ code that will wind up on the target (which is an embedded board, device or the emulator). This is usually a "cross" toolchain that runs on an X86 platform, but produces code for some other platform (most commonly ARM). The kernel is compiled as a standalone binary (it does not use a program loader or link to any outside libraries). Other items, like native programs (e.g. init or toolbox), daemons or libraries will link against bionic or other system libraries.

You will be using a Java compiler and a bunch of java-related tools to build most of the application framework, system services and Android applications themselves. Finally, tools are used to package the applications and resource files, and to create the filesystem images that can be installed on a device or used with the simulator.

Telling the system where the Java toolchain is

Before you build anything, you have to tell the Android build system where your Java SDK is. (Installing a Java SDK is a pre-requisite for building).

Do this by setting a JAVA_HOME environment variable.

Specifying what to build

In order to decide what to build, and how to build it, the build system requires that some variables be set. Different products, with different packages and options can be built from the same source tree. The variables to control this can be set via a file with declarations of 'make' variables, or can be specified in the environment.

A device vendor can create definition files that describe what is to be included on a particular board or for a particular product. The definition file is called:, and it is located in the top-level source directory. You can edit this manually to hardcode your selections.

If you have a file, it sets all the make variables needed for a build, and you don't have to mess with options.

Another method of specifying options is to set environment variables. The build system has a rather ornate method of managing these options for you.

To set up your build environment, you need to load the variables and functions in build/ Do this by 'source-ing' the file into your shell environment, like this:

$ . build/

You can type 'help' (or 'hmm') at this point to see some utility functions that are available to make it easier to work with the source.

To select the set of things you want to build, and what items to build for, you use either the 'choosecombo' function or the 'lunch' function. 'choosecombo' will walk you through the different items you have to select, one-by-one, while 'lunch' allows you select some pre-set combinations.

The items that have to be defined for a build are:

  • the product ('generic' or some specific board or platform name)
  • the build variant ('user', 'userdebug', or 'eng')
  • whether you're running on a simulator ('true' or 'false')
  • the build type ('release' or 'debug')

Descriptions of these different build variants are at

The build process from a user perspective is described pretty well in this blog post: First Android platform build by CodePainters, December 2009

Actually building the system

Once you have things set up, you actually build the system with the 'make' command.

To build the whole thing, run 'make' in the top directory. The build will take a long time, if you are building everything (for example, the first time you do it).

Build tricks

Seeing the actual commands used to build the software

Use the "showcommands" target on your 'make' line:

$ make -j4 showcommands

This can be used in conjunction with another make target, to see the commands for that build. That is, 'showcommands' is not a target itself, but just a modifier for the specified build.

In the example above, the -j4 is unrelated to the showcommands option, and is used to execute 4 make sessions that run in parallel.

Make targets

Here is a list of different make targets you can use to build different parts of the system:

  • make sdk - build the tools that are part of an SDK (adb, fastboot, etc.)
  • make snod - build the system image from the current software binaries
  • make services
  • make runtime
  • make droid - make droid is the normal build.
  • make all - make everything, whether it is included in the product definition or not
  • make clean - remove all built files (prepare for a new build). Same as rm -rf out/<configuration>/
  • make modules - shows a list of submodules that can be built (List of all LOCAL_MODULE definitions)
  • make <local_module> - make a specific module (note that this is not the same as directory name. It is the LOCAL_MODULE definition in the file)
  • make clean-<local_module> - clean a specific module
  • make bootimage TARGET_PREBUILT_KERNEL=/path/to/bzImage - create a new boot image with custom bzImage

Helper macros and functions

There are some helper macros and functions that are installed when you source They are documented at the top of, but here is information about a few of them:

  • croot - change directory to the top of the tree
  • m - execute 'make' from the top of the tree (even if your current directory is somewhere else)
  • mm - builds all of the modules in the current directory
  • mmm <dir1> ... - build all of the modules in the supplied directories
  • cgrep <pattern> - grep on all local C/C++ files
  • jgrep <pattern> - grep on all local Java files
  • resgrep <pattern> - grep on all local res/*.xml files
  • godir <filename> - go to the directory containing a file

Speeding up the build

You can use the '-j' option with make, to start multiple threads of make execution concurrently.

In my experience, you should specify about 2 more threads than you have processors on your machine. If you have 2 processors, use 'make -j4', If they are hyperthreaded (meaning you have 4 virtual processors), try 'make -j6.

You can also specify to use the 'ccache' compiler cache, which will speed up things once you have built things a first time. To do this, specify 'export USE_CCACHE=1' at your shell command line. (Note that ccache is included in the prebuilt section of the repository, and does not have to be installed on your host separately.)

Building only an individual program or module

If you use build/, you can use some of the defined functions to build only a part of the tree. Use the 'mm' or 'mmm' commands to do this.

The 'mm' command makes stuff in the current directory (and sub-directories, I believe). With the 'mmm' command, you specify a directory or list of directories, and it builds those.

To install your changes, do 'make snod' from the top of tree. 'make snod' builds a new system image from current binaries.

Setting module-specific build parameters

Some code in Android system can be customized in the way they are built (separate from the build variant and release vs. debug options). You can set variables that control individual build options, either by setting them in the environment or by passing them directly to 'make' (or the 'm...' functions which call 'make'.)

For example, the 'init' program can be built with support for bootchart logging by setting the INIT_BOOTCHART variable. (See Using Bootchart on Android for why you might want to do this.)

You can accomplish either with:

$ touch system/init/init.c
$ export INIT_BOOTCHART=true
$ make


$ touch system/init/init.c

Makefile tricks

These are some tips for things you can use in your own files.

build helper functions

A whole bunch of build helper functions are defined in the file build/core/

Try grep define build/core/ for an exhaustive list.

Here are some possibly interesting functions:

  • print-vars - shall all Makefile variables, for debugging
  • emit-line - output a line during building, to a file
  • dump-words-to-file - output a list of words to a file
  • copy-one-file - copy a file from one place to another (dest on target?)

Add a file directly to the output area

You can copy a file directly to the output area, without building anything, using the add-prebuilt-files function.

The following line, extracted from prebuilt/android-arm/gdbserver/ copies a list of files to the EXECUTABLES directory in the output area:

$(call add-prebuilt-files, EXECUTABLES, $(prebuilt_files))

Adding a new program to build

Steps for adding a new program to the Android source tree

  • make a directory under 'external'
    • e.g. ANDROID/external/myprogram
  • create your C/cpp files.
  • create as clone of external/ping/
  • Change the names ping.c and ping to match your C/cpp files and program name
  • add the directory name in ANDROID/build/core/ after external/zlib as external/myprogram
  • make from the root of the source tree
  • your files will show up in the build output area, and in system images.
    • You can copy your file from the build output area, under out/target/product/..., if you want to copy it individually to the target (not do a whole install)

See for a lot more detail.

Building the kernel

The kernel is "outside" of the normal Android build system (indeed, the kernel is not included by default in the Android Open Source Project). However, there are tools in AOSP for building a kernel. If you are building the kernel, start on this page:

If you are building the kernel for the emulator, you may also want to look at:

And, Ron M wrote (on the android-kernel mailing list, on May 21, 2012):

This post is very old - but nothing has changes as far as AOSP is concerned, so in case anyone is interested and runs into this problem when building for QEMU:

There is actually a nice and shorter way to build the kernel for your QEMU target provided by the AOSP:

1. cd to your kernel source dir (Only goldfish 2.6.29 works out of the box for the emulator)

2. ${ANDROID_BUILD_TOP}/external/qemu/distrib/ -j=64 --arch=x86 --out=$YourOutDir

3. emulator -kernel ${YourOutDir}/kernel-qemu # run emulator:

Step #2 calls the wrapper scripts which works around the SSE disabling gcc warning - which happens for GCC < 4.5 (as in the AOSP prebuilt X86 toolchain).

This script adds the " -mfpmath=387 -fno-pic" in case it is an X86 and that in turn eliminates the compilation errors seen above.

To have finer control over the build process, you can use the "" wrapper and set some other stuff without modifying the script files.

An example for building the same emulator is below:

# Set arch
export ARCH=x86
# Have make refer to the QEMU wrapper script for building android over x86 
(eliminates the errors listed above)
# Put your cross compiler here. I am using the AOSP prebuilt one in this example
# Configure your kernel - here I am taking the default goldfish_defconfig
make goldfish_defconfig
# build
make -j64
# Run emulator:
emulator -kernel arch/x86/boot/bzImage -show-kernel

This works for the 2.6.29 goldfish branch. If anyone is using the emulator with a 3+ kernel I would be like to hear about it.


2017.06.09 10:46:14

Product설정파일을 통해 환경변수를 설정하여 선택적으로 빌드가능
 PRODUCT_PACKAGE_OVERLAY : 대체될 resource가 있는 Path
 PRODUCT_PROPERTY_OVERRIDES : 추가될 system property 항목이며 /system/build.prop에 저장됨.
 PRODUCT_PACKAGES : 기본적으로 설치될 app 목록

전체 과정을 간략히 설명하면, TARGET_BUILD_VARIANT에 따라서 System Property와 설치될 모듈을 결정합니다그 과정을 Makefile을 따라가면서 확인해 보겠습니다.


시작은 open_src폴더 아래 Makefile에서 build/core/main.mk로 이동합니다.



include build/core/



아래 build/core/main.mk를 보면 환경변수 TARGET_BUILD_VARIANT에 따라서 System Property를 다르게 설정하고 있습니다.

Part 1 : /build/core/

## user/userdebug ##


user_variant := $(filter userdebug user,$(TARGET_BUILD_VARIANT))

enable_target_debugging := true

ifneq (,$(user_variant))

  # Target is secure in user builds.



  tags_to_install := user

  ifeq ($(user_variant),userdebug)

    # Pick up some extra useful tools

    tags_to_install += debug


    # Disable debugging in plain user builds.

    enable_target_debugging :=



  # TODO: Always set WITH_DEXPREOPT (for user builds) once it works on OSX.

  # Also, remove the corresponding block in config/product_config.make.

  ifeq ($(HOST_OS)-$(WITH_DEXPREOPT_buildbot),linux-true)

    WITH_DEXPREOPT := true



  # Disallow mock locations by default for user builds

  ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=0


else # !user_variant

  # Turn on checkjni for non-user builds.


  # Set device insecure for non-user builds.


  # Allow mock locations by default for non user builds

  ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=1

endif # !user_variant


ifeq (true,$(strip $(enable_target_debugging)))

  # Target is more debuggable and adbd is on by default

  ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=1 persist.service.adb.enable=1

  # Include the debugging/testing OTA keys in this build.


else # !enable_target_debugging

  # Target is less debuggable and adbd is off by default

  ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=0 persist.service.adb.enable=0

endif # !enable_target_debugging


## eng ##



tags_to_install := user debug eng

# Don't require the setup wizard on eng builds

#eng모드에서 ro.setupwizard.mode property를 뺍니다.

  ADDITIONAL_BUILD_PROPERTIES := $(filter-out ro.setupwizard.mode=%,\

          $(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES)))




TARGET_BUILD_VARIANT에 따른 동작은 아래와 같습니다.  Android.mk의 정의된 LOCAL_MODULE_TAGS를 정의하지 않은 모듈은 기본이 user 태그입니다따라서 이전에 eng로 설정되어 있는 모듈들이 설치되지 않은 이유는 명시적으로 eng태그를 설정해 주었기 때문입니다.




- Installs modules tagged with: eng, debug, user, and/or development.

- Installs non-APK modules that have no tags specified.

- Installs APKs according to the product definition files, in addition to tagged APKs.


- ro.debuggable=1


- adb is enabled by default.


- Installs modules tagged with user.

- Installs non-APK modules that have no tags specified.

- Installs APKs according to the product definition files; tags are ignored for APK modules.


- ro.debuggable=0

- adb is disabled by default.


The same as user, except:

- Also installs modules tagged with debug.

- ro.debuggable=1

- adb is enabled by default.



빌드시 build/tools/findleaves.sh를 사용해서 각 폴더의 첫번째 Android.mk파일을 모두 찾아서 Makefile에 추가합니다하위 폴더에 Android.mk파일이 존재하더라도 상위 폴더에 Android.mk가 존재하면 상위 폴더에 있는 Android.mk까지만 찾습니다.

그리고 현재 Product설정파일의 TARGET_DEVICE BoardConfig.mk를 포함시킵니다.


Part 2 : /build/core/

# Can't use first-makefiles-under here because

# --mindepth=2 makes the prunes not work.

subdir_makefiles += \

    $(shell build/tools/ --prune="./out" $(subdirs)


# Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)

# or under vendor/*/$(TARGET_DEVICE).  Search in both places, but

# make sure only one exists.

# Real boards should always be associated with an OEM vendor.

board_config_mk := \

    $(strip $(wildcard \

        $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/ \

        vendor/*/$(TARGET_DEVICE)/ \


ifeq ($(board_config_mk),)

  $(error No config file found for TARGET_DEVICE $(TARGET_DEVICE))


ifneq ($(words $(board_config_mk)),1)

  $(error Multiple board config files for TARGET_DEVICE $(TARGET_DEVICE): $(board_config_mk))


include $(board_config_mk)

TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))

board_config_mk :=


# Clean up/verify variables defined by the board config file.




# Include all of the makefiles in the system




# We've probably been invoked by the "mm" shell function

# with a subdirectory's makefile.


# Change CUSTOM_MODULES to include only modules that were

# defined by this makefile; this will install all of those

# modules as a side-effect.  Do this after including ONE_SHOT_MAKEFILE

# so that the modules will be installed in the same place they

# would have been with a normal make.

CUSTOM_MODULES := $(sort $(call get-tagged-modules,$(ALL_MODULE_TAGS),))



# Stub out the notice targets, which probably aren't defined

# when using ONE_SHOT_MAKEFILE.




include $(subdir_makefiles)


# -------------------------------------------------------------------

# All module makefiles have been included at this point.

# -------------------------------------------------------------------


build/tools/ 동작 예제

$find hardware –name “*.mk”





























$ ./build/tools/ hardware

hardware/libhardware/ => 폴더구조의 첫번째 Android.mk만 포함됨











hardware/msm7k/ 파일에서 아래와 같이 하위의 Android.mk파일을 상황에 따라서 include를 하여 필요한 모듈만 컴파일하여 추가시킬 때 사용할 수 있습니다(이것을 사용해서 Samsung Open Source쪽 변경 소스 관리를 할 수 있을 것으로 보입니다. )

ifneq ($(filter capella7200, surf, $(TARGET_DEVICE)), )

  include $(all-subdir-makefiles)



설치될 모듈들을 선택하고, LOCAL_OVERRIDES_PACKAGES로 선택된 Package를 항목에서 삭제합니다.

Part 3 : build/core/

# -------------------------------------------------------------------

# Figure out our module sets.


# Of the modules defined by the component makefiles,

# determine what we actually want to build.

# If a module has the "restricted" tag on it, it

# poisons the rest of the tags and shouldn't appear

# on any list.


                          $(ALL_BUILT_MODULES) \


# TODO: Remove the 3 places in the tree that use

# ALL_DEFAULT_INSTALLED_MODULES and get rid of it from this list.



  # The base list of modules to build for this product is specified

  # by the appropriate product definition file, which was included

  # by product_config.make.

  user_PACKAGES := $(call module-installed-files, \


  ifeq (0,1)

    $(info user packages for $(TARGET_DEVICE) ($(INTERNAL_PRODUCT)):)

    $(foreach p,$(user_PACKAGES),$(info :   $(p)))

    $(error done)



  # We're not doing a full build, and are probably only including

  # a subset of the module makefiles.  Don't try to build any modules

  # requested by the product, because we probably won't have rules

  # to build them.

  user_PACKAGES :=


# Use tags to get the non-APPS user modules.  Use the product

# definition files to get the APPS user modules.

user_MODULES := $(sort $(call get-tagged-modules,user,_class@APPS restricted))

user_MODULES := $(user_MODULES) $(user_PACKAGES)


eng_MODULES := $(sort $(call get-tagged-modules,eng,restricted))

debug_MODULES := $(sort $(call get-tagged-modules,debug,restricted))

tests_MODULES := $(sort $(call get-tagged-modules,tests,restricted))


ifeq ($(strip $(tags_to_install)),)

$(error ASSERTION FAILED: tags_to_install should not be empty)


modules_to_install := $(sort $(Default_MODULES) \

          $(foreach tag,$(tags_to_install),$($(tag)_MODULES)))


# Some packages may override others using LOCAL_OVERRIDES_PACKAGES.

# Filter out (do not install) any overridden packages.

overridden_packages := $(call get-package-overrides,$(modules_to_install))

ifdef overridden_packages

#  old_modules_to_install := $(modules_to_install)

  modules_to_install := \

      $(filter-out $(foreach p,$(overridden_packages),$(p) %/$(p).apk), \




추가로Android의 모든 Application은 고유한 Key를 사용해서 Signning을 수행해야 합니다어떤 Key Signning을 할지를 결정은 LOCAL_CERTIFICATE에 기술합니다.


LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)




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




#LOCAL_CERTIFICATE := vendor/samsung/products/security/media   => 명시적으로 선택가능


LOCAL_STATIC_JAVA_LIBRARIES := googlelogin-client


#include $(BUILD_PACKAGE)


# Use the following include to make our test apk.

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


package.mk파일을 보시면 LOCAL_CERTIFICATE가 설정되지 않으면 testkey가 사용되며관련 private certificate /build/target/product/security/폴더에 있는 key값을 사용합니다.   => key값을 생성하기 위한 명령어, Samsung Android폰 개발시 고유한 key를 생성해서 출시해야함.











# Pick a key to sign the package with.  If this package hasn't specified

# an explicit certificate, use the default.

# Secure release builds will have their packages signed after the fact,

# so it's ok for these private keys to be in the clear.


    LOCAL_CERTIFICATE := testkey


# If this is not an absolute certificate, assign it to a generic one.

ifeq ($(dir $(strip $(LOCAL_CERTIFICATE))),./)



private_key := $(LOCAL_CERTIFICATE).pk8

certificate := $(LOCAL_CERTIFICATE).x509.pem


$(LOCAL_BUILT_MODULE): $(private_key) $(certificate) $(SIGNAPK_JAR)







# Define the rule to build the actual package.



$(LOCAL_BUILT_MODULE): $(all_res_assets) $(jni_shared_libraries) $(full_android_manifest)

    @echo "target Package: $(PRIVATE_MODULE) ($@)"



ifneq ($(jni_shared_libraries),)



ifneq ($(full_classes_jar),)




    @# Alignment must happen after all other zip operations.



# Save information about this package





출처: [고 투 더 멘토]
List of Articles
번호 제목 글쓴이 날짜 조회 수
공지 개발 오디오 분석을 위한 소스 빌드 사전작업 secret eastsky 2010-12-16 3
공지 개발 Android Tips secret eastsky 2010-11-15 5
27 개발 Android6.0 - PowerManagerService状态分析 eastsky 2017-07-21 2275
26 개발 Android6.0 - PowerManagerService Notifier 分析 eastsky 2017-07-21 2107
25 개발 Android 개발 전반에 대한 연재 eastsky 2017-06-13 2706
24 개발 kBuild eastsky 2017-06-13 2440
23 개발 Kbuild system eastsky 2017-06-13 3655
22 개발 [Linux] make menuconfig 사용방법 [1] eastsky 2017-06-12 5121
21 개발 ADB 명령어 및 Log Filter eastsky 2017-06-12 9556
20 개발 GNU Make eastsky 2017-06-09 2519
» 개발 Android Build System [1] eastsky 2017-06-09 7067
18 개발 Linux and Android - Suspend / Resume eastsky 2012-12-24 33254
17 개발 안드로이드 터치 보정값을 얻자. file [1] 이종일 2011-02-23 44806
16 개발 Android에 BusyBox 첨가 하기. [3] 이종일 2011-02-22 54150
15 개발 Android 동호문서 따라하기 file 이종일 2011-02-18 30753
14 개발 Linux RamDisk 참고 자료 file 이종일 2011-02-17 34510
13 일반 Android 2.3 Platform Highlights eastsky 2010-12-08 21005
12 개발 안드로이드 초기화 과정 eastsky 2010-12-02 48127
11 일반 하이씨엘 앱 에디터 eastsky 2010-12-01 24671
10 개발 Android 2.2 - Market Client on ADV file eastsky 2010-11-30 27325
9 개발 Android 2.2 - SDK & AVD Manager file eastsky 2010-11-30 28714