Monday, April 27, 2009

A closer look at the Android project build system part II

This is the second post on the build system where we will take a closer look at the Android.mk file and what options are available. An Android.mk file describes the build for any native module that should go in the platform. We will start by looking at the makefile for the external ping facility found in external/ping.


ifneq ($(TARGET_SIMULATOR),true)

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_SRC_FILES:= ping.c
LOCAL_MODULE := ping
LOCAL_STATIC_LIBRARIES := libcutils libc
include $(BUILD_EXECUTABLE)

endif # TARGET_SIMULATOR != true


The first line is just a check if we are building for the (obsolete?) simulator. The next line sets the local path to the current directory (the directory of this Android.mk file). This is handled by a function called mydir that can be found in the definitions.mk file in the build system.

The next step is to include a makefile that will clear all local variables with the line include $(CLEAR_VARS). CLEAR_VARS is set in the build configuration in config.mk and will include the clear_vars.mk file at this point. The main purpose of this include is to make sure that we do not use any local variables set by another module.

After the two initial lines that basically prepares the build system to start with this module we set the build variables. These are


LOCAL_SRC_FILES - the source files that make up this module
LOCAL_MODULE - the name of the module
LOCAL_STATIC_LIBRARIES - libraries to statically link to this module

Since ping will be an executable command placed in /system/bin in the Android file system the make file for building an executable should be used. This done with the line:

include $(BUILD_EXECUTABLE)

There are makefiles available in the build system that can be used to build a number of different types of module. To include them you may use one of the variables set in the config.mk file. A few important ones are:


BUILD_EXECUTABLE - Build an executable module
BUILD_SHARED_LIBRARY - Build a shared library
BUILD_STATIC_LIBRARY - Build a static library
BUILD_PREBUILT - Add prebuilt components


There is also a number of local variables that are recognized by the build system and that needs to be set in order to build your module.


LOCAL_C_INCLUDES - path to include files needed by your module, e.g. ($KERNEL_HEADERS)
LOCAL_CFLAGS - Any additional flags to pass to the compiler
LOCAL_LDFLAGS - Any additional flags to pass to the linker
LOCAL_SHARED_LIBRARIES - Shared libraries that the module directly links against
LOCAL_SRC_FILES - The source files to compile
LOCAL_STATIC_LIBRARIES - Static libraries to include in the module


You may use one Android.mk to build several items. It is possible to build both a library and an executable using the same makefile. To illustrate how to write a makefile for some native functionality we will look at another example. This makefile will build a shared library and an executable. It links to a couple of shared libraries in the system.



LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
#Name of target to build
LOCAL_MODULE:= libmylibrary
#Source files to compile
LOCAL_SRC_FILES:= mysrcfile.c mysothersrcfile.c
#The shared libraries to link against
LOCAL_SHARED_LIBRARIES := libcutils
#No special headers needed
LOCAL_C_INCLUDES +=
#Prelink this library, also need to add it to the prelink map
LOCAL_PRELINK_MODULE := true
include $(BUILD_SHARED_LIBRARY)

#Clear variables and build the executable
include $(CLEAR_VARS)
LOCAL_MODULE:= myinfocmd
LOCAL_SRC_FILES:= mycmdsrcfile.c
include $(BUILD_EXECUTABLE)


The output of the build system is put in the out folder in the Android project. Build output is directed to a subfolder based on the product. A default build is for the generic product and will output everything target related to that folder. A shared library ends up in /out/target/product/generic/system/lib. In the same way an executable will end up in /out/target/product/generic/system/bin. The object files and intermediates are kept in the obj folder. The root, system, and data folders will be used to generate the file system images needed for Android in the last build step.

/Mattias

3 comments:

  1. Hi,

    What should be the command if just want to selectively build the ping module in your case for example?

    ReplyDelete
  2. To build a module in the Android Open Source Project there are a couple of commands available in the build system. These are enabled by running the envsetup.sh script in the build folder. Depending on what you prefer you may then use
    mm - to build modules in your current directory or
    mmm - to build modules in a directory you supply

    A command line example for ping would be:
    cd
    source build/envsetup.sh
    cd external/ping
    mm

    ReplyDelete
  3. The first line in the example above should read
    cd root_of_your_AOSP

    ReplyDelete