当前位置: 首页 > news >正文

Android 编译和打包image镜像流程

1. 编译命令

source build/envsetup.sh
lunch aosp_car_arm64-userdebug
make

2. 编译流程

source build/envsetup.sh

  • 定义一些函数的环境变量,如 lunch
  • validate_current_shell,确认 shell 环境
  • set_global_paths,设置环境变量 ANDROID_GLOBAL_BUILD_PATHS
  • source_vendorsetup,从 device vendor product 等目录遍历搜索 vendorsetup.sh(添加厂商自己定义的产品编译选项),并 source 进来
  • addcompletions,为一些命令添加自动补全功能

lunch aosp_car_arm64-userdebug

  • lunch,设置 TARGET_PRODUCT、TARGET_BUILD_VARIANT、PLATFORM_VERSION 等,示例:
    • TARGET_PRODUCT=aosp_car_arm64
    • TARGET_BUILD_VARIANT=userdebug
  • 调到 build/soong/soong_ui.bash,走到 build/soong/cmd/soong_ui/main.go
    soong_build_go soong_ui android/soong/cmd/soong_ui
    soong_build_go mk2rbc android/soong/mk2rbc/mk2rbc
    soong_build_go rbcrun rbcrun/rbcruncd ${TOP}
    exec "$(getoutdir)/soong_ui" "$@"
    
    • 通过编译 android/soong/cmd/soong_ui/main.go 来编译生成 soong_ui。该工具是 AOSP 的主入口之一,负责调度整个 Soong 构建流程(包括 lunch 后执行的 make 实际就是调用它)
    • 构建 mk2rbc 工具:Make to RBC 转换工具,作用是将 .mk 格式的旧 Makefile 语法转换为 Blueprint(或 Soong 的)中间格式(RBC:Rule-Based Config)
      构建 rbcrun 工具,用于执行 mk2rbc 转换后生成的 .rbc 中间构建逻辑
  • 执行 build_build_var_cache,调到 build/soong/soong_ui.bash,执行 --dumpvars-mode。
    bash |-- build/soong/cmd/soong_ui/main.go dumpVars |-- build/soong/ui/build/dumpvars.go 最后调用到了ckati执行-f build/make/core/config.mk 从Makefile获取变量值 → 传给Soong使用
  • config.mk等

make

  • 执行 envsetup.sh 中的 make,调到 build/soong/soong_ui.bash,执行 --make-node。
  • 最终会执行 exec out/soong_ui --make-mode 进行编译。
    |-- build/soong/cmd/soong_ui/main.gorunMakelogAndSymlinkSetup()|-- build/soong/ui/build/finder.goFindSources # 创建out/.module_paths/AndroidProducts.mk.list# 将device、vendor和product路径下所有的AndroidProducts.mk文件路径收集起来build.Build()|-- build/soong/ui/build/build.gorunMakeProductConfig runSoongrunKatiBuildrunNinjaForBuild
    

runMakeProductConfig – build/soong/ui/build/dumpvars.go

  • 主要配置编译参数

runSoong – build/soong/ui/build/soong.go

  • 对工具进行编译,编译出 blueprint 等编译工具, 把 *.bp 编译成 out/soong/build.ninja
    bootstrapBlueprint└─ bootstrap.RunBlueprint(...)├─ ctx.ListModulePaths → 获取Android.bp列表,列出需要解析的.bp文件路径├─ ctx.ParseFileList → 解析Android.bp文件├─ ctx.ResolveDependencies → 模块依赖关系建立,主要在.bp文件语法解析完之后、生成.ninja构建规则之前,进行模块依赖检查和构建图生成├─ ctx.PrepareBuildActions → 生成构建动作(构建图)└─ ctx.WriteBuildFile → 生成Ninja构建文件,bootstrap.ninjaninja("bootstrap", "bootstrap.ninja", targets...)|-- ninja -f out/soong/bootstrap.ninja [targets...]2025/06/19 14:28:59.631720 build/soong/ui/logger/logger.go:290: "soong bootstrap" executing "prebuilts/build-tools/linux-x86/bin/ninja" [prebuilts/build-tools/linux-x86/bin/ninja -d keepdepfile -d stats -o usesphonyoutputs=yes -o preremoveoutputs=yes -w dupbuild=err -w outputdir=warn -w missingoutfile=warn -j 22 --frontend_file out/.ninja_fifo -f out/soong/bootstrap.ninja out/soong/build.ninja]
    
  • -d keepdepfile:不要删除由构建命令产生的依赖文件 depfile(build.ninja.d),depfile 是构建过程中生成的文件,通常用来描述构建目标依赖了哪些源文件。ninja 通过读取 depfile,能知道当某个依赖文件发生改变时,哪些目标需要重新构建。
    Android.bp (模块描述文件)↓
    soong_build (调用Blueprint解析Android.bp)↓
    Blueprint(解析并构建模块依赖图)↓
    生成Ninja构建文件(build.ninja)↓
    ninja执行build.ninja完成编译链接等动作
    

runKatiBuild – build/soong/ui/build/kati.go

runKatiBuild|-- runKati2025/06/19 15:45:33.680642 build/soong/ui/logger/logger.go:290: "ckati" executing "prebuilts/build-tools/linux-x86/bin/ckati" [prebuilts/build-tools/linux-x86/bin/ckati --ninja --ninja_dir=out --ninja_suffix=-aosp_car_arm64 --no_ninja_prelude --use_ninja_phony_output --use_ninja_symlink_outputs --regen --ignore_optional_include=out/%.P --detect_android_echo --color_warnings --gen_all_targets --use_find_emulator --werror_find_emulator --no_builtin_rules --werror_suffix_rules --werror_real_to_phony --top_level_phony --werror_phony_looks_real --werror_writable --kati_stats --writable out/ --werror_implicit_rules -f build/make/core/main.mk ......]runKatiPackage|-- runKati2025/06/19 15:47:09.954615 build/soong/ui/logger/logger.go:290: "ckati" executing "prebuilts/build-tools/linux-x86/bin/ckati" [prebuilts/build-tools/linux-x86/bin/ckati --ninja --ninja_dir=out --ninja_suffix=-aosp_car_arm64-package --no_ninja_prelude --use_ninja_phony_output --use_ninja_symlink_outputs --regen --ignore_optional_include=out/%.P --detect_android_echo --color_warnings --gen_all_targets --use_find_emulator --werror_find_emulator --no_builtin_rules --werror_suffix_rules --werror_real_to_phony --top_level_phony --werror_phony_looks_real --werror_writable --kati_stats --writable out/dist/ --werror_implicit_rules --werror_overriding_commands -f build/make/packaging/main.mk ......]
  • 运行 runKatiBuild() 和 runKatiPackage(),加载 build/make/core/main.mk和build/make/packaging/main.mk(从 main.mk 开始,将通过 include 命令将其所有需要的 .mk 文件包含进来),分别生成 out/build-aosp_car_arm64.ninja 和 out/build-aosp_car_arm64-package.ninja。

runNinjaForBuild – build/soong/ui/build/ninja.go

2025/06/19 15:47:09.959923 build/soong/ui/logger/logger.go:290: "ninja" executing "prebuilts/build-tools/linux-x86/bin/ninja" [prebuilts/build-tools/linux-x86/bin/ninja -d keepdepfile -d keeprsp -d stats --frontend_file out/.ninja_fifo nothing -j 22 -f out/combined-aosp_car_arm64.ninja -o usesphonyoutputs=yes -w dupbuild=err -w missingdepfile=err]
  • out/combined-aosp_car_arm64.ninja 内容如下:
	builddir = outpool highmem_pooldepth = 7subninja out/build-aosp_car_arm64.ninjasubninja out/build-aosp_car_arm64-package.ninjasubninja out/soong/build.ninjaAndroid.bp --> Blueprint --> Soong --> NinjaMakefile/Android.mk --> kati --> Ninja

3. systemimage 打包

  • build/make/core/main.mk
# This is the default target.  It must be the first declared target.
.PHONY: droid
DEFAULT_GOAL := droid
$(DEFAULT_GOAL): droid_targets.PHONY: droid_targets
droid_targets:......droid_targets: droidcore-unbundled.......PHONY: droidcore-unbundled
droidcore-unbundled: $(filter $(HOST_OUT_ROOT)/%,$(modules_to_install)) \$(INSTALLED_FILES_OUTSIDE_IMAGES) \$(INSTALLED_SYSTEMIMAGE_TARGET) \$(INSTALLED_RAMDISK_TARGET) \......$(INSTALLED_VENDORIMAGE_TARGET) \......
  • build/make/core/Makefile

    # 这里就是out/target/product/<product_name>/system.img
    INSTALLED_SYSTEMIMAGE_TARGET := $(PRODUCT_OUT)/system.img......$(INSTALLED_SYSTEMIMAGE_TARGET): $()@echo "Install system fs image: $@"$(copy-file-to-target)$(hide) $(call assert-max-image-size,$@,$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))......systemimage_intermediates := \$(call intermediates-dir-for,PACKAGING,systemimage)
    BUILT_SYSTEMIMAGE := $(systemimage_intermediates)/system.img
    # 这里就是out/target/product/<product_name>/obj/PACKAGING/systemimage_intermediates/system.img......# $(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-image-prop-dictionary, $(systemimage_intermediates)/system_image_info.txt,system, \skip_fsck=true)PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \$(BUILD_IMAGE) \$(TARGET_OUT) $(systemimage_intermediates)/system_image_info.txt $(1) $(TARGET_OUT) \|| ( mkdir -p $${DIST_DIR}; \cp $(INSTALLED_FILES_FILE) $${DIST_DIR}/installed-files-rescued.txt; \exit 1 )
    endef$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE)$(call build-systemimage-target,$@)
    
    • BUILD_IMAGE 根据 system_image_info.txt(部分内容如下)最终生成 system.img
      system_fs_type=erofs
      system_disable_sparse=true
      system_selinux_fc=out/target/product/<product_name>/obj/ETC/file_contexts.bin_intermediates/file_contexts.bin
      building_system_image=true
      ext_mkuserimg=mkuserimg_mke2fs
      fs_type=ext4
      extfs_sparse_flag=-s
      erofs_sparse_flag=-s
      squashfs_sparse_flag=-s
      f2fs_sparse_flag=-S
      erofs_default_compressor=lz4hc,9
      ext4_share_dup_blocks=true
      avb_avbtool=avbtool
      avb_system_hashtree_enable=true
      ......
      
  • build/make/core/definitions.mk

    define copy-file-to-target
    @mkdir -p $(dir $@)
    $(hide) rm -f $@
    $(hide) cp "$<" "$@"
    endef
    
    • $@:out/target/product/<product_name>/system.img
    • $<:第一个依赖文件,out/target/product/<product_name>/obj/PACKAGING/systemimage_intermediates/system.img
  • build/make/core/Makefile 中的 $(FULL_SYSTEMIMAGE_DEPS)$(INSTALLED_FILES_FILE)

    INSTALLED_FILES_FILE := $(PRODUCT_OUT)/installed-files.txt
    INSTALLED_FILES_JSON := $(INSTALLED_FILES_FILE:.txt=.json)
    $(INSTALLED_FILES_FILE): .KATI_IMPLICIT_OUTPUTS := $(INSTALLED_FILES_JSON)
    $(INSTALLED_FILES_FILE): $(FULL_SYSTEMIMAGE_DEPS) $(FILESLIST) $(FILESLIST_UTIL)@echo Installed file list: $@mkdir -p $(dir $@)rm -f $@$(FILESLIST) $(TARGET_OUT) > $(@:.txt=.json)$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
    
    • 这里的 TARGET_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM),即out/target/product/<product_name>/system

      • PRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE) -- out/target/product/<product_name>
      • TARGET_DEVICE := $(PRODUCT_DEVICE) -- build/make/core/product_config.mk
        • PRODUCT_DEVICE := <product_name>
      • TARGET_PRODUCT_OUT_ROOT := $(TARGET_OUT_ROOT)/product -- out/target/product
        • TARGET_OUT_ROOT := $(OUT_DIR)/target -- out/target
        • OUT_DIR := out
      • TARGET_COPY_OUT_SYSTEM := system
    • $(FILESLIST) 是生成 JSON 清单的工具,输入是 $(TARGET_OUT)(打包目录),输出为 out/target/product/<product_name>/installed-files.json

    • $(FILESLIST_UTIL) 是工具程序,-c 选项代表将 .json 压缩为 .txt 形式的清单

      # out/target/product/<product_name>/installed-files.txt351773687  /system/priv-app/CarSettings/CarSettings.apk74870784  /system/apex/com.android.vndk.current.apex48640000  /system/apex/com.android.i18n.apex46346240  /system/apex/com.android.car.framework.apex42966569  /system/framework/framework.jar39179408  /system/lib64/libflutter_engine.so......
      
      # out/target/product/missi/installed-files.json
      [{"SHA256": "b120b4ed5d86a9e935eeda485ac92e1e8d9f63d6f5fb8e735fa0f0bac3d5da48","Name": "/system/priv-app/CarSettings/CarSettings.apk","Size": 351778736},{"SHA256": "792fe7a24c7f38721a0f87056f849e89d4ed4e1546ae0e001f228c75ae9bc9e0","Name": "/system/apex/com.android.vndk.current.apex","Size": 74830784},......
      
    • build/make/core/Makefile 中 $(FULL_SYSTEMIMAGE_DEPS)

      FULL_SYSTEMIMAGE_DEPS := $(INTERNAL_SYSTEMIMAGE_FILES) $(INTERNAL_USERIMAGES_DEPS)INTERNAL_USERIMAGES_DEPS := \$(BUILD_IMAGE) \$(MKE2FS_CONF) \$(MKEXTUSERIMG)INTERNAL_USERIMAGES_DEPS += ......# 从$(ALL_DEFAULT_INSTALLED_MODULES)过滤只符合out/target/product/<product_name>/system分区的文件路径
      INTERNAL_SYSTEMIMAGE_FILES := $(sort $(filter $(TARGET_OUT)/%, \$(ALL_DEFAULT_INSTALLED_MODULES)))# $(ALL_DEFAULT_INSTALLED_MODULES)所有模块最终的安装目标路径(包含system/vendor/product等)
      
      • $(INTERNAL_USERIMAGES_DEPS):列出了制作 system.img 所需要的工具
        • BUILD_IMAGE := $(HOST_OUT_EXECUTABLES)/build_image$(HOST_EXECUTABLE_SUFFIX)
          • 即:out/host/linux-x86/bin/build_image -- build/make/tools/releasetools/build_image.py
        • MKE2FS_CONF := system/extras/ext4_utils/mke2fs.conf
        • MKEXTUSERIMG := $(HOST_OUT_EXECUTABLES)/mkuserimg_mke2fs
          • 即:out/host/linux-x86/bin/mkuserimg_mke2fs
        • 等其它工具,不一一列出
      • $(INTERNAL_SYSTEMIMAGE_FILES)
        • $(ALL_DEFAULT_INSTALLED_MODULES) 所有模块最终的安装目标路径
          • build/make/core/main.mk
            known_custom_modules := $(filter $(ALL_MODULES),$(CUSTOM_MODULES))
            unknown_custom_modules := $(filter-out $(ALL_MODULES),$(CUSTOM_MODULES))
            CUSTOM_MODULES := \$(call module-installed-files,$(known_custom_modules)) \$(unknown_custom_modules)modules_to_install := $(sort \$(ALL_DEFAULT_INSTALLED_MODULES) \$(product_target_FILES) \$(product_host_FILES) \$(CUSTOM_MODULES) \)ALL_DEFAULT_INSTALLED_MODULES := $(modules_to_install)
            ifeq ($(HOST_OS),linux)include $(BUILD_SYSTEM)/Makefile  # BUILD_SYSTEM -- build/make/core
            endif
            modules_to_install := $(sort $(ALL_DEFAULT_INSTALLED_MODULES))
            ALL_DEFAULT_INSTALLED_MODULES :=product_host_FILES := $(call host-installed-files,$(INTERNAL_PRODUCT))product_target_FILES := $(call product-installed-files, $(INTERNAL_PRODUCT))
            
          • build/make/core/product_config.mk
            product_paths :=
            common_lunch_choices :=
            products_using_starlark_config :=
            $(foreach f,$(android_products_makefiles), \$(call _read-ap-file,$(f)) \$(eval product_paths += $(ap_product_paths)) \$(eval common_lunch_choices += $(ap_common_lunch_choices)) \$(eval products_using_starlark_config += $(ap_products_using_starlark_config)) \
            )# Dedup, extract product names, etc.
            product_paths := $(sort $(product_paths))
            all_named_products := $(sort $(call _first,$(product_paths),:))
            current_product_makefile := $(call _second,$(filter $(TARGET_PRODUCT):%,$(product_paths)),:)
            
        • 回到 build/make/core/main.mk:
          product_host_FILES := $(call host-installed-files,$(INTERNAL_PRODUCT))
          product_target_FILES := $(call product-installed-files, $(INTERNAL_PRODUCT))
          
          • 根据这个 $(INTERNAL_PRODUCT),抽取它所有声明的包和拷贝文件安装路径,作为最终 system.img 所需的内容清单。
          • product_host_FILES 部分内容如下:
            out/host/linux-x86/framework/BugReport.jar out/host/linux-x86/bin/BugReport out/host/linux-x86/bin/adb out/host/linux-x86/fake_packages/art-tools-timestamp out/host/linux-x86/bin/atest-dev out/host/linux-x86/bin/bcc out/host/linux-x86/bin/bit out/host/linux-x86/bin/brillo_update_payload out/host/linux-x86/bin/dump.erofs out/host/linux-x86/bin/e2fsck out/host/linux-x86/bin/e2fsdroid out/host/linux-x86/bin/fastboot out/host/linux-x86/bin/flags_health_check out/host/linux-x86/bin/fsck.erofs out/host/linux-x86/bin/fsck.f2fs out/host/linux-x86/bin/resize.f2fs out/host/linux-x86/bin/defrag.f2fs out/host/linux-x86/bin/dump.f2fs out/host/linux-x86/com.android.i18n/etc/icu/icudt72l.dat out/host/linux-x86/com.android.tzdata/etc/icu/icu_tzdata.dat out/host/linux-x86/bin/idmap2 out/host/linux-x86/bin/incident_report out/host/linux-x86/bin/ld.mc out/host/linux-x86/bin/lpdump out/host/linux-x86/bin/make_f2fs out/host/linux-x86/bin/minigzip out/host/linux-x86/bin/mke2fs out/host/linux-x86/bin/mkfs.erofs out/host/linux-x86/bin/qiifa_py2 out/host/linux-x86/bin/resize2fs out/host/linux-x86/bin/sgdisk out/host/linux-x86/bin/sload_f2fs out/host/linux-x86/bin/sqlite3 out/host/linux-x86/bin/tinyplay ......
            
          • product_target_FILES 部分内容如下:
            ......  out/target/product/missi/system/lib64/libservices.so out/target/product/missi/system/lib64/libservices.core-gnss.so out/target/product/missi/system/lib/libservices.core-gnss.so  ......
            
http://www.lqws.cn/news/493525.html

相关文章:

  • 小程序 顶部栏标题栏 下拉滚动 渐显白色背景
  • 华为HN8145V光猫改华为蓝色公版界面,三网通用,xgpon公版光猫
  • 多智能体协同的力量:赋能AI安全报告系统的智能设计之道
  • 创客匠人洞察:2025 创始人 IP 打造六大趋势与知识变现新路径​
  • 【入门级-基础知识与编程环境:3、计算机网络与Internet的基本概念】
  • Flutter ListTile 徽章宽度自适应的真正原因与最佳实践
  • 开启游戏新时代:神经网络渲染技术实现重大跨越
  • HarmonyOS 5 双向滚动课程表:技术实现与交互设计解析(附:源代码)
  • 谷歌地图的3d街景使用的是什么数据格式?
  • Java 程序设计试题​
  • 常见JavaScript 代理模式应用场景解析
  • 6.23_JAVA_RabbitMQ
  • 2025年中科院三区全新算法,恒星振荡优化器:受自然启发的元启发式优化,完整MATLAB代码免费获取
  • hive集群优化和治理常见的问题答案
  • 综述AI生成工具推荐:高效自动化生成学术综述
  • 网络安全之某cms的漏洞分析
  • MocapApi 中文文档 和github下载地址 NeuronDataReader(以下简称 NDR)的下一代编程接口
  • 1 Studying《Systems.Performance》7-13
  • Maven 多模块项目调试与问题排查总结
  • SpreadJS 迷你图:数据趋势可视化的利器
  • Web基础 -SpringBoot入门 -HTTP-分层解耦 -三层架构
  • HTML语义化标签
  • 最近小峰一直在忙国际化项目,确实有点分身乏术... [特殊字符] 不过! 我正紧锣密鼓准备一系列干货文章/深度解析
  • [HTML]iframe显示pdf,隐藏左侧分页
  • Python异步爬虫编程技巧:从入门到高级实战指南
  • 从本地到云端:通过ToolJet和cpolar构建远程开发环境实践过程
  • ​​FFmpeg命令全解析:三步完成视频合并、精准裁剪​​、英伟达显卡加速
  • systemd[1]: Failed to start LSB: Bring up/down networking
  • 在大数据求职面试中如何回答分布式协调与数据挖掘问题
  • 开疆智能CCLinkIE转ModbusTCP网关连接 BORUNTE伯朗特机器人案例