Chinaunix首页 | 论坛 | 博客
  • 博客访问: 395470
  • 博文数量: 119
  • 博客积分: 1796
  • 博客等级: 上尉
  • 技术积分: 890
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-14 10:16
个人简介

守正

文章分类
文章存档

2013年(1)

2011年(40)

2010年(78)

分类: 嵌入式

2010-06-04 19:20:18

Android build system

[First written by Steve Guo, please keep the mark if forwarding.]

Device/docs/design/build-system.html is a good start point to understand Android build system. In this topic, I will describe the behind details using mm to compile an executable and shared library.

Basic

In envsetup.sh, mm macro is defined.

function mm()

{

    # If we're sitting in the root of the build tree, just do a

    # normal make.

    if [ -f config/envsetup.make -a -f Makefile ]; then

        make $@

    else

        # Find the closest Android.mk file.

        T=$(gettop)

        M=$(findmakefile)

        if [ ! "$T" ]; then

            echo "Couldn't locate the top of the tree.  Try setting TOP."

        elif [ ! "$M" ]; then

            echo "Couldn't locate a makefile from the current directory."

        else

            ONE_SHOT_MAKEFILE=$M make -C $T files $@

        fi

    fi

}

 

In top layer Makefile

ifneq ($(ONE_SHOT_MAKEFILE),)

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

# with a subdirectory's makefile.

include $(ONE_SHOT_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),))

FULL_BUILD :=

INTERNAL_DEFAULT_DOCS_TARGETS :=

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

# when using ONE_SHOT_MAKEFILE.

NOTICE-HOST-%: ;

NOTICE-TARGET-%: ;

So if we type mm in a directory, it will finally include our own Android.mk. Android will put every Android.mk into one huge Makefile.

In top layer Makefile, it includes base_rules.make, while in base_rules.make it defines a target for LOCAL_MODULE which must be specified in our own Android.mk.

# Provide a short-hand for building this module.

# We name both BUILT and INSTALLED in case

# LOCAL_UNINSTALLABLE_MODULE is set.

.PHONY: $(LOCAL_MODULE)

$(LOCAL_MODULE): $(LOCAL_BUILT_MODULE) $(LOCAL_INSTALLED_MODULE)

 

definitions.make contains the most important macros for building source file. Here lists the two macros for building C++ and C source files.

###########################################################

## Commands for running gcc to compile a C++ file

###########################################################

 

define transform-cpp-to-o

@mkdir -p $(dir $@)

@echo "target $(PRIVATE_ARM_MODE) C++: $(PRIVATE_MODULE) <= $<"

$(hide) $(PRIVATE_CXX) \

       $(foreach incdir, \

           $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \

              $(TARGET_PROJECT_INCLUDES) \

              $(TARGET_C_INCLUDES) \

            ) \

           $(PRIVATE_C_INCLUDES) \

         , \

           -I $(incdir) \

        ) \

       -c \

       $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \

           $(TARGET_GLOBAL_CFLAGS) \

           $(TARGET_GLOBAL_CPPFLAGS) \

           $(PRIVATE_ARM_CFLAGS) \

        ) \

       $(PRIVATE_CFLAGS) \

       $(PRIVATE_CPPFLAGS) \

       $(PRIVATE_DEBUG_CFLAGS) \

       -fno-rtti \

       -MD -o $@ $<

$(hide) $(transform-d-to-p)

endef

 

###########################################################

## Commands for running gcc to compile a C file

###########################################################

 

# $(1): extra flags

define transform-c-or-s-to-o-no-deps

@mkdir -p $(dir $@)

$(hide) $(PRIVATE_CC) \

       $(foreach incdir, \

           $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \

              $(TARGET_PROJECT_INCLUDES) \

              $(TARGET_C_INCLUDES) \

            ) \

           $(PRIVATE_C_INCLUDES) \

         , \

           -I $(incdir) \

        ) \

       -c \

       $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \

           $(TARGET_GLOBAL_CFLAGS) \

           $(PRIVATE_ARM_CFLAGS) \

        ) \

       $(PRIVATE_CFLAGS) \

       $(1) \

       $(PRIVATE_DEBUG_CFLAGS) \

       -MD -o $@ $<

endef

 

 

Executable

In our own Android.mk we should add two lines.

LOCAL_MODULE := ***

include $(BUILD_EXECUTABLE)

 

BUILD_EXECUTALE is defined in config.make.

BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.make

 

In executable.make

include $(BUILD_SYSTEM)/dynamic_binary.make

 

ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)

$(linked_module): $(TARGET_CRTBEGIN_STATIC_O) $(all_objects) $(all_libraries) $(TARGET_CRTEND_O)

       $(transform-o-to-static-executable)

else 

$(linked_module): $(TARGET_CRTBEGIN_DYNAMIC_O) $(all_objects) $(all_libraries) $(TARGET_CRTEND_O)

       $(transform-o-to-executable)

Endif

So here defined a new target $(linked_module).

 

transform-o-to-exeuctable macro is defined in defintions.make.

define transform-o-to-executable

@mkdir -p $(dir $@)

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

$(hide) $(transform-o-to-executable-inner)

endef

 

combo/linux-arm.make contains macros to transform o to executable for ARM.

define transform-o-to-executable-inner

$(TARGET_CXX) -nostdlib -Bdynamic -Wl,-T,$(BUILD_SYSTEM)/armelf.x \

       -Wl,-dynamic-linker,/system/bin/linker \

    -Wl,--gc-sections \

       -Wl,-z,nocopyreloc \

       -o $@ \

       $(TARGET_GLOBAL_LD_DIRS) \

       -Wl,-rpath-link=$(TARGET_OUT_INTERMEDIATE_LIBRARIES) \

       $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \

       $(TARGET_CRTBEGIN_DYNAMIC_O) \

       $(PRIVATE_ALL_OBJECTS) \

       $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \

       $(PRIVATE_LDFLAGS) \

       $(TARGET_LIBGCC) \

       $(TARGET_CRTEND_O)

endef

 

binary.make contains some PRIVATE_* definitions used by the above macros.

$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_YACCFLAGS := $(LOCAL_YACCFLAGS)

$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ASFLAGS := $(LOCAL_ASFLAGS)

$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CFLAGS := $(LOCAL_CFLAGS)

$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CPPFLAGS := $(LOCAL_CPPFLAGS)

$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_DEBUG_CFLAGS := $(debug_cflags)

$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_C_INCLUDES := $(LOCAL_C_INCLUDES)

$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_LDFLAGS := $(LOCAL_LDFLAGS)

$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_LDLIBS := $(LOCAL_LDLIBS)

 

combo/linux-arm.make contains default CFLAGS/CPPFLAGS/C_INCLUDES definitions.

$(combo_target)GLOBAL_CFLAGS += \

                     -march=armv5te -mtune=xscale \

                     -msoft-float -fpic \

                     -mthumb-interwork \

                     -ffunction-sections \

                     -funwind-tables \

                     -fstack-protector \

                     -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ \

                     -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ \

                     -include include/arch/linux-arm/AndroidConfig.h

 

$(combo_target)GLOBAL_CPPFLAGS += -fvisibility-inlines-hidden

 

$(combo_target)RELEASE_CFLAGS := \

                     -DSK_RELEASE -DNDEBUG \

                     -O2 -g \

                     -Wstrict-aliasing=2 \

                     -finline-functions \

                     -fno-inline-functions-called-once \

                     -fgcse-after-reload \

                     -frerun-cse-after-loop \

                     -frename-registers

 

# unless CUSTOM_KERNEL_HEADERS is defined, we're going to use

# symlinks located in out/ to point to the appropriate kernel

# headers. see 'config/kernel_headers.make' for more details

#

KERNEL_HEADERS_COMMON := system/bionic/kernel/common

KERNEL_HEADERS_ARCH   := system/bionic/kernel/arch-$(TARGET_ARCH)

ifneq ($(CUSTOM_KERNEL_HEADERS),)

    KERNEL_HEADERS_COMMON := $(CUSTOM_KERNEL_HEADERS)

    KERNEL_HEADERS_ARCH   := $(CUSTOM_KERNEL_HEADERS)

endif

KERNEL_HEADERS := $(KERNEL_HEADERS_COMMON) $(KERNEL_HEADERS_ARCH)

 

$(combo_target)C_INCLUDES := \

       system/bionic/arch-arm/include \

       system/bionic/include \

       system/libstdc++/include \

       $(KERNEL_HEADERS) \

       system/libm/include \

       system/libm/include/arch/arm \

       system/libthread_db/include

 

Shared Library

In our own Android.mk we should add two lines.

LOCAL_MODULE := ***

include $(BUILD_SHARED_LIBRARY)

 

BUILD_SHARED_LIBRARY is defined in config.make.

BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.make

 

In shared_library.make

include $(BUILD_SYSTEM)/dynamic_binary.make

 

$(linked_module): $(all_objects) $(all_libraries) $(LOCAL_ADDITIONAL_DEPENDENCIES)

       $(transform-o-to-shared-lib)

So here defined a new target $(linked_module).

 

transform-o-to-shared-lib macro is defined in defintions.make.

define transform-o-to-shared-lib

@mkdir -p $(dir $@)

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

$(hide) $(transform-o-to-shared-lib-inner)

endef

 

combo/linux-arm.make contains macro to transform o to shared lib for ARM.

define transform-o-to-shared-lib-inner

$(TARGET_CXX) \

       -nostdlib -Wl,-soname,$(notdir $@) -Wl,-T,$(BUILD_SYSTEM)/armelf.xsc \

       -Wl,--gc-sections \

       -Wl,-shared,-Bsymbolic \

       $(TARGET_GLOBAL_LD_DIRS) \

       $(PRIVATE_ALL_OBJECTS) \

       -Wl,--whole-archive \

       $(call normalize-host-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \

       -Wl,--no-whole-archive \

       $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \

       $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \

       -o $@ \

       $(PRIVATE_LDFLAGS) \

       $(TARGET_LIBGCC)

endef

 

Tips: “make *** showcommands”can let build system show the original compile commands.

阅读(1261) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~