当前位置: 首页 > 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  ......
            

相关文章:

  • RS485
  • 用于算法性能预测的 GNN 框架
  • 在Ubuntu上设置Firefox自动化测试环境:指定Marionette端口号
  • 【Comosl教程】如何计算物体所受到的力矩——质心积分法
  • 微信小程序:选择页面单选实现(多页面均可选择)
  • 探秘 Java 安全利器 ——JVMTI
  • 从哈希到挑战响应,密码传输安全解析
  • 《去哪儿网Redis高并发实战:从问题定位到架构升级》
  • RK3288 android7.1 将普通串口设置为调试串口
  • 从ConstraintLayout到Jetpack Compose:全面掌握Android UI设计与布局技术
  • 广东省专升本英语形容词与副词全梳理
  • ​​FFmpeg命令全解析:三步完成视频合并、精准裁剪​​、英伟达显卡加速
  • Maven 多模块项目调试与问题排查总结
  • 自动化 UI 测试智能体在 Trae 平台的部署体验
  • FPGA基础 -- Verilog 竞争/竞态(Race Condition)
  • AI辅助编程工具技术评估(2025年):CodeBuddy在开发者生态中的差异化优势分析
  • Stable Diffusion 项目实战落地:AI绘画与文案创作的魔法 第一篇 ——让你的小说推文秒变视觉与故事双料爆款!
  • 用 Makefile 自动生成详解:从零到精通的硬核指南
  • 在 AI 工具海洋中掌舵:Cherry Studio 如何成为你的统一指挥中心
  • 使用CloudFormation模板自动化AWS基础设施的部署
  • b s架构做的网站/无锡谷歌推广
  • 网站素材图/互联网营销课程体系
  • 成都手机端建站模板/乐陵市seo关键词优化
  • 广西柳州网站制作公司/宁波优化网站哪家好
  • vb.net做网站/如何创建一个平台
  • 网站设计素材下载/营销型网站建设实训总结