Android 编译
1、Android 内核编译
/项目/ap/
source build/envsetup.sh
lunch msm8953-userdebug
make update-api
make / make -j32 2>&1 |tee xxx.log
1、将envsetup.sh里的所有用到的命令加载到环境变量里
2、envsetup.sh里有很多命令,其主要作用如下:
- 加载了编译时使用到的函数命令,如:help,lunch,m,mm,mmm等
- 添加了两个编译选项:generic-eng和simulator,这两个选项是系统默认选项
- 查找vendor/<-厂商目录>/和vendor/<厂商目录>/build/目录下的vendorsetup.sh,如果存在的话,加载执行它,添加厂商自己定义产品的编译选项
3、lunch命令是envsetup.sh里定义的一个命令,用来让用户选择编译项,来定义Product和编译过程中用到的全局变量
4、更新api,上层更新后会更新
5、编译整个内核或者某部分镜像 32线程 错误输出重定向到标准输出 输出 到xxx.log
2、Android app编译
/项目/ap/vendor/
1、新建目录,里面放入测试的源文件和一个Android.mk文件
2、到目录下使用 `mm` 命令(之前需source、lunch)
3、Android 编译流程
以boot.img为例
make bootimage这个命令其实是由两部分组成,make这个指令是编译器定义的指令,bootimage的target定义在build/core/main.mk中,main.mk中还包含了Makefile和其他重要的mk文件:
BUILD_SYSTEM := $(TOPDIR)build/core
...
include $(BUILD_SYSTEM)/Makefile
...
.PHONY: bootimage
bootimage: $(INSTALLED_BOOTIMAGE_TARGET)
...
INSTALLED_BOOTIMAGE_TARGET和它的依赖项就定义在Makefile中:
INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
...
$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(BOOT_SIGNER)
$(call pretty,"Target1 boot image: $@")
$(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@
$(BOOT_SIGNER) /boot $@ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).pk8 \
$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem $@
$(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE))
$(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@
是关键的编译语句,使用$(MKBOOTIMG)工具,针对INTERNAL_BOOTIMAGE_ARGS来生成 bootimage。
INTERNAL_BOOTIMAGE_ARGS这个编译的参数也是定义在Makefile中:
# the boot image, which is a collection of other images.
INTERNAL_BOOTIMAGE_ARGS := \
$(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET)) \
--kernel $(INSTALLED_KERNEL_TARGET)
ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
INTERNAL_BOOTIMAGE_ARGS += --ramdisk $(INSTALLED_RAMDISK_TARGET)
endif
INTERNAL_BOOTIMAGE_FILES := $(filter-out --%,$(INTERNAL_BOOTIMAGE_ARGS))
ifdef BOARD_KERNEL_BASE
INTERNAL_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
endif
ifdef BOARD_KERNEL_PAGESIZE
INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
endif
ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),true)
ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
VERITY_KEYID := veritykeyid=id:`openssl x509 -in $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem -text \
| grep keyid | sed 's/://g' | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]' | sed 's/keyid//g'`
endif
endif
INTERNAL_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE) buildvariant=$(TARGET_BUILD_VARIANT) $(VERITY_KEYID))
ifdef INTERNAL_KERNEL_CMDLINE
INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(INTERNAL_KERNEL_CMDLINE)"
endif
可以看到我们编译的bootimage包含了几个image:kernel、ramdisk、cmdline、pagesize。我们看其中的kernel的target为INSTALLED_KERNEL_TARGET,也定义在本文件中:
INSTALLED_KERNEL_TARGET := $(PRODUCT_OUT)/kernel
要编译INSTALLED_KERNEL_TARGET目标就要有依赖关系,此处寻找依赖关系有些复杂,首先找到相关文件,main.mk文件会搜索并include所有子目录下的Android.mk文件,因此 build/target/board/Android.mk也已经被main.mk所引用
-include $(TARGET_DEVICE_DIR)/AndroidBoard.mk //include时遇到错误也不会中断
其中TARGET_DEVICE_DIR定义在build\core\envsetup.mk
TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))
...
# Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)
# or under vendor/*/$(TARGET_DEVICE). Search in both places, but
# make sure only one exists.
# Real boards should always be associated with an OEM vendor.
board_config_mk := \
$(strip $(sort $(wildcard \
$(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
$(shell test -d device && find -L device -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
$(shell test -d vendor && find -L vendor -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
)))
上边这一段脚本会在device,vendor文件夹下寻找在当前项目名文件夹下包含的BoardConfig.mk。
而我们需要的INSTALLED_KERNEL_TARGET的依赖关系也就定义在这里
$(INSTALLED_KERNEL_TARGET): $(TARGET_PREBUILT_KERNEL) | $(ACP)
$(transform-prebuilt-to-target)
本文件中包含kernel/ANdroidKernel.mk
ifeq ($(TARGET_KERNEL_SOURCE),)
TARGET_KERNEL_SOURCE := kernel
endif
include $(TARGET_KERNEL_SOURCE)/AndroidKernel.mk
TARGET_PREBUILT_KERNE的依赖关系在之中:
TARGET_PREBUILT_KERNEL := $(TARGET_PREBUILT_INT_KERNEL)
ifeq ($(TARGET_USES_UNCOMPRESSED_KERNEL),true)
$(info Using uncompressed kernel)
TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/Image
else
ifeq ($(KERNEL_ARCH),arm64)
TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/Image.gz
else
TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/zImage
endif
AndroidKernel.mk中执行make编译命令就会调用到kernel目录下的Makefile文件
$(KERNEL_OUT):
mkdir -p $(KERNEL_OUT)
$(KERNEL_CONFIG): $(KERNEL_OUT)
$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_DEFCONFIG)
$(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \
echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_OUT)/.config; \
$(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) oldconfig; fi

浙公网安备 33010602011771号