Skip to content

Instantly share code, notes, and snippets.

@jpzhu
Last active August 29, 2015 14:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpzhu/7793ad996776f61d5f29 to your computer and use it in GitHub Desktop.
Save jpzhu/7793ad996776f61d5f29 to your computer and use it in GitHub Desktop.
build lunch

lunch脚本做了些什么

从LUNCH_MENU_CHOICES列表从选择一项产品作为编译目标

这个没有什么好介绍的,将选中的内容以“-”号部分作为分隔符,分别赋给两个变量.

前面部分叫product,也就是要编译什么

local product=$(echo -n $selection | sed -e "s/-.*$//")

后面部分叫variant,编一个什么版本

local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")

比如mini_armv7a_neon-userdebug的product=mini_armv7a_neon,而variant=userdebug。
后面会检查设置的这两个值是否合法有效。

查验合格,会将product的数值赋值給TARGET_PRODUCT和TARGET_BUILD_VARIANT

export TARGET_PRODUCT=$product
export TARGET_BUILD_VARIANT=$variant

查验product值

check_product()这一部分是lunch的精华。
它通过调用get_build_var(),进而使用make file系统去查询编译系统的配置文件。而不仅仅是简单的bash脚本。我们看 get_build_var()的实现。

# Get the exact value of a build variable.
function get_build_var()
{
    T=$(gettop)
    if [ ! "$T" ]; then
        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
        return
    fi
    (\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
      make --no-print-directory -f build/core/config.mk dumpvar-$1)
}

.mk文件会有include另外一个文件的情况,主要的工作由以下部分组成。

make系统去查找device和vendor目录下所有的AndroidProducts.mk文件.

file:build/core/product.mk

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

将找到的AndroidProducts.mk里的PRODUCT_MAKEFILES值取到一个列表里

file:build/core/product.mk

define get-product-makefiles
$(sort \
  $(foreach f,$(1), \
    $(info file: $(f)) \
    $(eval PRODUCT_MAKEFILES :=) \
    $(eval LOCAL_DIR := $(patsubst %/,%,$(dir $(f)))) \
    $(eval include $(f)) \
    $(PRODUCT_MAKEFILES) \
   ) \
  $(eval PRODUCT_MAKEFILES :=) \
  $(eval LOCAL_DIR :=) \
 )
endef

下面列一个AndroidProducts.mk文件例子 file:device/generic/armv7-a-neon/AndroidProducts.mk

PRODUCT_MAKEFILES := \
    $(LOCAL_DIR)/mini_armv7a_neon.mk

这个文件名去掉后缀不包含路径的部分,就是我们前面的product名字。

查找上一步得到的PRODUCT_MAKEFILES列表

查看该列表里是不是包含里lunch里设置的product,如果没有,则check会失败。
如果查到,则将它当作当前的current_product_makefile。会导入其中的编译环境变量。
我们看上面那个例子mini_armv7a_neon.mk里的内容。

file:device/generic/armv7-a-neon/mini_armv7a_neon.mk

$(call inherit-product, device/generic/armv7-a-neon/mini_common.mk)

PRODUCT_NAME := mini_armv7a_neon
PRODUCT_DEVICE := armv7-a-neon
PRODUCT_BRAND := Android
PRODUCT_MODEL := Mini for armv7-a-neon

# default is nosdcard, S/W button enabled in resource
DEVICE_PACKAGE_OVERLAYS := device/generic/armv7-a-neon/overlay
PRODUCT_CHARACTERISTICS := nosdcard

PRODUCT_DEVICE变量里的值很重要,会被传给TARGET_DEVICE变量。

查找$(TARGET_DEVICE)/目录下的BoardConfig.mk文件

根据前一步得到的TARGET_DEVICE,回去查找该设备的相关配置信息。查找代码在
file:build/core/envsetup.mk

board_config_mk := \
        $(strip $(wildcard \
                $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
                $(shell test -d device && find device -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
                $(shell test -d vendor && find vendor -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
        ))

也看一个例子.
file:device/generic/armv7-a-neon/BoardConfig.mk

# config.mk
#
# Product-specific compile-time definitions.
#

# The generic product target doesn't have any hardware-specific pieces.
TARGET_NO_BOOTLOADER := true
TARGET_NO_KERNEL := true

TARGET_ARCH := arm
TARGET_ARCH_VARIANT := armv7-a-neon
TARGET_CPU_VARIANT := cortex-a9
TARGET_CPU_ABI := armeabi-v7a
TARGET_CPU_ABI2 := armeabi
TARGET_CPU_SMP := true

SMALLER_FONT_FOOTPRINT := true
MINIMAL_FONT_FOOTPRINT := true
# Some framework code requires this to enable BT
BOARD_HAVE_BLUETOOTH := true
BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR := device/generic/common/bluetooth

USE_OPENGL_RENDERER := true

BOARD_USE_LEGACY_UI := true

总结

感觉这一步实现的相当罗嗦:(
这样,作为一个设备提供商要提供一个SDK开发平台,要提供以下几个文件. vendorsetup.sh AndroidProducts.mk $product.mk $product_device/BoardConfig.mk

查验variant值

variant 只检查是否为user,eng,userdebug 3个值之一。

VARIANT_CHOICES=(user userdebug eng)

设置编译(执行后续make命令)所需的环境变量

调用函数是set_stuff_for_environment(),主要是下面4部分工作

settitle

该步骤执行后,有些编辑终端上面的显示Title会发生变化,显示产品信息。

export PROMPT_COMMAND="echo -ne "\033]0;[${arch}-${product}-${variant}] ${USER}@${HOSTNAME}: ${PWD}\007""

set_java_home

设置JAVA_HOME,不过这个不影响最后Makefile中设置自己的java路径。

setpaths

配置交叉编译toolchain的路径,以及android开发环境的一些工具的路径,emulator,adb之类的所在路径,加入$PATH变量中。

set_sequence_number

设置了下面这个环境变量,暂时不知干嘛用的。

function set_sequence_number()
{
    export BUILD_ENV_SEQUENCE_NUMBER=10
}

输出编译系统配置信息

调用函数是printconfig(),也就是你最后会看到的这些信息

============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.4
TARGET_PRODUCT=mini_x86
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=x86
TARGET_ARCH_VARIANT=x86
TARGET_CPU_VARIANT=
HOST_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-3.2.0-60-generic-x86_64-with-Ubuntu-12.04-precise
HOST_BUILD_TYPE=release
BUILD_ID=KRT16S
OUT_DIR=out
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment