python—android编译中build_image.py分析

本文解析了Android编译系统中build_image.py的作用及工作原理,详细介绍了如何通过此脚本生成系统镜像,并深入分析了其核心函数及调用流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在学习python,基础知识学习了一遍。我的学习习惯是:了解了基础语法后,去阅读开源代码(掌握优秀程序员的一些写代码习惯和手法),最后结合项目实践,实践的过程对某些细节进行深化。
想起android编译系统中有一些python脚本,下面对build_image.py进行简单分析。

编译系统中调用build_image.py

生成系统镜像的target在build\core\Makefile中,

#----------build\core\Makefile-------------
# $(1): output file
define build-systemimage-target
  @echo "Target system fs image: $(1)"
  @mkdir -p $(dir $(1)) $(systemimage_intermediates) && rm -rf $(systemimage_intermediates)/system_image_info.txt
  $(call generate-userimage-prop-dictionary, $(systemimage_intermediates)/system_image_info.txt, skip_fsck=true)
  $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
      ./build/tools/releasetools/build_image.py \
      $(TARGET_OUT) $(systemimage_intermediates)/system_image_info.txt $(1)
endef

其中,可以看出来主要是借助了build_image.py去生成镜像,/build/tools/releasetools/build_image.py $(TARGET_OUT) $(systemimage_intermediates)/system_image_info.txt $(1) , 有三个参数,一个是作为输入的文件目录,system_image_info.txt,和最终生成的镜像名,例如system.img。

build_image.py分析

由于上面makefile中是在shell中直接调用build_image.py(不是import 模块),所以__name____main__,会直接调用main函数,

#参数格式必须为3个
# $(TARGET_OUT) system_image_info.txt output_file
def main(argv):
  if len(argv) != 3:
    print __doc__
    sys.exit(1)

  in_dir = argv[0]
  glob_dict_file = argv[1]
  out_file = argv[2]

  #将system_image_info.txt中的内容保存到字典中,例如{'fs_type':'ext4',.....}
  glob_dict = LoadGlobalDict(glob_dict_file)
  #basename获取文件名(不包括路径),这里为system.img
  image_filename = os.path.basename(out_file)
  mount_point = ""
  if image_filename == "system.img":
    mount_point = "system"
  elif image_filename == "userdata.img":
    mount_point = "data"
  elif image_filename == "cache.img":
    mount_point = "cache"
  elif image_filename == "vendor.img":
    mount_point = "vendor"
  else:
    print >> sys.stderr, "error: unknown image file name ", image_filename
    exit(1)
  #print >> 
  #the first expression after the >> must evaluate to a “file-like” object, 
  #输入为system_image_info.txt内容字典和system
  image_properties = ImagePropFromGlobalDict(glob_dict, mount_point)
  if not BuildImage(in_dir, image_properties, out_file):
    print >> sys.stderr, "error: failed to build %s from %s" % (out_file, in_dir)
    exit(1)

#当被直接python build_image.py执行时 __name__为__main__
#当被其他import时,__name__是模块的名字,build_image
#argv[0]是脚本名
if __name__ == '__main__':
  main(sys.argv[1:])

其中,system_image_info.txt一个例子如下所示,一些参数及其值,

fs_type=ext4
system_size=1288491008
userdata_size=5835325440
cache_fs_type=ext4
cache_size=268435456
extfs_sparse_flag=-s
selinux_fc=out/target/product/msm8916_64/root/file_contexts
verity=true
verity_key=build/target/product/security/verity
verity_signer_cmd=out/host/linux-x86/bin/verity_signer
system_verity_block_device=/dev/block/bootdevice/by-name/system
skip_fsck=true

LoadGlobalDict函数如下,将system_image_info.txt中的内容保存到字典中,例如{‘fs_type’:’ext4’,…..}

def LoadGlobalDict(filename):
  """Load "name=value" pairs from filename"""
  d = {}
  f = open(filename)
  #对文件对象的迭代
  #文件中#不处理,是注释
  #strip去除字符串两头,不包括内部的空格
  #split将字符串分割成序列 str.split(sep=None, maxsplit=-1) 
  #If maxsplit is given, at most maxsplit splits are done (thus, the list will have at most maxsplit+1 elements). 
  #>>>'1,2,3'.split(',', maxsplit=1)
  #['1', '2,3']
  #所以用=分割,只有=前面和后面2个元素
  for line in f:
    line = line.strip()
    if not line or line.startswith("#"):
      continue
    k, v = line.split("=", 1)
    d[k] = v
  f.close()
  return d

ImagePropFromGlobalDict函数,从全局字典(system_image_info.txt中有些东西不是都有用)取出需要的东西,返回一个新字典。

def ImagePropFromGlobalDict(glob_dict, mount_point):
  """Build an image property dictionary from the global dictionary.

  Args:
    glob_dict: the global dictionary from the build system.
    mount_point: such as "system", "data" etc.
  """
  d = {}

  def copy_prop(src_p, dest_p):
    if src_p in glob_dict:
      d[dest_p] = str(glob_dict[src_p])
 #extfs_sparse_flag=-s
 #skip_fsck=true
 #selinux_fc=out/target/product/msm8916_64/root/file_contexts
 #将common_props属性中的值保存到新建的字典d中,
  common_props = (
      "extfs_sparse_flag",
      "mkyaffs2_extra_flags",
      "selinux_fc",
      "skip_fsck",
      )
  for p in common_props:
    copy_prop(p, p)

  #添加'mount_point':'system'
  d["mount_point"] = mount_point
  if mount_point == "system":
    #'fs_type':'ext4'
    #'partition_size':'1288491008'
    copy_prop("fs_type", "fs_type")
    copy_prop("system_size", "partition_size")
  elif mount_point == "data":
    copy_prop("fs_type", "fs_type")
    copy_prop("userdata_size", "partition_size")
  elif mount_point == "cache":
    copy_prop("cache_fs_type", "fs_type")
    copy_prop("cache_size", "partition_size")
  elif mount_point == "vendor":
    copy_prop("vendor_fs_type", "fs_type")
    copy_prop("vendor_size", "partition_size")

  return d

最后调用BuildImage函数,其实就是组了一个命令,然后执行该命令(mkuserimg.sh -s in_dir out_file ext4 system 1288491008 out/target/product/msm8916_64/root/file_contexts)。

def BuildImage(in_dir, prop_dict, out_file):
  """Build an image to out_file from in_dir with property prop_dict.

  Args:
    in_dir: path of input directory.
    prop_dict: property dictionary.
    out_file: path of the output image file.

  Returns:
    True iff the image is built successfully.
  """
  build_command = []
  #字典的get方法,如果键不存在,没有任何异常,而得到None
  fs_type = prop_dict.get("fs_type", "")
  run_fsck = False
  #文件系统以ext开头
  #这里是ext4,走这里,其实就是组一个要执行的命令 mkuserimg.sh -s in_dir out_file ext4 system 1288491008 out/target/product/msm8916_64/root/file_contexts
  if fs_type.startswith("ext"):
    build_command = ["mkuserimg.sh"]
    if "extfs_sparse_flag" in prop_dict:
      build_command.append(prop_dict["extfs_sparse_flag"])
      run_fsck = True
    build_command.extend([in_dir, out_file, fs_type,
                          prop_dict["mount_point"]])
    if "partition_size" in prop_dict:
      build_command.append(prop_dict["partition_size"])
    if "selinux_fc" in prop_dict:
      build_command.append(prop_dict["selinux_fc"])
  else:
    build_command = ["mkyaffs2image", "-f"]
    #split用于将字符串分割成list,没有参数表示用空格分割
    if prop_dict.get("mkyaffs2_extra_flags", None):
      build_command.extend(prop_dict["mkyaffs2_extra_flags"].split())
    build_command.append(in_dir)
    build_command.append(out_file)
    if "selinux_fc" in prop_dict:
      build_command.append(prop_dict["selinux_fc"])
      build_command.append(prop_dict["mount_point"])

  #执行该命令mkuserimg.sh -s in_dir out_file ext4 system
  exit_code = RunCommand(build_command)
  if exit_code != 0:
    return False
# >>> os.path.dirname('c:\\Python\\a.txt') 返回目录
# 'c:\\Python'
# >>> os.path.basename('c:\\Python\\a.txt') 返回文件名
# 'a.txt'
# os.path.join连接目录与文件名或目录

  #skip_fsck=true,不走这里 
  if run_fsck and prop_dict.get("skip_fsck") != "true":
    # Inflate the sparse image
    unsparse_image = os.path.join(
        os.path.dirname(out_file), "unsparse_" + os.path.basename(out_file))
    inflate_command = ["simg2img", out_file, unsparse_image]
    exit_code = RunCommand(inflate_command)
    #This function is semantically identical to unlink().
    #remove和unlink一样
    if exit_code != 0:
      os.remove(unsparse_image)
      return False

    # Run e2fsck on the inflated image file
    e2fsck_command = ["e2fsck", "-f", "-n", unsparse_image]
    exit_code = RunCommand(e2fsck_command)

    os.remove(unsparse_image)

  return exit_code == 0

其中,RunCommand其实就类似于c语言中的system(),执行一段命令,获取返回值,用popen实现的。

def RunCommand(cmd):
  """ Echo and run the given command

  Args:
    cmd: the command represented as a list of strings.
  Returns:
    The exit code.
  """
  print "Running: ", " ".join(cmd)
  #创建子进程
  p = subprocess.Popen(cmd)
  #等待子进程执行完
  p.communicate()
  return p.returncode

最终其实是调用了mkuserimg.sh脚本,脚本核心是调用make_ext4fs 应用程序

#system\extras\ext4_utils\mkuserimg.sh

function usage() {
cat<<EOT
Usage:
mkuserimg.sh [-s] SRC_DIR OUTPUT_FILE EXT_VARIANT MOUNT_POINT SIZE [FILE_CONTEXTS]
EOT
}

echo "in mkuserimg.sh PATH=$PATH"

ENABLE_SPARSE_IMAGE=
if [ "$1" = "-s" ]; then
  ENABLE_SPARSE_IMAGE="-s"
  shift
fi

if [ $# -ne 5 -a $# -ne 6 ]; then
  usage
  exit 1
fi

SRC_DIR=$1
if [ ! -d $SRC_DIR ]; then
  echo "Can not find directory $SRC_DIR!"
  exit 2
fi

OUTPUT_FILE=$2
EXT_VARIANT=$3
MOUNT_POINT=$4
SIZE=$5
FC=$6

case $EXT_VARIANT in
  ext4) ;;
  *) echo "Only ext4 is supported!"; exit 3 ;;
esac

if [ -z $MOUNT_POINT ]; then
  echo "Mount point is required"
  exit 2
fi

if [ -z $SIZE ]; then
  echo "Need size of filesystem"
  exit 2
fi

if [ -n "$FC" ]; then
    FCOPT="-S $FC"
fi

#核心是make_ext4fs 应用程序
MAKE_EXT4FS_CMD="make_ext4fs $ENABLE_SPARSE_IMAGE $FCOPT -l $SIZE -a $MOUNT_POINT $OUTPUT_FILE $SRC_DIR"
echo $MAKE_EXT4FS_CMD
$MAKE_EXT4FS_CMD
if [ $? -ne 0 ]; then
  exit 4
fi

而make_ext4fs 应用程序具体在system\extras\ext4_utils中生成,makefile如下,其中makefile中有两个make_ext4fs的module,一个是host(BUILD_HOST_EXECUTABLE),一个是target的(BUILD_EXECUTABLE),这个命令是在编译机调用,也就是host上而不是target上。

include $(CLEAR_VARS)
LOCAL_SRC_FILES := make_ext4fs_main.c
LOCAL_MODULE := make_ext4fs
LOCAL_STATIC_LIBRARIES += \
    libext4_utils_host \
    libsparse_host \
    libz
ifeq ($(HOST_OS),windows)
  LOCAL_LDLIBS += -lws2_32
else
  LOCAL_STATIC_LIBRARIES += libselinux
  LOCAL_CFLAGS := -DHOST
endif
include $(BUILD_HOST_EXECUTABLE)
#!/bin/bash # Logging functions with color-coded output function log_error() { local msg="$1" if [[ -n "${msg}" ]]; then echo -e "\033[31m[ERROR] ${msg}\033[0m" fi } function log_info() { local msg="$1" if [[ -n "${msg}" ]]; then echo -e "\033[32m[INFO] ${msg}\033[0m" fi } function log_warn() { local msg="$1" if [[ -n "${msg}" ]]; then echo -e "\033[33m[WARN] ${msg}\033[0m" fi } # Execute command with error checking function run_command() { local cmd="$@" log_warn "Executing: $cmd" time eval "$cmd" local retVal=$? if [ $retVal -ne 0 ]; then log_error "Command failed with exit code $retVal: $cmd" exit $retVal else log_info "Command succeeded: $cmd" fi } # Build Android QSSI function build_android_qssi() { if [ -d "${ANDROID_QSSI_DIR}" ]; then cd "${ANDROID_QSSI_DIR}" || exit 1 unset PATH || true export PATH="${ORIGIN_ENV}" log_info "build android_qssi start" run_command "source build/envsetup.sh" run_command "lunch ${ANDROID_QSSI_TARGET}-${AND_BUILD_VARIANT}" run_command "${BASH} build.sh dist -j${MAX_JOBS} --qssi_only" log_info "build android_qssi end" else log_warn "${ANDROID_QSSI_DIR} not found, skipping!" fi } # Build Android Vendor function build_android_vendor() { if [ -d "${ANDROID_VENDOR_DIR}" ]; then cd "${ANDROID_VENDOR_DIR}" || exit 1 unset PATH || true export PATH="${ORIGIN_ENV}" log_info "build android_vendor start" run_command "source build/envsetup.sh" run_command "lunch ${ANDROID_VENDOR_TARGET}-${AND_BUILD_VARIANT}" run_command "source kernel_platform/qcom/proprietary/prebuilt_HY11/vendorsetup.sh" run_command "bash kernel_platform/build/android/prepare_vendor.sh autogvm gki" run_command "${BASH} build.sh dist -j${MAX_JOBS} --target_only" # Generate super.img if [ ! -e "${ANDROID_QSSI_DIR}/out/target/product/${ANDROID_QSSI_TARGET}/system.img" ]; then log_error "system.img must exist when generating super.img" exit 1 fi run_command "${PYTHON} vendor/qcom/opensource/core-utils/build/build_image_standalone.py --image super \ --qssi_build_path ${ANDROID_QSSI_DIR} \ --target_build_path ${ANDROID_VENDOR_DIR} \ --merged_build_path ${ANDROID_VENDOR_DIR} \ --target_lunch ${ANDROID_VENDOR_TARGET} --output_ota --skip_qiifa" log_info "build android_vendor end" else log_warn "${ANDROID_VENDOR_DIR} not found, skipping!" fi } # Build Android OTA package function build_android_ota() { if [ -d "${ANDROID_VENDOR_DIR}" ]; then cd "${ANDROID_VENDOR_DIR}" || exit 1 unset PATH || true export PATH="${ORIGIN_ENV}" log_info "build android_ota start" run_command "source build/envsetup.sh" run_command "lunch ${ANDROID_VENDOR_TARGET}-${AND_BUILD_VARIANT}" run_command "${BASH} build.sh dist --merge_only" log_info "build android_ota end" else log_error "${ANDROID_VENDOR_DIR} not found, exiting!" exit 1 fi } # Build QCOM components function build_qcom_boot() { log_info "build qcom_boot start" cd "${TEST_DEVICE_DIR}/boot" || exit 1 run_command "${PYTHON} boot_images/boot_tools/buildex.py --variant AU -r RELEASE -t Makena,QcomToolsPkg" log_info "build qcom_boot end" } function build_qcom_tz() { log_info "build qcom_tz start" cd "${TEST_DEVICE_DIR}/tz/trustzone_images/build/ms/" || exit 1 run_command "python3 build_all.py -b TZ.XF.5.0 CHIPSET=makena" log_info "build qcom_tz end" } function build_qcom_sdsp() { log_info "build qcom_sdsp start" cd "${TEST_DEVICE_DIR}/sdsp/slpi_proc/build/ms/" || exit 1 run_command "${PYTHON} ./build_variant.py makena.slpi.prod2" log_info "build qcom_sdsp end" } function build_qcom_cdsp() { log_info "build qcom_cdsp start" cd "${TEST_DEVICE_DIR}/cdsp/cdsp_proc/build/ms/" || exit 1 run_command "${PYTHON} ./build_variant.py makena.cdsp0.prod" run_command "${PYTHON} ./build_variant.py makena.cdsp1.prod" log_info "build qcom_cdsp end" } function build_qcom_adsp() { log_info "build qcom_adsp start" cd "${TEST_DEVICE_DIR}/adsp/adsp_proc/build/ms/" || exit 1 run_command "${PYTHON} ./build_variant.py makena.adsp_au.prod2" log_info "build qcom_adsp end" } function build_qcom_aop() { log_info "build qcom_aop start" cd "${TEST_DEVICE_DIR}/aop/aop_proc/build/" || exit 1 run_command "${BASH} build_makenaau.sh" log_info "build qcom_aop end" } function build_qcom_bin() { log_info "build qcom_bin start" if [ ! -d "${TEST_DEVICE_DIR}" ]; then log_error "${TEST_DEVICE_DIR} not found, exiting!" exit 1 fi cd "${TEST_DEVICE_DIR}" || exit 1 run_command "source setenv.sh" build_qcom_aop build_qcom_adsp build_qcom_cdsp build_qcom_sdsp build_qcom_boot build_qcom_tz log_info "build qcom_bin end" } # Build Android (QSSI + Vendor) function build_android_all() { log_info "build android_all start" build_android_qssi build_android_vendor log_info "build android_all end" } # Build QNX function build_qnx_only() { log_info "build qnx_only start" if [ -d "${QNX_DIR}" ]; then unset PATH || true export PATH="${ORIGIN_ENV}" cd "${QNX_DIR}/workspace/modules/bsp/apps/qnx_ap" || exit 1 run_command "source setenv_hyp710.sh --external $(pwd)/../../../../../external/sdk/qualcomm/qnx710_host -p 3R425" run_command "make" else log_warn "no qnx code found, skipping!" fi log_info "build qnx_only end" } # Build meta function build_meta() { log_info "build meta start" cd "${TEST_DEVICE_DIR}" || exit 1 if [ ! -d "${ANDROID_QSSI_DIR}" ]; then log_error "${ANDROID_QSSI_DIR} not found, exiting!" exit 1 fi if [ ! -d "${ANDROID_VENDOR_DIR}" ]; then log_error "${ANDROID_VENDOR_DIR} not found, exiting!" exit 1 fi if [ ! -d "${TEST_DEVICE_DIR}/apps_kernel" ]; then mkdir "${TEST_DEVICE_DIR}/apps_kernel" || exit 1 fi ln -fs "$(dirname "$(dirname "${ANDROID_QSSI_DIR}")")" . ln -fs "$(dirname "$(dirname "${ANDROID_VENDOR_DIR}")")" . ln -fs "${QNX_DIR}/workspace/modules/bsp/apps" . ln -fs "${KERNEL_PLATFORM_DIR}" "${TEST_DEVICE_DIR}/apps_kernel" cd "${TEST_DEVICE_DIR}/common/build" || exit 1 if [ "${GWM_V4_DV}" == "true" ]; then sed -i 's/<file_name>cluster.img<\/file_name>/<file_name><\/file_name>/g' "${TEST_DEVICE_DIR}/common/config/contents_${VARIANT}.xml" sed -i 's/<file_name>qnxres.img<\/file_name>/<file_name><\/file_name>/g' "${TEST_DEVICE_DIR}/common/config/contents_${VARIANT}.xml" sed -i 's/<file_name>vr.img<\/file_name>/<file_name><\/file_name>/g' "${TEST_DEVICE_DIR}/common/config/contents_${VARIANT}.xml" sed -i 's/<file_name>navi_buffer.img<\/file_name>/<file_name><\/file_name>/g' "${TEST_DEVICE_DIR}/common/config/contents_${VARIANT}.xml" sed -i 's/<file_name>appres.img<\/file_name>/<file_name><\/file_name>/g' "${TEST_DEVICE_DIR}/common/config/contents_${VARIANT}.xml" sed -i 's/filename=\"qnxres.img\"/filename=\"\"/g' "${TEST_DEVICE_DIR}/common/config/ufs/partition_la_ext.xml" sed -i 's/filename=\"cluster.img\"/filename=\"\"/g' "${TEST_DEVICE_DIR}/common/config/ufs/partition_la_ext.xml" sed -i 's/filename=\"navi_buffer.img\"/filename=\"\"/g' "${TEST_DEVICE_DIR}/common/config/ufs/partition_la_ext.xml" sed -i 's/filename=\"vr.img\"/filename=\"\"/g' "${TEST_DEVICE_DIR}/common/config/ufs/partition_la_ext.xml" sed -i 's/filename=\"appres.img\"/filename=\"\"/g' "${TEST_DEVICE_DIR}/common/config/ufs/partition_la_ext.xml" fi run_command "${PYTHON} build.py --flavors=${FLAVOR} --variant=${VARIANT} --st=${STORAGE}" log_info "build meta end" } # Pack qfile function pack_qfile() { log_info "build pack_qfile start" cd "${SCRIPTS_DIR}" || exit 1 run_command "${PYTHON} copy_meta_data.py --rootdir ${TOP_CODE_DIR} --output ${TOP_CODE_DIR} --variant ${VARIANT} --flavor ${FLAVOR} --storage ${STORAGE}" log_info "please get the flash img in ${TOP_CODE_DIR}/output" log_info "build pack_qfile end" } # Build userdebug (full build including QCOM, QNX, meta, and OTA) function build_userdebug() { log_info "build userdebug start" AND_BUILD_VARIANT="userdebug" build_android_all build_qnx_only build_qcom_bin build_meta build_android_ota log_info "build userdebug end" } # Build user (release version) function build_user() { log_info "build user start" unset AND_BUILD_VARIANT || true export AND_BUILD_VARIANT="user" build_android_all build_qnx_only build_qcom_bin build_meta build_android_ota log_info "build user end" } # Print help message function print_help() { log_warn "Android and QNX project paths must be replaced with actual project info!" log_info "build android qssi:\nbash build_all.sh --android_qssi" log_info "build android vendor:\nbash build_all.sh --android_vendor" log_info "build android all:\nbash build_all.sh --android_all" log_info "build qnx:\nbash build_all.sh --qnx_only" log_info "build android+qnx:\nbash build_all.sh --android_qnx" log_info "build qcom bin:\nbash build_all.sh --qcom_bin" log_info "build android ota:\nbash build_all.sh --ota\nWarning: run this after compiling all code once" log_info "build userdebug version:\nbash build_all.sh --userdebug" log_info "build user release version:\nbash build_all.sh --user" log_info "pack qfile img:\nbash build_all.sh --pack_qfile" } # Main function function main() { if [ $# -eq 0 ]; then print_help exit 0 fi # Parse arguments ARGS=$(getopt -o h --long help,pack_qfile,android_all,qcom_bin,ota,userdebug,user,android_qssi,android_vendor,qnx_only,android_qnx,dv,recompile_kernel,android_vendor_pro:,qnx_pro:,variant:,storage:,flavor:,jobs: -n "$0" -- "$@") if [ $? -ne 0 ]; then log_error "Invalid arguments. Terminating..." exit 1 fi eval set -- "${ARGS}" # Initialize flags declare -A BUILD_FLAGS while true; do case "$1" in -h|--help) print_help exit 0 ;; --android_all) BUILD_FLAGS[ANDROID_ALL]=1; shift ;; --android_qssi) BUILD_FLAGS[ANDROID_QSSI]=1; shift ;; --android_vendor) BUILD_FLAGS[ANDROID_VENDOR]=1; shift ;; --qcom_bin) BUILD_FLAGS[QCOM_BIN]=1; shift ;; --ota) BUILD_FLAGS[ANDROID_OTA]=1; shift ;; --qnx_only) BUILD_FLAGS[QNX]=1; shift ;; --recompile_kernel) export RECOMPILE_KERNEL=1; shift ;; --android_qnx) BUILD_FLAGS[ANDROID_QNX]=1; shift ;; --userdebug) BUILD_FLAGS[USERDEBUG]=1; shift ;; --user) BUILD_FLAGS[USER]=1; shift ;; --pack_qfile) BUILD_FLAGS[PACK_QFILE]=1; shift ;; --dv) export GWM_V4_DV=true; shift ;; --android_vendor_pro) ANDROID_VENDOR_TARGET="$2"; shift 2 ;; --qnx_pro) QNX_TARGET="$2"; shift 2 ;; --variant) VARIANT="$2"; shift 2 ;; --storage) STORAGE="$2"; shift 2 ;; --flavor) FLAVOR="$2"; shift 2 ;; --jobs) MAX_JOBS="$2"; shift 2 ;; --) shift; break ;; *) log_error "Unknown option: $1"; exit 1 ;; esac done # Global settings TOP_CODE_DIR=$(dirname "$(pwd)") QFILE_DIR="${TOP_CODE_DIR}/pack/qfile" FASTBOOT_DIR="${TOP_CODE_DIR}/pack/fastboot" ANDROID_QSSI_DIR="${TOP_CODE_DIR}/lagvm_qssi/LINUX/android" ANDROID_VENDOR_DIR="${TOP_CODE_DIR}/lagvm/LINUX/android" KERNEL_PLATFORM_DIR="${TOP_CODE_DIR}/lagvm_qssi/LINUX/android/kernel_platform" QNX_DIR="${TOP_CODE_DIR}/qnx" TEST_DEVICE_DIR="${TOP_CODE_DIR}/test_device" SCRIPTS_DIR="${TOP_CODE_DIR}/integration" ORIGIN_ENV="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ANDROID_QSSI_TARGET=${ANDROID_QSSI_TARGET:-'qssi_au'} ANDROID_VENDOR_TARGET=${ANDROID_VENDOR_TARGET:-'msmnile_gvmq'} MAX_JOBS=${MAX_JOBS:-24} RECOMPILE_KERNEL=${RECOMPILE_KERNEL:-0} VARIANT=${VARIANT:-'8888la'} STORAGE=${STORAGE:-'ufs'} FLAVOR=${FLAVOR:-'8888_la'} PYTHON=${PYTHON:-'python'} BASH=${BASH:-'/bin/bash'} AND_BUILD_VARIANT=${AND_BUILD_VARIANT:-'userdebug'} # Execute builds based on flags if [ "${BUILD_FLAGS[USERDEBUG]}" == 1 ]; then build_userdebug elif [ "${BUILD_FLAGS[USER]}" == 1 ]; then build_user else if [ "${BUILD_FLAGS[ANDROID_ALL]}" == 1 ]; then build_android_all fi if [ "${BUILD_FLAGS[ANDROID_QSSI]}" == 1 ]; then build_android_qssi fi if [ "${BUILD_FLAGS[ANDROID_VENDOR]}" == 1 ]; then build_android_vendor fi if [ "${BUILD_FLAGS[ANDROID_OTA]}" == 1 ]; then build_android_ota fi if [ "${BUILD_FLAGS[QNX]}" == 1 ]; then build_qnx_only fi if [ "${BUILD_FLAGS[ANDROID_QNX]}" == 1 ]; then build_android_all build_qnx_only fi if [ "${BUILD_FLAGS[QCOM_BIN]}" == 1 ]; then build_qcom_bin fi if [ "${BUILD_FLAGS[PACK_QFILE]}" == 1 ]; then build_meta pack_qfile fi fi } # Run main main "$@" 请优化此代码实现,执行bash build_all.sh --userdebug或bash build_all.sh --user可以编译,且函数build_qcom_bin和build_meta也可以执行,且满足代码规范
最新发布
06-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值