Android 编译脚本浅析

buildspec.mk



所在路径:/build/

buildspec.mk是用户应当配置的脚本文件,模板可以使用buildspec.mk.default,放到$(TOP)下。
在 buildspec.mk中,用户应该配置好主要的参数,例如 TARGET_PRODUCT, TARGET_BUILD_VARIANT, CUSTOM_MODULES,  TARGET_SIMULATOR, TARGET_BUILD_TYPE, CUSTOM_LOCALES, 和BUILD_ENV_SEQUENCE_NUMBER等。
如果不使用buildspec.mk配置参数,也可以使用环境变量的形式。若不配置参数,那么android会使用默认的参数

#

# Copyright (C) 2007 The Android Open Source Project

#

# Licensed under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at

#

#      http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

#


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

# This is a do-nothing template file.  To use it, copy it to a file

# named "buildspec.mk" in the root directory, and uncomment or change

# the variables necessary for your desired configuration.  The file

# "buildspec.mk" should never be checked in to source control.

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


# Choose a product to build for.  Look in the products directory for ones

# that work.

#在buildspec.mk或环境变量中已经定义好

ifndef TARGET_PRODUCT

#TARGET_PRODUCT:=generic

endif


# Choose a variant to build.  If you don't pick one, the default is eng.

# User is what we ship.  Userdebug is that, with a few flags turned on

# for debugging.  Eng has lots of extra tools for development.

##再检查TARGET_BUILD_VARIANT,若为空,则置eng。TARGET_BUILD_VARIANT应当在buildspec.mk或环境变量中已经定义好

ifndef TARGET_BUILD_VARIANT

#TARGET_BUILD_VARIANT:=user

#TARGET_BUILD_VARIANT:=userdebug

#TARGET_BUILD_VARIANT:=eng

endif


# Choose additional targets to always install, even when building

# minimal targets like "make droid".  This takes simple target names

# like "Browser" or "MyApp", the names used by LOCAL_MODULE or

# LOCAL_PACKAGE_NAME.  Modules listed here will always be installed in

# /system, even if they'd usually go in /data.

ifndef CUSTOM_MODULES

#CUSTOM_MODULES:=

endif


# Set this to debug or release if you care.  Otherwise, it defaults to release.

ifndef TARGET_BUILD_TYPE

#TARGET_BUILD_TYPE:=release

endif


# Uncomment this if you want the host tools built in debug mode.  Otherwise

# it defaults to release.

ifndef HOST_BUILD_TYPE

#HOST_BUILD_TYPE:=debug

endif


# Turn on debugging for selected modules.  If DEBUG_MODULE_<module-name> is set

# to a non-empty value, the appropriate HOST_/TARGET_CUSTOM_DEBUG_CFLAGS

# will be added to LOCAL_CFLAGS when building the module.

#DEBUG_MODULE_ModuleName:=true


# Specify an alternative tool chain prefix if needed.

#TARGET_TOOLS_PREFIX:=


# Specify the extra CFLAGS to use when building a module whose

# DEBUG_MODULE_ variable is set.  Host and device flags are handled

# separately.

#HOST_CUSTOM_DEBUG_CFLAGS:=

#TARGET_CUSTOM_DEBUG_CFLAGS:=


# Choose additional locales, like "en_US" or "it_IT", to add to any

# built product.  Any locales that appear in CUSTOM_LOCALES but not in

# the locale list for the selected product will be added to the end

# of PRODUCT_LOCALES.

ifndef CUSTOM_LOCALES

#CUSTOM_LOCALES:=

endif


# If you have a special place to put your ouput files, set this, otherwise

# it goes to <build-root>/out

#OUT_DIR:=/tmp/stuff


# If you want to always set certain system properties, add them to this list.

# E.g., "ADDITIONAL_BUILD_PROPERTIES += ro.prop1=5 prop2=value"

# This mechanism does not currently support values containing spaces.

#ADDITIONAL_BUILD_PROPERTIES +=


# If you want to reduce the system.img size by several meg, and are willing to

# lose access to CJK (and other) character sets, define NO_FALLBACK_FONT:=true

ifndef NO_FALLBACK_FONT

#NO_FALLBACK_FONT:=true

endif


# OVERRIDE_RUNTIMES allows you to locally override PRODUCT_RUNTIMES.

#

# To only build ART, use "runtime_libart_default"

# To use Dalvik but also include ART, use "runtime_libdvm_default runtime_libart"

# To use ART but also include Dalvik, use "runtime_libart_default runtime_libdvm"

ifndef OVERRIDE_RUNTIMES

#OVERRIDE_RUNTIMES:=runtime_libart_default

#OVERRIDE_RUNTIMES:=runtime_libdvm_default runtime_libart

#OVERRIDE_RUNTIMES:=runtime_libart_default runtime_libdvm

endif


# when the build system changes such that this file must be updated, this

# variable will be changed.  After you have modified this file with the new

# changes (see buildspec.mk.default), update this to the new value from

# buildspec.mk.default.

BUILD_ENV_SEQUENCE_NUMBER := 10

---------------------------------------------------------------------------------


build_id


用户可以在build_id.mk中定义这样几个参数,
PLATFORM_VERSION
PLATFORM_SDK_VERSION
PLATFORM_VERSION_CODENAME
DEFAULT_APP_TARGET_SDK
BUILD_ID
BUILD_NUMBER
这些参数最终将出现build.prop中。

Froyo的build_id.mk中定义了2个变量,
BUILD_ID,通常用于说明分支branch的,默认的是OPENMASTER,用户应该配置这个参数。

DISPLAY_BUILD_NUMBER, 在TARGET_BUILD_VARIANT=user的版本中,build.prop中是ro.build.id是显示 成$(BUILD_ID).$(BUILD_NUMBER),还是显示成$(BUILD_ID)形式。设成true,则显示前者


#

# Copyright (C) 2008 The Android Open Source Project

#

# Licensed under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at

#

#      http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

#

# BUILD_ID is usually used to specify the branch name

# (like "MAIN") or a branch name and a release candidate

# (like "CRB01").  It must be a single word, and is

# capitalized by convention.


export BUILD_ID=KOT49H


---------------------------------------------------------------------------------

version_defaults.mk



在build/core路径下

version_defaults.mk是检查一些跟版本相关的变量是否定义,如果未定义,则使用默认值。这些变量包括

PLATFORM_VERSION,默认AOSP
PLATFORM_SDK_VERSION,默认8
PLATFORM_VERSION_CODENAME,默认AOSP
DEFAULT_APP_TARGET_SDK,默认AOSP
BUILD_ID,默认UNKNOWN
BUILD_NUMBER,默认eng.$(USER).$(shell date +%Y%m%d.%H%M%S)的形式。

version_defaults.mk首先包含进build_id.mk。用户应当配置build_id.mk,而不应该改动version_defaults.mk文件。
然后检查上述变量,如未定义则赋值默认值

#

# Copyright (C) 2008 The Android Open Source Project

#

# Licensed under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at

#

#      http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

#


#

# Handle various build version information.

#

# Guarantees that the following are defined:

#     PLATFORM_VERSION

#     PLATFORM_SDK_VERSION

#     PLATFORM_VERSION_CODENAME

#     DEFAULT_APP_TARGET_SDK

#     BUILD_ID

#     BUILD_NUMBER

#


# Look for an optional file containing overrides of the defaults,

# but don't cry if we don't find it.  We could just use -include, but

# the build.prop target also wants INTERNAL_BUILD_ID_MAKEFILE to be set

# if the file exists.

#

INTERNAL_BUILD_ID_MAKEFILE := $(wildcard $(BUILD_SYSTEM)/build_id.mk)

ifneq "" "$(INTERNAL_BUILD_ID_MAKEFILE)"

  include $(INTERNAL_BUILD_ID_MAKEFILE)

endif


ifeq "" "$(PLATFORM_VERSION)"

  # This is the canonical definition of the platform version,

  # which is the version that we reveal to the end user.

  # Update this value when the platform version changes (rather

  # than overriding it somewhere else).  Can be an arbitrary string.

#在设置>关于手机>android版本快速点击,即可显示此版本号,再长按就会显示版本动画

  PLATFORM_VERSION := 4.4.2

endif


ifeq "" "$(PLATFORM_SDK_VERSION)"

  # This is the canonical definition of the SDK version, which defines

  # the set of APIs and functionality available in the platform.  It

  # is a single integer that increases monotonically as updates to

  # the SDK are released.  It should only be incremented when the APIs for

  # the new release are frozen (so that developers don't write apps against

  # intermediate builds).  During development, this number remains at the

  # SDK version the branch is based on and PLATFORM_VERSION_CODENAME holds

  # the code-name of the new development work.

  PLATFORM_SDK_VERSION := 19

endif


ifeq "" "$(PLATFORM_VERSION_CODENAME)"

  # This is the current development code-name, if the build is not a final

  # release build.  If this is a final release build, it is simply "REL".

  PLATFORM_VERSION_CODENAME := REL

endif


ifeq "" "$(DEFAULT_APP_TARGET_SDK)"

  # This is the default minSdkVersion and targetSdkVersion to use for

  # all .apks created by the build system.  It can be overridden by explicitly

  # setting these in the .apk's AndroidManifest.xml.  It is either the code

  # name of the development build or, if this is a release build, the official

  # SDK version of this release.

  ifeq "REL" "$(PLATFORM_VERSION_CODENAME)"

    DEFAULT_APP_TARGET_SDK := $(PLATFORM_SDK_VERSION)

  else

    DEFAULT_APP_TARGET_SDK := $(PLATFORM_VERSION_CODENAME)

  endif

endif


ifeq "" "$(BUILD_ID)"

  # Used to signify special builds.  E.g., branches and/or releases,

  # like "M5-RC7".  Can be an arbitrary string, but must be a single

  # word and a valid file name.

  #

  # If there is no BUILD_ID set, make it obvious.

  BUILD_ID := UNKNOWN

endif


ifeq "" "$(BUILD_NUMBER)"

  # BUILD_NUMBER should be set to the source control value that

  # represents the current state of the source code.  E.g., a

  # perforce changelist number or a git hash.  Can be an arbitrary string

  # (to allow for source control that uses something other than numbers),

  # but must be a single word and a valid file name.

  #

  # If no BUILD_NUMBER is set, create a useful "I am an engineering build

  # from this date/time" value.  Make it start with a non-digit so that

  # anyone trying to parse it as an integer will probably get "0".

  BUILD_NUMBER := eng.$(USER).$(shell date +%Y%m%d.%H%M%S)

endif


ifeq "" "$(HARDWARE_VERSION)"

  HARDWARE_VERSION := UNKNOWN

endif


ifeq "" "$(INTERNAL_VERSION)"

  INTERNAL_VERSION := UNKNOWN

endif

--------------------------------------------------------------------------------------------------------------------------------

version_defaults.mk  在build/core路径下


version_defaults.mk是检查一些跟版本相关的变量是否定义,如果未定义,则使用默认值。这些变量包括
PLATFORM_VERSION,默认AOSP
PLATFORM_SDK_VERSION,默认8
PLATFORM_VERSION_CODENAME,默认AOSP
DEFAULT_APP_TARGET_SDK,默认AOSP
BUILD_ID,默认UNKNOWN
BUILD_NUMBER,默认eng.$(USER).$(shell date +%Y%m%d.%H%M%S)的形式。

version_defaults.mk首先包含进build_id.mk。用户应当配置build_id.mk,而不应该改动version_defaults.mk文件。
然后检查上述变量,如未定义则赋值默认值

#

# Copyright (C) 2008 The Android Open Source Project

#

# Licensed under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at

#

#      http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

#


#

# Handle various build version information.

#

# Guarantees that the following are defined:

#     PLATFORM_VERSION

#     PLATFORM_SDK_VERSION

#     PLATFORM_VERSION_CODENAME

#     DEFAULT_APP_TARGET_SDK

#     BUILD_ID

#     BUILD_NUMBER

#


# Look for an optional file containing overrides of the defaults,

# but don't cry if we don't find it.  We could just use -include, but

# the build.prop target also wants INTERNAL_BUILD_ID_MAKEFILE to be set

# if the file exists.

#

INTERNAL_BUILD_ID_MAKEFILE := $(wildcard $(BUILD_SYSTEM)/build_id.mk)

ifneq "" "$(INTERNAL_BUILD_ID_MAKEFILE)"

  include $(INTERNAL_BUILD_ID_MAKEFILE)

endif


ifeq "" "$(PLATFORM_VERSION)"

  # This is the canonical definition of the platform version,

  # which is the version that we reveal to the end user.

  # Update this value when the platform version changes (rather

  # than overriding it somewhere else).  Can be an arbitrary string.

#在设置>关于手机>android版本快速点击,即可显示此版本号,再长按就会显示版本动画

  PLATFORM_VERSION := 4.4.2

endif


ifeq "" "$(PLATFORM_SDK_VERSION)"

  # This is the canonical definition of the SDK version, which defines

  # the set of APIs and functionality available in the platform.  It

  # is a single integer that increases monotonically as updates to

  # the SDK are released.  It should only be incremented when the APIs for

  # the new release are frozen (so that developers don't write apps against

  # intermediate builds).  During development, this number remains at the

  # SDK version the branch is based on and PLATFORM_VERSION_CODENAME holds

  # the code-name of the new development work.

  PLATFORM_SDK_VERSION := 19

endif


ifeq "" "$(PLATFORM_VERSION_CODENAME)"

  # This is the current development code-name, if the build is not a final

  # release build.  If this is a final release build, it is simply "REL".

  PLATFORM_VERSION_CODENAME := REL

endif


ifeq "" "$(DEFAULT_APP_TARGET_SDK)"

  # This is the default minSdkVersion and targetSdkVersion to use for

  # all .apks created by the build system.  It can be overridden by explicitly

  # setting these in the .apk's AndroidManifest.xml.  It is either the code

  # name of the development build or, if this is a release build, the official

  # SDK version of this release.

  ifeq "REL" "$(PLATFORM_VERSION_CODENAME)"

    DEFAULT_APP_TARGET_SDK := $(PLATFORM_SDK_VERSION)

  else

    DEFAULT_APP_TARGET_SDK := $(PLATFORM_VERSION_CODENAME)

  endif

endif


ifeq "" "$(BUILD_ID)"

  # Used to signify special builds.  E.g., branches and/or releases,

  # like "M5-RC7".  Can be an arbitrary string, but must be a single

  # word and a valid file name.

  #

  # If there is no BUILD_ID set, make it obvious.

  BUILD_ID := UNKNOWN

endif


ifeq "" "$(BUILD_NUMBER)"

  # BUILD_NUMBER should be set to the source control value that

  # represents the current state of the source code.  E.g., a

  # perforce changelist number or a git hash.  Can be an arbitrary string

  # (to allow for source control that uses something other than numbers),

  # but must be a single word and a valid file name.

  #

  # If no BUILD_NUMBER is set, create a useful "I am an engineering build

  # from this date/time" value.  Make it start with a non-digit so that

  # anyone trying to parse it as an integer will probably get "0".

  BUILD_NUMBER := eng.$(USER).$(shell date +%Y%m%d.%H%M%S)

endif


ifeq "" "$(HARDWARE_VERSION)"

  HARDWARE_VERSION := UNKNOWN

endif


ifeq "" "$(INTERNAL_VERSION)"

  INTERNAL_VERSION := UNKNOWN

endif

-------------------------------------------------------------------------------------------------------------------------------

product_config.mk

make PRODUCT-<prodname>-<goal>  <other>

如果使用上述形式的make命令,那么将等同于

TARGET_PRODUCT:=<prodname>
TARGET_BUILD_VARIANT:=<goal>
goal_name:=PRODUCT-<prodname>-<goal>
MAKECMDGOALS:=droid <other>

.PHONY: $(goal_name)
$(goal_name): $(MAKECMDGOALS)
endif

注意,goal的取值范围是user userdebug eng tests,如果不属于上述范围,则将算入MAKECMDGOALS中,此时, TARGET_BUILD_VARIANT := eng。例如
make PRODUCT-dream-installclean
等同于
TARGET_PRODUCT=dream make installclean

使用make PRODUCT-<prodname>-<goal>这种形式,可以方便的指定TARGET_PRODUCT,和TARGET_BUILD_VARIANT。


make APP-<appname>  <other>

如果使用上述形式的make命令,那么将等同于
TARGET_BUILD_APPS:=<appname>
unbundled_goals:=APP-<appname>
MAKECMDGOALS:=droid <other>

.PHONY: $(unbundled_goals)
$(unbundled_goals): $(MAKECMDGOALS)

使用make APP-<appname>这种形式,可以方便的指定TARGET_BUILD_APPS。


注意,PRODUCT-<prodname>-<goal>和APP-<appname>可以一块使用。

处理完PRODUCT-<prodname>-<goal>和APP-<appname>,product_config.mk会包含下面3个文件
node_fns.mk
product.mk
device.mk

上面的3个mk文件定义了一些命令,用于搜寻product, device对应的目录,生成相应的PRODUCT.XXX,和DEVICE.XXX变量。

接着,使用$(call import-products, $(get-all-product-makefiles))遍历Prodcut相关的AndroidProducts.mk文件,读入PRODCUTS.xxx变量。可以去掉文件中下面两句话的注释符,查看。
#$(dump-products)
#$(error done)

随后,使用PRODCUT.xxx和TARGET_PRODUCT,得到INTERNAL_PRODUCT信息,即指定product的路径。

再 由INTERNAL_PRODUCT得到TARGET_DEVICE, PRODUCT_LOCALES, PRODUCT_BRAND, PRODUCT_MODEL, PRODUCT_MANUFACTURER, PRODUCT_DEFAULT_WIFI_CHANNELS, PRODUCT_POLICY, PRODUCT_COPY_FILES, PRODUCT_PROPERTY_OVERRIDES, PRODUCT_PACKAGE_OVERLAYS, DEVICE_PACKAGE_OVERLAYS, PRODUCT_TAGS, PRODUCT_OTA_PUBLIC_KEYS。
由PRODUCT_LOCALES导出PRODUCT_AAPT_CONFIG。
ADDITIONAL_BUILD_PROPERTIES中追加PRODUCT_PROPERTY_OVERRIDES中的值。
上面所说的这些值,实际上都是在product的mk文件中定义。


在 build/core/

#

# Copyright (C) 2008 The Android Open Source Project

#

# Licensed under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at

#

#      http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

#


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

# Generic functions

# TODO: Move these to definitions.make once we're able to include

# definitions.make before config.make.


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

## Return non-empty if $(1) is a C identifier; i.e., if it

## matches /^[a-zA-Z_][a-zA-Z0-9_]*$/.  We do this by first

## making sure that it isn't empty and doesn't start with

## a digit, then by removing each valid character.  If the

## final result is empty, then it was a valid C identifier.

##

## $(1): word to check

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


_ici_digits := 0 1 2 3 4 5 6 7 8 9

_ici_alphaunderscore := \

    a b c d e f g h i j k l m n o p q r s t u v w x y z \

    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _

define is-c-identifier

$(strip \

  $(if $(1), \

    $(if $(filter $(addsuffix %,$(_ici_digits)),$(1)), \

     , \

      $(eval w := $(1)) \

      $(foreach c,$(_ici_digits) $(_ici_alphaunderscore), \

        $(eval w := $(subst $(c),,$(w))) \

       ) \

      $(if $(w),,TRUE) \

      $(eval w :=) \

     ) \

   ) \

 )

endef


# TODO: push this into the combo files; unfortunately, we don't even

# know HOST_OS at this point.

trysed := $(shell echo a | sed -E -e 's/a/b/' 2>/dev/null)

ifeq ($(trysed),b)

  SED_EXTENDED := sed -E

else

  trysed := $(shell echo c | sed -r -e 's/c/d/' 2>/dev/null)

  ifeq ($(trysed),d)

    SED_EXTENDED := sed -r

  else

    $(error Unknown sed version)

  endif

endif


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

## List all of the files in a subdirectory in a format

## suitable for PRODUCT_COPY_FILES and

## PRODUCT_SDK_ADDON_COPY_FILES

##

## $(1): Glob to match file name

## $(2): Source directory

## $(3): Target base directory

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


define find-copy-subdir-files

$(shell find $(2) -name "$(1)" | $(SED_EXTENDED) "s:($(2)/?(.*)):\\1\\:$(3)/\\2:" | sed "s://:/:g")

endef


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


# These are the valid values of TARGET_BUILD_VARIANT.  Also, if anything else is passed

# as the variant in the PRODUCT-$TARGET_BUILD_PRODUCT-$TARGET_BUILD_VARIANT form,

# it will be treated as a goal, and the eng variant will be used.

INTERNAL_VALID_VARIANTS := user userdebug eng


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

# Provide "PRODUCT-<prodname>-<goal>" targets, which lets you build

# a particular configuration without needing to set up the environment.

#

product_goals := $(strip $(filter PRODUCT-%,$(MAKECMDGOALS)))

ifdef product_goals

  # Scrape the product and build names out of the goal,

  # which should be of the form PRODUCT-<productname>-<buildname>.

  #

  ifneq ($(words $(product_goals)),1)

    $(error Only one PRODUCT-* goal may be specified; saw "$(product_goals)")

  endif

  goal_name := $(product_goals)

  product_goals := $(patsubst PRODUCT-%,%,$(product_goals))

  product_goals := $(subst -, ,$(product_goals))

  ifneq ($(words $(product_goals)),2)

    $(error Bad PRODUCT-* goal "$(goal_name)")

  endif


  # The product they want

  TARGET_PRODUCT := $(word 1,$(product_goals))


  # The variant they want

  TARGET_BUILD_VARIANT := $(word 2,$(product_goals))


  ifeq ($(TARGET_BUILD_VARIANT),tests)

    $(error "tests" has been deprecated as a build variant. Use it as a build goal instead.)

  endif


  # The build server wants to do make PRODUCT-dream-installclean

  # which really means TARGET_PRODUCT=dream make installclean.

  ifneq ($(filter-out $(INTERNAL_VALID_VARIANTS),$(TARGET_BUILD_VARIANT)),)

    MAKECMDGOALS := $(MAKECMDGOALS) $(TARGET_BUILD_VARIANT)

    TARGET_BUILD_VARIANT := eng

    default_goal_substitution :=

  else

    default_goal_substitution := $(DEFAULT_GOAL)

  endif


  # Replace the PRODUCT-* goal with the build goal that it refers to.

  # Note that this will ensure that it appears in the same relative

  # position, in case it matters.

  #

  # Note that modifying this will not affect the goals that make will

  # attempt to build, but it's important because we inspect this value

  # in certain situations (like for "make sdk").

  #

  MAKECMDGOALS := $(patsubst $(goal_name),$(default_goal_substitution),$(MAKECMDGOALS))


  # Define a rule for the PRODUCT-* goal, and make it depend on the

  # patched-up command-line goals as well as any other goals that we

  # want to force.

  #

.PHONY: $(goal_name)

$(goal_name): $(MAKECMDGOALS)

endif

# else: Use the value set in the environment or buildspec.mk.


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

# Provide "APP-<appname>" targets, which lets you build

# an unbundled app.

#

unbundled_goals := $(strip $(filter APP-%,$(MAKECMDGOALS)))

ifdef unbundled_goals

  ifneq ($(words $(unbundled_goals)),1)

    $(error Only one APP-* goal may be specified; saw "$(unbundled_goals)"))

  endif

  TARGET_BUILD_APPS := $(strip $(subst -, ,$(patsubst APP-%,%,$(unbundled_goals))))

  ifneq ($(filter $(DEFAULT_GOAL),$(MAKECMDGOALS)),)

    MAKECMDGOALS := $(patsubst $(unbundled_goals),,$(MAKECMDGOALS))

  else

    MAKECMDGOALS := $(patsubst $(unbundled_goals),$(DEFAULT_GOAL),$(MAKECMDGOALS))

  endif


.PHONY: $(unbundled_goals)

$(unbundled_goals): $(MAKECMDGOALS)

endif # unbundled_goals


# Default to building dalvikvm on hosts that support it...

ifeq ($(HOST_OS),linux)

# ... or if the if the option is already set

ifeq ($(WITH_HOST_DALVIK),)

  WITH_HOST_DALVIK := true

endif

endif


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

# Include the product definitions.

# We need to do this to translate TARGET_PRODUCT into its

# underlying TARGET_DEVICE before we start defining any rules.

#

include $(BUILD_SYSTEM)/node_fns.mk

include $(BUILD_SYSTEM)/product.mk

include $(BUILD_SYSTEM)/device.mk


ifneq ($(strip $(TARGET_BUILD_APPS)),)

# An unbundled app build needs only the core product makefiles.

all_product_configs := $(call get-product-makefiles,\

    $(SRC_TARGET_DIR)/product/AndroidProducts.mk)

else

# Read in all of the product definitions specified by the AndroidProducts.mk

# files in the tree.

all_product_configs := $(get-all-product-makefiles)

endif


# Find the product config makefile for the current product.

# all_product_configs consists items like:

# <product_name>:<path_to_the_product_makefile>

# or just <path_to_the_product_makefile> in case the product name is the

# same as the base filename of the product config makefile.

current_product_makefile :=

all_product_makefiles :=

$(foreach f, $(all_product_configs),\

    $(eval _cpm_words := $(subst :,$(space),$(f)))\

    $(eval _cpm_word1 := $(word 1,$(_cpm_words)))\

    $(eval _cpm_word2 := $(word 2,$(_cpm_words)))\

    $(if $(_cpm_word2),\

        $(eval all_product_makefiles += $(_cpm_word2))\

        $(if $(filter $(TARGET_PRODUCT),$(_cpm_word1)),\

            $(eval current_product_makefile += $(_cpm_word2)),),\

        $(eval all_product_makefiles += $(f))\

        $(if $(filter $(TARGET_PRODUCT),$(basename $(notdir $(f)))),\

            $(eval current_product_makefile += $(f)),)))

_cpm_words :=

_cpm_word1 :=

_cpm_word2 :=

current_product_makefile := $(strip $(current_product_makefile))

all_product_makefiles := $(strip $(all_product_makefiles))


ifneq (,$(filter product-graph dump-products, $(MAKECMDGOALS)))

# Import all product makefiles.

$(call import-products, $(all_product_makefiles))

else

# Import just the current product.

ifndef current_product_makefile

$(error Can not locate config makefile for product "$(TARGET_PRODUCT)")

endif

ifneq (1,$(words $(current_product_makefile)))

$(error Product "$(TARGET_PRODUCT)" ambiguous: matches $(current_product_makefile))

endif

$(call import-products, $(current_product_makefile))

endif  # Import all or just the current product makefile


# Sanity check

$(check-all-products)


ifneq ($(filter dump-products, $(MAKECMDGOALS)),)

$(dump-products)

$(error done)

endif


# Convert a short name like "sooner" into the path to the product

# file defining that product.

#

INTERNAL_PRODUCT := $(call resolve-short-product-name, $(TARGET_PRODUCT))

ifneq ($(current_product_makefile),$(INTERNAL_PRODUCT))

$(error PRODUCT_NAME inconsistent in $(current_product_makefile) and $(INTERNAL_PRODUCT))

endif

current_product_makefile :=

all_product_makefiles :=

all_product_configs :=



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

# TODO: Remove this hack once only 1 runtime is left.

# Include the runtime product makefile based on the product's PRODUCT_RUNTIMES

$(call clear-var-list, $(_product_var_list))


# Set PRODUCT_RUNTIMES, allowing buildspec to override using OVERRIDE_RUNTIMES

product_runtimes := $(sort $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_RUNTIMES))

ifneq ($(OVERRIDE_RUNTIMES),)

  $(info Overriding PRODUCT_RUNTIMES=$(product_runtimes) with $(OVERRIDE_RUNTIMES))

  product_runtimes := $(OVERRIDE_RUNTIMES)

endif

$(foreach runtime, $(product_runtimes), $(eval include $(SRC_TARGET_DIR)/product/$(runtime).mk))

$(foreach v, $(_product_var_list), $(if $($(v)),\

    $(eval PRODUCTS.$(INTERNAL_PRODUCT).$(v) += $(sort $($(v))))))


$(call clear-var-list, $(_product_var_list))

# Now we can assign to PRODUCT_RUNTIMES

PRODUCT_RUNTIMES := $(product_runtimes)

product_runtimes :=

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


# A list of module names of BOOTCLASSPATH (jar files)

PRODUCT_BOOT_JARS := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BOOT_JARS)


# Find the device that this product maps to.

TARGET_DEVICE := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE)


# Figure out which resoure configuration options to use for this

# product.

PRODUCT_LOCALES := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_LOCALES))

# TODO: also keep track of things like "port", "land" in product files.


# If CUSTOM_LOCALES contains any locales not already included

# in PRODUCT_LOCALES, add them to PRODUCT_LOCALES.

extra_locales := $(filter-out $(PRODUCT_LOCALES),$(CUSTOM_LOCALES))

ifneq (,$(extra_locales))

  ifneq ($(CALLED_FROM_SETUP),true)

    # Don't spam stdout, because envsetup.sh may be scraping values from it.

    $(info Adding CUSTOM_LOCALES [$(extra_locales)] to PRODUCT_LOCALES [$(PRODUCT_LOCALES)])

  endif

  PRODUCT_LOCALES += $(extra_locales)

  extra_locales :=

endif


# Add PRODUCT_LOCALES to PRODUCT_AAPT_CONFIG

PRODUCT_AAPT_CONFIG := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_CONFIG))

PRODUCT_AAPT_CONFIG := $(PRODUCT_LOCALES) $(PRODUCT_AAPT_CONFIG)

PRODUCT_AAPT_PREF_CONFIG := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_PREF_CONFIG))


# Default to medium-density assets.

# (Can be overridden in the device config, e.g.: PRODUCT_AAPT_CONFIG += hdpi)

PRODUCT_AAPT_CONFIG := $(strip \

    $(PRODUCT_AAPT_CONFIG) \

    $(if $(filter %dpi,$(PRODUCT_AAPT_CONFIG)),,mdpi))

PRODUCT_AAPT_PREF_CONFIG := $(strip $(PRODUCT_AAPT_PREF_CONFIG))


# Everyone gets nodpi assets which are density-independent.

PRODUCT_AAPT_CONFIG += nodpi


# Convert spaces to commas.

comma := ,

PRODUCT_AAPT_CONFIG := \

    $(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_CONFIG)))

PRODUCT_AAPT_PREF_CONFIG := \

    $(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_PREF_CONFIG)))


PRODUCT_BRAND := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BRAND))


PRODUCT_MODEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MODEL))

ifndef PRODUCT_MODEL

  PRODUCT_MODEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_NAME))

endif


PRODUCT_MANUFACTURER := \

    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MANUFACTURER))

ifndef PRODUCT_MANUFACTURER

  PRODUCT_MANUFACTURER := unknown

endif


BUILD_NUMBER := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).BUILD_NUMBER))

INTERNAL_VERSION := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).INTERNAL_VERSION))

HARDWARE_VERSION := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).HARDWARE_VERSION))

ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHARACTERISTICS),)

  TARGET_AAPT_CHARACTERISTICS := default

else

  TARGET_AAPT_CHARACTERISTICS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHARACTERISTICS))

endif


PRODUCT_DEFAULT_WIFI_CHANNELS := \

    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_WIFI_CHANNELS))


PRODUCT_DEFAULT_DEV_CERTIFICATE := \

    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_DEV_CERTIFICATE))

ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE

ifneq (1,$(words $(PRODUCT_DEFAULT_DEV_CERTIFICATE)))

    $(error PRODUCT_DEFAULT_DEV_CERTIFICATE='$(PRODUCT_DEFAULT_DEV_CERTIFICATE)', \

      only 1 certificate is allowed.)

endif

endif


# A list of words like <source path>:<destination path>[:<owner>].

# The file at the source path should be copied to the destination path

# when building  this product.  <destination path> is relative to

# $(PRODUCT_OUT), so it should look like, e.g., "system/etc/file.xml".

# The rules for these copy steps are defined in build/core/Makefile.

# The optional :<owner> is used to indicate the owner of a vendor file.

PRODUCT_COPY_FILES := \

    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_COPY_FILES))


# A list of property assignments, like "key = value", with zero or more

# whitespace characters on either side of the '='.

PRODUCT_PROPERTY_OVERRIDES := \

    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PROPERTY_OVERRIDES))


# A list of property assignments, like "key = value", with zero or more

# whitespace characters on either side of the '='.

# used for adding properties to default.prop

PRODUCT_DEFAULT_PROPERTY_OVERRIDES := \

    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_PROPERTY_OVERRIDES))


# Should we use the default resources or add any product specific overlays

PRODUCT_PACKAGE_OVERLAYS := \

    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGE_OVERLAYS))

DEVICE_PACKAGE_OVERLAYS := \

        $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).DEVICE_PACKAGE_OVERLAYS))


# An list of whitespace-separated words.

PRODUCT_TAGS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_TAGS))


# The list of product-specific kernel header dirs

PRODUCT_VENDOR_KERNEL_HEADERS := \

    $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_KERNEL_HEADERS)


# Add the product-defined properties to the build properties.

ADDITIONAL_BUILD_PROPERTIES := \

    $(ADDITIONAL_BUILD_PROPERTIES) \

    $(PRODUCT_PROPERTY_OVERRIDES)


# The OTA key(s) specified by the product config, if any.  The names

# of these keys are stored in the target-files zip so that post-build

# signing tools can substitute them for the test key embedded by

# default.

PRODUCT_OTA_PUBLIC_KEYS := $(sort \

    $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OTA_PUBLIC_KEYS))


PRODUCT_EXTRA_RECOVERY_KEYS := $(sort \

    $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_EXTRA_RECOVERY_KEYS))


---------------------------------------------------------------------------------------------------------------------------------------------------------------

node_fns.mk


定义了一些命令。这些命令在product.mk,device.mk,和product_config.mk中会使用。这里重点说明import-nodes。

import-nodes需要3个入口参数:
$(1)是一个字串,是输出变量的主干名。例如”PRODUCTS"和”DEVICES“。
$(2)是一个makefile文件列表,这些文件中应该含有对$(3)中变量的定义。
$(3)是一个变量列表。

import- nodes会创建这样形式的变量,以$(1)="PRODUCTS", $(2)中含有"build/target/product/core.mk", $(3)中含有"PRODUCT_NAME", 而且core.mk中定义了PRODUCT_NAME:=core为例,
PRODUCT.build/target/product/core.mk.PRODUCT_NAME:=core

import- nodes中还考虑了inherit的问题,如果某个PRODUCTS.XXX变量的值中有‘@inherit:<mk文件>’标识后面跟着 mk文件名的字串,则会把那个mk文件中相应的变量的属性添加到PRODUCTS.XXX中。'@inherit:<mk文件>'是 inherit-product命令添加的。参见product.mk。

在product_config.mk中会说明$(2)中的mk文件列表是AndroidProducts.mk中的PRODUCT_MAKEFILES定义的。

node_fns.mk的代码真的很杀伤脑细胞...

在build/core/

#

# Copyright (C) 2007 The Android Open Source Project

#

# Licensed under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at

#

#      http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

#


#

# Clears a list of variables using ":=".

#

# E.g.,

#   $(call clear-var-list,A B C)

# would be the same as:

#   A :=

#   B :=

#   C :=

#

# $(1): list of variable names to clear

#

define clear-var-list

$(foreach v,$(1),$(eval $(v):=))

endef


#

# Copies a list of variables into another list of variables.

# The target list is the same as the source list, but has

# a dotted prefix affixed to it.

#

# E.g.,

#   $(call copy-var-list, PREFIX, A B)

# would be the same as:

#   PREFIX.A := $(A)

#   PREFIX.B := $(B)

#

# $(1): destination prefix

# $(2): list of variable names to copy

#

define copy-var-list

$(foreach v,$(2),$(eval $(strip $(1)).$(v):=$($(v))))

endef


#

# Moves a list of variables into another list of variables.

# The variable names differ by a prefix.  After moving, the

# source variable is cleared.

#

# NOTE: Spaces are not allowed around the prefixes.

#

# E.g.,

#   $(call move-var-list,SRC,DST,A B)

# would be the same as:

#   DST.A := $(SRC.A)

#   SRC.A :=

#   DST.B := $(SRC.B)

#   SRC.B :=

#

# $(1): source prefix

# $(2): destination prefix

# $(3): list of variable names to move

#

define move-var-list

$(foreach v,$(3), \

  $(eval $(2).$(v) := $($(1).$(v))) \

  $(eval $(1).$(v) :=) \

 )

endef


#

# $(1): haystack

# $(2): needle

#

# Guarantees that needle appears at most once in haystack,

# without changing the order of other elements in haystack.

# If needle appears multiple times, only the first occurrance

# will survive.

#

# How it works:

#

# - Stick everything in haystack into a single word,

#   with "|||" separating the words.

# - Replace occurrances of "|||$(needle)|||" with "||| |||",

#   breaking haystack back into multiple words, with spaces

#   where needle appeared.

# - Add needle between the first and second words of haystack.

# - Replace "|||" with spaces, breaking haystack back into

#   individual words.

#

define uniq-word

$(strip \

  $(if $(filter-out 0 1,$(words $(filter $(2),$(1)))), \

    $(eval h := |||$(subst $(space),|||,$(strip $(1)))|||) \

    $(eval h := $(subst |||$(strip $(2))|||,|||$(space)|||,$(h))) \

    $(eval h := $(word 1,$(h)) $(2) $(wordlist 2,9999,$(h))) \

    $(subst |||,$(space),$(h)) \

   , \

    $(1) \

 ))

endef


INHERIT_TAG := @inherit:


#

# Walks through the list of variables, each qualified by the prefix,

# and finds instances of words beginning with INHERIT_TAG.  Scrape

# off INHERIT_TAG from each matching word, and return the sorted,

# unique set of those words.

#

# E.g., given

#   PREFIX.A := A $(INHERIT_TAG)aaa B C

#   PREFIX.B := B $(INHERIT_TAG)aaa C $(INHERIT_TAG)bbb D E

# Then

#   $(call get-inherited-nodes,PREFIX,A B)

# returns

#   aaa bbb

#

# $(1): variable prefix

# $(2): list of variables to check

#

define get-inherited-nodes

$(sort \

  $(subst $(INHERIT_TAG),, \

    $(filter $(INHERIT_TAG)%, \

      $(foreach v,$(2),$($(1).$(v))) \

 )))

endef


#

# for each variable ( (prefix + name) * vars ):

#   get list of inherited words; if not empty:

#     for each inherit:

#       replace the first occurrence with (prefix + inherited + var)

#       clear the source var so we can't inherit the value twice

#

# $(1): context prefix

# $(2): name of this node

# $(3): list of variable names

#

define _expand-inherited-values

  $(foreach v,$(3), \

    $(eval ### "Shorthand for the name of the target variable") \

    $(eval _eiv_tv := $(1).$(2).$(v)) \

    $(eval ### "Get the list of nodes that this variable inherits") \

    $(eval _eiv_i := \

        $(sort \

            $(patsubst $(INHERIT_TAG)%,%, \

                $(filter $(INHERIT_TAG)%, $($(_eiv_tv)) \

     )))) \

    $(foreach i,$(_eiv_i), \

      $(eval ### "Make sure that this inherit appears only once") \

      $(eval $(_eiv_tv) := \

          $(call uniq-word,$($(_eiv_tv)),$(INHERIT_TAG)$(i))) \

      $(eval ### "Expand the inherit tag") \

      $(eval $(_eiv_tv) := \

          $(strip \

              $(patsubst $(INHERIT_TAG)$(i),$($(1).$(i).$(v)), \

                  $($(_eiv_tv))))) \

      $(eval ### "Clear the child so DAGs don't create duplicate entries" ) \

      $(eval $(1).$(i).$(v) :=) \

      $(eval ### "If we just inherited ourselves, it's a cycle.") \

      $(if $(filter $(INHERIT_TAG)$(2),$($(_eiv_tv))), \

        $(warning Cycle detected between "$(2)" and "$(i)" for context "$(1)") \

        $(error import of "$(2)" failed) \

      ) \

     ) \

   ) \

   $(eval _eiv_tv :=) \

   $(eval _eiv_i :=)

endef


#

# $(1): context prefix

# $(2): makefile representing this node

# $(3): list of node variable names

#

# _include_stack contains the list of included files, with the most recent files first.

define _import-node

  $(eval _include_stack := $(2) $$(_include_stack))

  $(call clear-var-list, $(3))

  $(eval LOCAL_PATH := $(patsubst %/,%,$(dir $(2))))

  $(eval MAKEFILE_LIST :=)

  $(eval include $(2))

  $(eval _included := $(filter-out $(2),$(MAKEFILE_LIST)))

  $(eval MAKEFILE_LIST :=)

  $(eval LOCAL_PATH :=)

  $(call copy-var-list, $(1).$(2), $(3))

  $(call clear-var-list, $(3))


  $(eval $(1).$(2).inherited := \

      $(call get-inherited-nodes,$(1).$(2),$(3)))

  $(call _import-nodes-inner,$(1),$($(1).$(2).inherited),$(3))


  $(call _expand-inherited-values,$(1),$(2),$(3))


  $(eval $(1).$(2).inherited :=)

  $(eval _include_stack := $(wordlist 2,9999,$$(_include_stack)))

endef


#

# This will generate a warning for _included above

#  $(if $(_included), \

#      $(eval $(warning product spec file: $(2)))\

#      $(foreach _inc,$(_included),$(eval $(warning $(space)$(space)$(space)includes: $(_inc)))),)

#


#

# $(1): context prefix

# $(2): list of makefiles representing nodes to import

# $(3): list of node variable names

#

#TODO: Make the "does not exist" message more helpful;

#      should print out the name of the file trying to include it.

define _import-nodes-inner

  $(foreach _in,$(2), \

    $(if $(wildcard $(_in)), \

      $(if $($(1).$(_in).seen), \

        $(eval ### "skipping already-imported $(_in)") \

       , \

        $(eval $(1).$(_in).seen := true) \

        $(call _import-node,$(1),$(strip $(_in)),$(3)) \

       ) \

     , \

      $(error $(1): "$(_in)" does not exist) \

     ) \

   )

endef


#

# $(1): output list variable name, like "PRODUCTS" or "DEVICES"

# $(2): list of makefiles representing nodes to import

# $(3): list of node variable names

#

define import-nodes

$(if \

  $(foreach _in,$(2), \

    $(eval _node_import_context := _nic.$(1).[[$(_in)]]) \

    $(if $(_include_stack),$(eval $(error ASSERTION FAILED: _include_stack \

                should be empty here: $(_include_stack))),) \

    $(eval _include_stack := ) \

    $(call _import-nodes-inner,$(_node_import_context),$(_in),$(3)) \

    $(call move-var-list,$(_node_import_context).$(_in),$(1).$(_in),$(3)) \

    $(eval _node_import_context :=) \

    $(eval $(1) := $($(1)) $(_in)) \

    $(if $(_include_stack),$(eval $(error ASSERTION FAILED: _include_stack \

                should be empty here: $(_include_stack))),) \

   ) \

,)

endef


---------------------------------------------------------------------------------------------------------------------------------------------

product.mk


product.mk构造了一些命令,供product_config.mk中使用。

_find-android-products-files这个命令会得到device/和vendor/, 包括子目录,以及build/target/product/下的AndroidProducts.mk文件列表。

get-all-product-makefiles这个命令会得到所有$(_find-android-products-files)的AndroidProducts.mk文件中PRODUCT_MAKEFILES变量定义的mk文件。

_product_var_list对应的是import-nodes命令的$(3), 定义了会生成那些PRODUCT属性名的变量。这些变量实际也是在product的mk文件中要考虑定义的。
_product_var_list := \
    PRODUCT_NAME \
    PRODUCT_MODEL \
    PRODUCT_LOCALES \
    PRODUCT_PACKAGES \
    PRODUCT_DEVICE \
    PRODUCT_MANUFACTURER \
    PRODUCT_BRAND \
    PRODUCT_PROPERTY_OVERRIDES \
    PRODUCT_COPY_FILES \
    PRODUCT_OTA_PUBLIC_KEYS \
    PRODUCT_POLICY \
    PRODUCT_PACKAGE_OVERLAYS \
    DEVICE_PACKAGE_OVERLAYS \
    PRODUCT_CONTRIBUTORS_FILE \
    PRODUCT_TAGS \
    PRODUCT_SDK_ADDON_NAME \
    PRODUCT_SDK_ADDON_COPY_FILES \
    PRODUCT_SDK_ADDON_COPY_MODULES \
    PRODUCT_SDK_ADDON_DOC_MODULE \
    PRODUCT_DEFAULT_WIFI_CHANNELS

import-products会调用import-nodes。product_config.mk中用到。
define import-products
$(call import-nodes,PRODUCTS,$(1),$(_product_var_list))
endef

inherit-product命令则将在所有的PRODUCT.xxx变量值中后缀上'@inherit:<mk文件>',当import-nodes处理时,会替换成继承的属性。

check-all-products命令借助$(PRODUCTS)诸变量,会对product进行唯一性检查和PRODUCT_NAME,PRODUCT_BRAND,PRODCUT_COPY_FILES的简单检查。

resolve-short-product-name命令,给定Product的短名,返回对应mk的路径



#

# Copyright (C) 2007 The Android Open Source Project

#

# Licensed under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at

#

#      http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

#


#

# Functions for including AndroidProducts.mk files

# PRODUCT_MAKEFILES is set up in AndroidProducts.mks.

# Format of PRODUCT_MAKEFILES:

# <product_name>:<path_to_the_product_makefile>

# If the <product_name> is the same as the base file name (without dir

# and the .mk suffix) of the product makefile, "<product_name>:" can be

# omitted.


#

# Returns the list of all AndroidProducts.mk files.

# $(call ) isn't necessary.

#

define _find-android-products-files

$(shell test -d device && find device -maxdepth 6 -name AndroidProducts.mk) \

  $(shell test -d vendor && find vendor -maxdepth 6 -name AndroidProducts.mk) \

  $(SRC_TARGET_DIR)/product/AndroidProducts.mk

endef


#

# Returns the sorted concatenation of PRODUCT_MAKEFILES

# variables set in the given AndroidProducts.mk files.

# $(1): the list of AndroidProducts.mk files.

#

define get-product-makefiles

$(sort \

  $(foreach f,$(1), \

    $(eval PRODUCT_MAKEFILES :=) \

    $(eval LOCAL_DIR := $(patsubst %/,%,$(dir $(f)))) \

    $(eval include $(f)) \

    $(PRODUCT_MAKEFILES) \

   ) \

  $(eval PRODUCT_MAKEFILES :=) \

  $(eval LOCAL_DIR :=) \

 )

endef


#

# Returns the sorted concatenation of all PRODUCT_MAKEFILES

# variables set in all AndroidProducts.mk files.

# $(call ) isn't necessary.

#

define get-all-product-makefiles

$(call get-product-makefiles,$(_find-android-products-files))

endef


#

# Functions for including product makefiles

#


_product_var_list := \

    PRODUCT_NAME \

    PRODUCT_MODEL \

    PRODUCT_LOCALES \

    PRODUCT_AAPT_CONFIG \

    PRODUCT_AAPT_PREF_CONFIG \

    PRODUCT_PACKAGES \

    PRODUCT_PACKAGES_DEBUG \

    PRODUCT_PACKAGES_ENG \

    PRODUCT_PACKAGES_TESTS \

    PRODUCT_DEVICE \

    PRODUCT_MANUFACTURER \

    PRODUCT_BRAND \

    PRODUCT_PROPERTY_OVERRIDES \

    PRODUCT_DEFAULT_PROPERTY_OVERRIDES \

    PRODUCT_CHARACTERISTICS \

    PRODUCT_COPY_FILES \

    PRODUCT_OTA_PUBLIC_KEYS \

    PRODUCT_EXTRA_RECOVERY_KEYS \

    PRODUCT_PACKAGE_OVERLAYS \

    DEVICE_PACKAGE_OVERLAYS \

    PRODUCT_TAGS \

    PRODUCT_SDK_ADDON_NAME \

    PRODUCT_SDK_ADDON_COPY_FILES \

    PRODUCT_SDK_ADDON_COPY_MODULES \

    PRODUCT_SDK_ADDON_DOC_MODULES \

    PRODUCT_DEFAULT_WIFI_CHANNELS \

    PRODUCT_DEFAULT_DEV_CERTIFICATE \

    PRODUCT_RESTRICT_VENDOR_FILES \

    PRODUCT_VENDOR_KERNEL_HEADERS \

    PRODUCT_FACTORY_RAMDISK_MODULES \

    PRODUCT_FACTORY_BUNDLE_MODULES \

    PRODUCT_RUNTIMES \

    BUILD_NUMBER \

    INTERNAL_VERSION \

    HARDWARE_VERSION \

    PRODUCT_BOOT_JARS



define dump-product

$(info ==== $(1) ====)\

$(foreach v,$(_product_var_list),\

$(info PRODUCTS.$(1).$(v) := $(PRODUCTS.$(1).$(v))))\

$(info --------)

endef


define dump-products

$(foreach p,$(PRODUCTS),$(call dump-product,$(p)))

endef


#

# $(1): product to inherit

#

# Does three things:

#  1. Inherits all of the variables from $1.

#  2. Records the inheritance in the .INHERITS_FROM variable

#  3. Records that we've visited this node, in ALL_PRODUCTS

#

define inherit-product

  $(foreach v,$(_product_var_list), \

      $(eval $(v) := $($(v)) $(INHERIT_TAG)$(strip $(1)))) \

  $(eval inherit_var := \

      PRODUCTS.$(strip $(word 1,$(_include_stack))).INHERITS_FROM) \

  $(eval $(inherit_var) := $(sort $($(inherit_var)) $(strip $(1)))) \

  $(eval inherit_var:=) \

  $(eval ALL_PRODUCTS := $(sort $(ALL_PRODUCTS) $(word 1,$(_include_stack))))

endef



#

# Do inherit-product only if $(1) exists

#

define inherit-product-if-exists

  $(if $(wildcard $(1)),$(call inherit-product,$(1)),)

endef


#

# $(1): product makefile list

#

#TODO: check to make sure that products have all the necessary vars defined

define import-products

$(call import-nodes,PRODUCTS,$(1),$(_product_var_list))

endef



#

# Does various consistency checks on all of the known products.

# Takes no parameters, so $(call ) is not necessary.

#

define check-all-products

$(if ,, \

  $(eval _cap_names :=) \

  $(foreach p,$(PRODUCTS), \

    $(eval pn := $(strip $(PRODUCTS.$(p).PRODUCT_NAME))) \

    $(if $(pn),,$(error $(p): PRODUCT_NAME must be defined.)) \

    $(if $(filter $(pn),$(_cap_names)), \

      $(error $(p): PRODUCT_NAME must be unique; "$(pn)" already used by $(strip \

          $(foreach \

            pp,$(PRODUCTS),

              $(if $(filter $(pn),$(PRODUCTS.$(pp).PRODUCT_NAME)), \

                $(pp) \

               ))) \

       ) \

     ) \

    $(eval _cap_names += $(pn)) \

    $(if $(call is-c-identifier,$(pn)),, \

      $(error $(p): PRODUCT_NAME must be a valid C identifier, not "$(pn)") \

     ) \

    $(eval pb := $(strip $(PRODUCTS.$(p).PRODUCT_BRAND))) \

    $(if $(pb),,$(error $(p): PRODUCT_BRAND must be defined.)) \

    $(foreach cf,$(strip $(PRODUCTS.$(p).PRODUCT_COPY_FILES)), \

      $(if $(filter 2 3,$(words $(subst :,$(space),$(cf)))),, \

        $(error $(p): malformed COPY_FILE "$(cf)") \

       ) \

     ) \

   ) \

)

endef



#

# Returns the product makefile path for the product with the provided name

#

# $(1): short product name like "generic"

#

define _resolve-short-product-name

  $(eval pn := $(strip $(1)))

  $(eval p := \

      $(foreach p,$(PRODUCTS), \

          $(if $(filter $(pn),$(PRODUCTS.$(p).PRODUCT_NAME)), \

            $(p) \

       )) \

   )

  $(eval p := $(sort $(p)))

  $(if $(filter 1,$(words $(p))), \

    $(p), \

    $(if $(filter 0,$(words $(p))), \

      $(error No matches for product "$(pn)"), \

      $(error Product "$(pn)" ambiguous: matches $(p)) \

    ) \

  )

endef

define resolve-short-product-name

$(strip $(call _resolve-short-product-name,$(1)))

endef



_product_stash_var_list := $(_product_var_list) \

PRODUCT_BOOTCLASSPATH \

TARGET_ARCH \

TARGET_ARCH_VARIANT \

TARGET_CPU_VARIANT \

TARGET_BOARD_PLATFORM \

TARGET_BOARD_PLATFORM_GPU \

TARGET_BOARD_KERNEL_HEADERS \

TARGET_DEVICE_KERNEL_HEADERS \

TARGET_PRODUCT_KERNEL_HEADERS \

TARGET_BOOTLOADER_BOARD_NAME \

TARGET_COMPRESS_MODULE_SYMBOLS \

TARGET_NO_BOOTLOADER \

TARGET_NO_KERNEL \

TARGET_NO_RECOVERY \

TARGET_NO_RADIOIMAGE \

TARGET_HARDWARE_3D \

TARGET_PROVIDES_INIT_RC \

TARGET_CPU_ABI \

TARGET_CPU_ABI2 \

TARGET_CPU_SMP \



_product_stash_var_list += \

BOARD_WPA_SUPPLICANT_DRIVER \

BOARD_WLAN_DEVICE \

BOARD_USES_GENERIC_AUDIO \

BOARD_KERNEL_CMDLINE \

BOARD_KERNEL_BASE \

BOARD_HAVE_BLUETOOTH \

BOARD_VENDOR_USE_AKMD \

BOARD_EGL_CFG \

BOARD_BOOTIMAGE_PARTITION_SIZE \

BOARD_RECOVERYIMAGE_PARTITION_SIZE \

BOARD_SYSTEMIMAGE_PARTITION_SIZE \

BOARD_USERDATAIMAGE_PARTITION_SIZE \

BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE \

BOARD_CACHEIMAGE_PARTITION_SIZE \

BOARD_PRODNVIMAGE_FILE_SYSTEM_TYPE \

BOARD_PRODNVIMAGE_PARTITION_SIZE \

BOARD_FLASH_BLOCK_SIZE \

BOARD_SYSTEMIMAGE_PARTITION_SIZE \

BOARD_INSTALLER_CMDLINE \



_product_stash_var_list += \

DEFAULT_SYSTEM_DEV_CERTIFICATE


#

# Stash vaues of the variables in _product_stash_var_list.

# $(1): Renamed prefix

#

define stash-product-vars

$(foreach v,$(_product_stash_var_list), \

        $(eval $(strip $(1))_$(call rot13,$(v)):=$$($$(v))) \

 )

endef


#

# Assert that the the variable stashed by stash-product-vars remains untouched.

# $(1): The prefix as supplied to stash-product-vars

#

define assert-product-vars

$(strip \

  $(eval changed_variables:=)

  $(foreach v,$(_product_stash_var_list), \

    $(if $(call streq,$($(v)),$($(strip $(1))_$(call rot13,$(v)))),, \

        $(eval $(warning $(v) has been modified: $($(v)))) \

        $(eval $(warning previous value: $($(strip $(1))_$(call rot13,$(v))))) \

        $(eval changed_variables := $(changed_variables) $(v))) \

   ) \

  $(if $(changed_variables),\

    $(eval $(error The following variables have been changed: $(changed_variables))),)

)

endef


define add-to-product-copy-files-if-exists

$(if $(wildcard $(word 1,$(subst :, ,$(1)))),$(1))

endef


-------------------------------------------------------------------------------------------------------------------------------------------

device.mk


同product.mk类似,device.mk构造了一些命令。有resolve-short-device-name,和import-devices。

在build/core/

#

# Copyright (C) 2007 The Android Open Source Project

#

# Licensed under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at

#

#      http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

#


_device_var_list := \

    DEVICE_NAME \

    DEVICE_BOARD \

    DEVICE_REGION


define dump-device

$(info ==== $(1) ====)\

$(foreach v,$(_device_var_list),\

$(info DEVICES.$(1).$(v) := $(DEVICES.$(1).$(v))))\

$(info --------)

endef


define dump-devices

$(foreach p,$(DEVICES),$(call dump-device,$(p)))

endef


#

# $(1): device to inherit

#

define inherit-device

  $(foreach v,$(_device_var_list), \

      $(eval $(v) := $($(v)) $(INHERIT_TAG)$(strip $(1))))

endef


#

# $(1): device makefile list

#

#TODO: check to make sure that devices have all the necessary vars defined

define import-devices

$(call import-nodes,DEVICES,$(1),$(_device_var_list))

endef



#

# $(1): short device name like "sooner"

#

define _resolve-short-device-name

  $(eval dn := $(strip $(1)))

  $(eval d := \

      $(foreach d,$(DEVICES), \

          $(if $(filter $(dn),$(DEVICES.$(d).DEVICE_NAME)), \

            $(d) \

       )) \

   )

  $(eval d := $(sort $(d)))

  $(if $(filter 1,$(words $(d))), \

    $(d), \

    $(if $(filter 0,$(words $(d))), \

      $(error No matches for device "$(dn)"), \

      $(error Device "$(dn)" ambiguous: matches $(d)) \

    ) \

  )

endef


#

# $(1): short device name like "sooner"

#

define resolve-short-device-name

$(strip $(call _resolve-short-device-name,$(1)))

endef

---------------------------------------------------------------------------------------------------------------------

envsetup.mk


envsetup.mk分析:

# Variables we check:

#     HOST_BUILD_TYPE = { release debug }

#     TARGET_BUILD_TYPE = { release debug }

# and we output a bunch of variables, see the case statement at

# the bottom for the full list

#     OUT_DIR is also set to "out" if it's not already set.

#         this allows you to set it to somewhere else if you like


# Set up version information.

#首先包含进version_defaults.mk,定义好一些版本相关的变量。请看文件version_defaults.mk

include $(BUILD_SYSTEM)/version_defaults.mk


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

# If you update the build system such that the environment setup

# or buildspec.mk need to be updated, increment this number, and

# people who haven't re-run those will have to do so before they

# can build.  Make sure to also update the corresponding value in

# buildspec.mk.default and envsetup.sh.

#定义CORRECT_BUILD_ENV_SEQUENCE_NUMBER,这个数字用于buildspec.mk更新时的提醒,应该同buildspec.mk中的或环境变量中的BUILD_ENV_SEQUENCE_NUMBER相等。一般不用关注

CORRECT_BUILD_ENV_SEQUENCE_NUMBER := 10


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

# The product defaults to generic on hardware

# NOTE: This will be overridden in product_config.mk if make

# was invoked with a PRODUCT-xxx-yyy goal.

#随后检查TARGET_PRODUCT,若为空,则置generic。TARGET_PRODUCT应当在buildspec.mk或环境变量中已经定义好

ifeq ($(TARGET_PRODUCT),)

TARGET_PRODUCT := full

endif



# the variant -- the set of files that are included for a build

#再检查TARGET_BUILD_VARIANT,若为空,则置eng。TARGET_BUILD_VARIANT应当在buildspec.mk或环境变量中已经定义好

ifeq ($(strip $(TARGET_BUILD_VARIANT)),)

TARGET_BUILD_VARIANT := eng

endif


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

# Set up configuration for host machine.  We don't do cross-

# compiles except for arm/mips, so the HOST is whatever we are

# running on


UNAME := $(shell uname -sm)


# HOST_OS

ifneq (,$(findstring Linux,$(UNAME)))

HOST_OS := linux

endif

ifneq (,$(findstring Darwin,$(UNAME)))

HOST_OS := darwin

endif

ifneq (,$(findstring Macintosh,$(UNAME)))

HOST_OS := darwin

endif

ifneq (,$(findstring CYGWIN,$(UNAME)))

HOST_OS := windows

endif


# BUILD_OS is the real host doing the build.

BUILD_OS := $(HOST_OS)


# Under Linux, if USE_MINGW is set, we change HOST_OS to Windows to build the

# Windows SDK. Only a subset of tools and SDK will manage to build properly.

ifeq ($(HOST_OS),linux)

ifneq ($(USE_MINGW),)

HOST_OS := windows

endif

endif


ifeq ($(HOST_OS),)

$(error Unable to determine HOST_OS from uname -sm: $(UNAME)!)

endif



# HOST_ARCH

ifneq (,$(findstring 86,$(UNAME)))

HOST_ARCH := x86

endif


ifneq (,$(findstring Power,$(UNAME)))

HOST_ARCH := ppc

endif


BUILD_ARCH := $(HOST_ARCH)


ifeq ($(HOST_ARCH),)

$(error Unable to determine HOST_ARCH from uname -sm: $(UNAME)!)

endif


# the host build defaults to release, and it must be release or debug

ifeq ($(HOST_BUILD_TYPE),)

HOST_BUILD_TYPE := release

endif


ifneq ($(HOST_BUILD_TYPE),release)

ifneq ($(HOST_BUILD_TYPE),debug)

$(error HOST_BUILD_TYPE must be either release or debug, not '$(HOST_BUILD_TYPE)')

endif

endif


# This is the standard way to name a directory containing prebuilt host

# objects. E.g., prebuilt/$(HOST_PREBUILT_TAG)/cc

ifeq ($(HOST_OS),windows)

  HOST_PREBUILT_TAG := windows

else

  HOST_PREBUILT_TAG := $(HOST_OS)-$(HOST_ARCH)

endif


# TARGET_COPY_OUT_* are all relative to the staging directory, ie PRODUCT_OUT.

# Define them here so they can be used in product config files.

TARGET_COPY_OUT_SYSTEM := system

TARGET_COPY_OUT_DATA := data

TARGET_COPY_OUT_VENDOR := system/vendor

TARGET_COPY_OUT_ROOT := root

TARGET_COPY_OUT_RECOVERY := recovery


# Read the product specs so we an get TARGET_DEVICE and other

# variables that we need in order to locate the output files.

#然后包含进product_config.mk

include $(BUILD_SYSTEM)/product_config.mk


#接着,检查$(TARGET_BUILD_VARIANT),取值范围是eng user userdebug tests。

build_variant := $(filter-out eng user userdebug,$(TARGET_BUILD_VARIANT))

ifneq ($(build_variant)-$(words $(TARGET_BUILD_VARIANT)),-1)

$(warning bad TARGET_BUILD_VARIANT: $(TARGET_BUILD_VARIANT))

$(error must be empty or one of: eng user userdebug)

endif


#随后判定HOST_OS(linux),HOST_ARCH(x86)

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

# Set up configuration for target machine.

# The following must be set:

#接着,确定TARGET_ARCH和TARGET_OS,若没有定义,则取默认值。
#TARGET_ARCH := arm
#TARGET_OS := linux

TARGET_OS = { linux }

TARGET_ARCH = { arm | x86 | mips }


TARGET_OS := linux

# TARGET_ARCH should be set by BoardConfig.mk and will be checked later


# the target build type defaults to release

#接着,确定TARGET_BUILD_TYPE,若没有定义,则取默认值。
#TARGET_BUILD_TYPE := release

ifneq ($(TARGET_BUILD_TYPE),debug)

TARGET_BUILD_TYPE := release

endif


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

# figure out the output directories

#接着,确定OUT_DIR。OUT_DIR是存放中间文件和最终结果的地方。若没有定义,则取默认值。
#OUT_DIR := $(TOPDIR)out

ifeq (,$(strip $(OUT_DIR)))

ifeq (,$(strip $(OUT_DIR_COMMON_BASE)))

OUT_DIR := $(TOPDIR)out

else

OUT_DIR := $(OUT_DIR_COMMON_BASE)/$(notdir $(PWD))

endif

endif


DEBUG_OUT_DIR := $(OUT_DIR)/debug

#随后,定义了一些列的路径变量
DEBUG_OUT_DIR,TARGET_OUT_ROOT_release,TARGET_OUT_ROOT_debug,TARGET_OUT_ROOT,BUILD_OUT,PRODUCT_OUT,TARGET_COMMON_OUT_ROOT,等等。

# Move the host or target under the debug/ directory

# if necessary.

TARGET_OUT_ROOT_release := $(OUT_DIR)/target

TARGET_OUT_ROOT_debug := $(DEBUG_OUT_DIR)/target

TARGET_OUT_ROOT := $(TARGET_OUT_ROOT_$(TARGET_BUILD_TYPE))


HOST_OUT_ROOT_release := $(OUT_DIR)/host

HOST_OUT_ROOT_debug := $(DEBUG_OUT_DIR)/host

HOST_OUT_ROOT := $(HOST_OUT_ROOT_$(HOST_BUILD_TYPE))


HOST_OUT_release := $(HOST_OUT_ROOT_release)/$(HOST_OS)-$(HOST_ARCH)

HOST_OUT_debug := $(HOST_OUT_ROOT_debug)/$(HOST_OS)-$(HOST_ARCH)

HOST_OUT := $(HOST_OUT_$(HOST_BUILD_TYPE))


BUILD_OUT := $(OUT_DIR)/host/$(BUILD_OS)-$(BUILD_ARCH)


TARGET_PRODUCT_OUT_ROOT := $(TARGET_OUT_ROOT)/product


TARGET_COMMON_OUT_ROOT := $(TARGET_OUT_ROOT)/common

HOST_COMMON_OUT_ROOT := $(HOST_OUT_ROOT)/common


PRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE)


OUT_DOCS := $(TARGET_COMMON_OUT_ROOT)/docs


BUILD_OUT_EXECUTABLES:= $(BUILD_OUT)/bin


HOST_OUT_EXECUTABLES:= $(HOST_OUT)/bin

HOST_OUT_SHARED_LIBRARIES:= $(HOST_OUT)/lib

HOST_OUT_JAVA_LIBRARIES:= $(HOST_OUT)/framework

HOST_OUT_SDK_ADDON := $(HOST_OUT)/sdk_addon


HOST_OUT_INTERMEDIATES := $(HOST_OUT)/obj

HOST_OUT_HEADERS:= $(HOST_OUT_INTERMEDIATES)/include

HOST_OUT_INTERMEDIATE_LIBRARIES := $(HOST_OUT_INTERMEDIATES)/lib

HOST_OUT_NOTICE_FILES:=$(HOST_OUT_INTERMEDIATES)/NOTICE_FILES

HOST_OUT_COMMON_INTERMEDIATES := $(HOST_COMMON_OUT_ROOT)/obj


TARGET_OUT_INTERMEDIATES := $(PRODUCT_OUT)/obj

TARGET_OUT_HEADERS:= $(TARGET_OUT_INTERMEDIATES)/include

TARGET_OUT_INTERMEDIATE_LIBRARIES := $(TARGET_OUT_INTERMEDIATES)/lib

TARGET_OUT_COMMON_INTERMEDIATES := $(TARGET_COMMON_OUT_ROOT)/obj


TARGET_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM)

TARGET_OUT_EXECUTABLES:= $(TARGET_OUT)/bin

TARGET_OUT_OPTIONAL_EXECUTABLES:= $(TARGET_OUT)/xbin

TARGET_OUT_SHARED_LIBRARIES:= $(TARGET_OUT)/lib

TARGET_OUT_JAVA_LIBRARIES:= $(TARGET_OUT)/framework

TARGET_OUT_APPS:= $(TARGET_OUT)/app

TARGET_OUT_APPS_PRIVILEGED := $(TARGET_OUT)/priv-app

TARGET_OUT_KEYLAYOUT := $(TARGET_OUT)/usr/keylayout

TARGET_OUT_KEYCHARS := $(TARGET_OUT)/usr/keychars

TARGET_OUT_ETC := $(TARGET_OUT)/etc

TARGET_OUT_NOTICE_FILES:=$(TARGET_OUT_INTERMEDIATES)/NOTICE_FILES

TARGET_OUT_FAKE := $(PRODUCT_OUT)/fake_packages


TARGET_OUT_DATA := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_DATA)

TARGET_OUT_DATA_EXECUTABLES:= $(TARGET_OUT_EXECUTABLES)

TARGET_OUT_DATA_SHARED_LIBRARIES:= $(TARGET_OUT_SHARED_LIBRARIES)

TARGET_OUT_DATA_JAVA_LIBRARIES:= $(TARGET_OUT_DATA)/framework

TARGET_OUT_DATA_APPS:= $(TARGET_OUT_DATA)/app

TARGET_OUT_DATA_KEYLAYOUT := $(TARGET_OUT_KEYLAYOUT)

TARGET_OUT_DATA_KEYCHARS := $(TARGET_OUT_KEYCHARS)

TARGET_OUT_DATA_ETC := $(TARGET_OUT_ETC)

TARGET_OUT_DATA_NATIVE_TESTS := $(TARGET_OUT_DATA)/nativetest

TARGET_OUT_DATA_FAKE := $(TARGET_OUT_DATA)/fake_packages


TARGET_OUT_CACHE := $(PRODUCT_OUT)/cache

TARGET_OUT_PRODUCT := $(PRODUCT_OUT)/prodnv


TARGET_OUT_VENDOR := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR)

TARGET_OUT_VENDOR_EXECUTABLES:= $(TARGET_OUT_VENDOR)/bin

TARGET_OUT_VENDOR_OPTIONAL_EXECUTABLES:= $(TARGET_OUT_VENDOR)/xbin

TARGET_OUT_VENDOR_SHARED_LIBRARIES:= $(TARGET_OUT_VENDOR)/lib

TARGET_OUT_VENDOR_JAVA_LIBRARIES:= $(TARGET_OUT_VENDOR)/framework

TARGET_OUT_VENDOR_APPS:= $(TARGET_OUT_VENDOR)/app

TARGET_OUT_VENDOR_ETC := $(TARGET_OUT_VENDOR)/etc


TARGET_OUT_UNSTRIPPED := $(PRODUCT_OUT)/symbols

TARGET_OUT_EXECUTABLES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/bin

TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/lib

TARGET_ROOT_OUT_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)

TARGET_ROOT_OUT_SBIN_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/sbin

TARGET_ROOT_OUT_BIN_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/bin


TARGET_ROOT_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ROOT)

TARGET_ROOT_OUT_BIN := $(TARGET_ROOT_OUT)/bin

TARGET_ROOT_OUT_SBIN := $(TARGET_ROOT_OUT)/sbin

TARGET_ROOT_OUT_ETC := $(TARGET_ROOT_OUT)/etc

TARGET_ROOT_OUT_USR := $(TARGET_ROOT_OUT)/usr


TARGET_RECOVERY_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_RECOVERY)

TARGET_RECOVERY_ROOT_OUT := $(TARGET_RECOVERY_OUT)/root


TARGET_SYSLOADER_OUT := $(PRODUCT_OUT)/sysloader

TARGET_SYSLOADER_ROOT_OUT := $(TARGET_SYSLOADER_OUT)/root

TARGET_SYSLOADER_SYSTEM_OUT := $(TARGET_SYSLOADER_OUT)/root/system


TARGET_INSTALLER_OUT := $(PRODUCT_OUT)/installer

TARGET_INSTALLER_DATA_OUT := $(TARGET_INSTALLER_OUT)/data

TARGET_INSTALLER_ROOT_OUT := $(TARGET_INSTALLER_OUT)/root

TARGET_INSTALLER_SYSTEM_OUT := $(TARGET_INSTALLER_OUT)/root/system


TARGET_FACTORY_RAMDISK_OUT := $(PRODUCT_OUT)/factory_ramdisk


COMMON_MODULE_CLASSES := TARGET-NOTICE_FILES HOST-NOTICE_FILES HOST-JAVA_LIBRARIES


ifeq (,$(strip $(DIST_DIR)))

  DIST_DIR := $(OUT_DIR)/dist

endif


ifeq ($(PRINT_BUILD_CONFIG),)

PRINT_BUILD_CONFIG := true

endif

--------------------------------------------------------------




  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值