Skip to content

Android Automotive »

AOSP Build Notes

Notes when working with AOSP

Last update: 2022-07-14

Table of Content


Bionic is an implementation of the standard C library, developed by Google for its Android operating system. It differs from the GNU C Library (glibc) in being designed for devices with less memory and processor power than a typical Linux system.

Bionic is a C library for use with the Linux kernel, and provides libc, libdl, and libm (libpthread functionality is part of libc, not a separate library as on some other systems).


Bionic only supports Linux kernels, but currently supports the arm, arm64, x86, and x86-64 architectures.


In Makefiles, we usually see the command to inherit another product:

$(call inherit-product, <>)
# or
$(call inherit-product-if-exist, <>)

The function inherit-product is defined in build/core/

# Functions for including product makefiles
# $(1): product to inherit
# To be called from product makefiles, and is later evaluated during the import-nodes
# call below. It does three things:
#  1. Inherits all of the variables from $1.
#  2. Records the inheritance in the .INHERITS_FROM variable
#  3. Records the calling makefile in PARENT_PRODUCT_FILES
# (2) and (3) can be used together to reconstruct the include hierarchy
# See e.g. for an example of this.

define inherit-product
  $(if $(findstring ../,$(1)),\
    $(eval np := $(call normalize-paths,$(1))),\
    $(eval np := $(strip $(1))))\
  $(foreach v,$(_product_var_list), \
      $(eval $(v) := $($(v)) $(INHERIT_TAG)$(np))) \
  $(eval current_mk := $(strip $(word 1,$(_include_stack)))) \
  $(eval inherit_var := PRODUCTS.$(current_mk).INHERITS_FROM) \
  $(eval $(inherit_var) := $(sort $($(inherit_var)) $(np))) \
  $(eval PARENT_PRODUCT_FILES := $(sort $(PARENT_PRODUCT_FILES) $(current_mk)))

Let’s say you have:

  • PRODUCT_VAR := a in
  • PRODUCT_VAR := b in

If you include in_ A.mk_, you will get PRODUCT_VAR := b at last.

If you inherit-product in, you will getPRODUCT_VAR := a b, note the order is a then b.

And inherit-product makes sure that you won’t include a makefile twice because it Records that we’ve visited this node, in PARENT_PRODUCT_FILES.


When using inherit-product, there are cases that a destination file is copied from many sources.

For example:

$(call inherit-product,

After the inherit-product call, the variable has been changed as:

    /path/a.txt:/path/target.txt \

The rule for PRODUCT_COPY_FILES is:

only eval the copy rule if this src:dest pair is the first one to match the same dest.

Therefore, only the rule /path/a.txt:/path/target.txt is evaluated.

The rules for PRODUCT_COPY_FILES is defined in build/core/Makefile:

# -----------------------------------------------------------------
# Define rules to copy PRODUCT_COPY_FILES defined by the product.
# PRODUCT_COPY_FILES contains words like <source file>:<dest file>[:<owner>].
# <dest file> is relative to $(PRODUCT_OUT), so it should look like,
# e.g., "system/etc/file.xml".
# The filter part means "only eval the copy-one-file rule if this
# src:dest pair is the first one to match the same dest"
#$(1): the src:dest pair
#$(2): the dest
define check-product-copy-files
$(if $(filter-out $(TARGET_COPY_OUT_SYSTEM_OTHER)/%,$(2)), \
$(if $(filter %.apk, $(2)),$(error \
    Prebuilt apk found in PRODUCT_COPY_FILES: $(1), use BUILD_PREBUILT instead!)))
# filter out the duplicate <source file>:<dest file> pairs.
unique_product_copy_files_pairs :=
$(foreach cf,$(PRODUCT_COPY_FILES), \
    $(if $(filter $(unique_product_copy_files_pairs),$(cf)),,\
        $(eval unique_product_copy_files_pairs += $(cf))))
unique_product_copy_files_destinations :=
product_copy_files_ignored :=
$(foreach cf,$(unique_product_copy_files_pairs), \
    $(eval _src := $(call word-colon,1,$(cf))) \
    $(eval _dest := $(call word-colon,2,$(cf))) \
    $(call check-product-copy-files,$(cf),$(_dest)) \
    $(if $(filter $(unique_product_copy_files_destinations),$(_dest)), \
        $(eval product_copy_files_ignored += $(cf)), \
        $(eval _fulldest := $(call append-path,$(PRODUCT_OUT),$(_dest))) \
        $(if $(filter %.xml,$(_dest)),\
            $(eval $(call copy-xml-file-checked,$(_src),$(_fulldest))),\
            $(if $(and $(filter %.jar,$(_dest)),$(filter $(basename $(notdir $(_dest))),$(PRODUCT_LOADED_BY_PRIVILEGED_MODULES))),\
                $(eval $(call copy-and-uncompress-dexs,$(_src),$(_fulldest))), \
                $(if $(filter init%rc,$(notdir $(_dest)))$(filter %/etc/init,$(dir $(_dest))),\
                    $(eval $(call copy-init-script-file-checked,$(_src),$(_fulldest))),\
                    $(eval $(call copy-one-file,$(_src),$(_fulldest)))))) \
        $(eval unique_product_copy_files_destinations += $(_dest))))

# Dump a list of overriden (and ignored PRODUCT_COPY_FILES entries)
pcf_ignored_file := $(PRODUCT_OUT)/product_copy_files_ignored.txt
$(pcf_ignored_file): PRIVATE_IGNORED := $(sort $(product_copy_files_ignored))
    echo "$(PRIVATE_IGNORED)" | tr " " "\n" >$@

$(call dist-for-goals,droidcore,$(pcf_ignored_file):logs/$(notdir $(pcf_ignored_file)))

pcf_ignored_file :=
product_copy_files_ignored :=
unique_product_copy_files_pairs :=
unique_product_copy_files_destinations :=