[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.
BasicIn 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
ExecutableIn 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 LibraryIn 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.
|
|