★★★ 友情链接 : 个人博客导读首页—点击此处 ★★★

当敲击make命令时,会找到第一个目标droid(在build/core/main.mk中),droid依赖droid_targets,droid_targets依赖droidcore和dist_files,droidcore的依赖关系如下:

.PHONY: droidcore
droidcore: files \systemimage \$(INSTALLED_BOOTIMAGE_TARGET) \$(INSTALLED_RECOVERYIMAGE_TARGET) \$(INSTALLED_VBMETAIMAGE_TARGET) \$(INSTALLED_USERDATAIMAGE_TARGET) \$(INSTALLED_CACHEIMAGE_TARGET) \$(INSTALLED_BPTIMAGE_TARGET) \$(INSTALLED_VENDORIMAGE_TARGET) \$(INSTALLED_PRODUCTIMAGE_TARGET) \$(INSTALLED_SYSTEMOTHERIMAGE_TARGET) \$(INSTALLED_FILES_FILE) \$(INSTALLED_FILES_FILE_VENDOR) \$(INSTALLED_FILES_FILE_PRODUCT) \$(INSTALLED_FILES_FILE_SYSTEMOTHER) \soong_docs

切到build/core/Makefile中,我们看到systemimage又依赖INSTALLED_SYSTEMIMAGE,而INSTALLED_SYSTEMIMAGE又依赖BUILT_SYSTEMIMAGE,BUILT_SYSTEMIMAGE其实就是system.img

systemimage: $(INSTALLED_SYSTEMIMAGE)
$(INSTALLED_SYSTEMIMAGE): $(BUILT_SYSTEMIMAGE) $(RECOVERY_FROM_BOOT_PATCH)BUILT_SYSTEMIMAGE := $(systemimage_intermediates)/system.img

我们再来看看BUILT_SYSTEMIMAGE的依赖关系:

$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE) $(BUILD_IMAGE_SRCS)$(call build-systemimage-target,$@)

BUILT_SYSTEMIMAGE依赖的一些文件生成后,会调用makefile中的build-systemimage-target函数,我们接着去看build-systemimage-target的函数原型:

define build-systemimage-target@echo "Target system fs image: $(1)"$(call create-system-vendor-symlink)@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) $(TARGET_OUT) \|| ( echo "Out of space? the tree size of $(TARGET_OUT) is (MB): " 1>&2 ;\du -sm $(TARGET_OUT) 1>&2;\if [ "$(INTERNAL_USERIMAGES_EXT_VARIANT)" == "ext4" ]; then \maxsize=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE); \if [ "$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" == "true" ]; then \maxsize=$$((maxsize - 4096 * 4096)); \fi; \echo "The max is $$(( maxsize / 1048576 )) MB." 1>&2 ;\else \echo "The max is $$(( $(BOARD_SYSTEMIMAGE_PARTITION_SIZE) / 1048576 )) MB." 1>&2 ;\fi; \mkdir -p $(DIST_DIR); cp $(INSTALLED_FILES_FILE) $(DIST_DIR)/installed-files-rescued.txt; \exit 1 )
endef

看起来挺复杂吧,其实都是些shell语句,仔细看还是能看懂的。看不懂也没关系,我们只关心其中的关键语句 ./build/tools/releasetools/build_image.py,其后跟随了一堆的参数,我们不必关心这些参数,只要 明白,这里调用了build_image.py
打开build_image.py,main函数如下,其实并不复杂,这里随后调用了BuildImage()

def main(argv):if len(argv) != 4:print __doc__sys.exit(1)in_dir = argv[0]glob_dict_file = argv[1]out_file = argv[2]target_out = argv[3]glob_dict = LoadGlobalDict(glob_dict_file)if "mount_point" in glob_dict:# The caller knows the mount point and provides a dictionay needed by# BuildImage().image_properties = glob_dictelse:image_filename = os.path.basename(out_file)mount_point = ""if image_filename == "system.img":mount_point = "system"elif image_filename == "system_other.img":mount_point = "system_other"elif image_filename == "userdata.img":mount_point = "data"elif image_filename == "cache.img":mount_point = "cache"elif image_filename == "vendor.img":mount_point = "vendor"elif image_filename == "oem.img":mount_point = "oem"else:print >> sys.stderr, "error: unknown image file name ", image_filenameexit(1)image_properties = ImagePropFromGlobalDict(glob_dict, mount_point)if not BuildImage(in_dir, image_properties, out_file, target_out):print >> sys.stderr, "error: failed to build %s from %s" % (out_file,in_dir)exit(1)

继续查看BuildImage(),原型如下:

def BuildImage(in_dir, prop_dict, out_file, target_out=None):"""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.target_out: path of the product out directory to read device specific FS config files.Returns:True iff the image is built successfully."""# system_root_image=true: build a system.img that combines the contents of# /system and the ramdisk, and can be mounted at the root of the file system.origin_in = in_dirfs_config = prop_dict.get("fs_config")base_fs_file = Noneif (prop_dict.get("system_root_image") == "true"and prop_dict["mount_point"] == "system"):in_dir = tempfile.mkdtemp()# Change the mount point to "/"prop_dict["mount_point"] = "/"if fs_config:# We need to merge the fs_config files of system and ramdisk.fd, merged_fs_config = tempfile.mkstemp(prefix="root_fs_config",suffix=".txt")os.close(fd)with open(merged_fs_config, "w") as fw:if "ramdisk_fs_config" in prop_dict:with open(prop_dict["ramdisk_fs_config"]) as fr:fw.writelines(fr.readlines())with open(fs_config) as fr:fw.writelines(fr.readlines())fs_config = merged_fs_configbuild_command = []fs_type = prop_dict.get("fs_type", "")run_fsck = Falsefs_spans_partition = Trueif fs_type.startswith("squash"):fs_spans_partition = Falseis_verity_partition = "verity_block_device" in prop_dictverity_supported = prop_dict.get("verity") == "true"verity_fec_supported = prop_dict.get("verity_fec") == "true"# Adjust the partition size to make room for the hashes if this is to be# verified.if verity_supported and is_verity_partition:partition_size = int(prop_dict.get("partition_size"))(adjusted_size, verity_size) = AdjustPartitionSizeForVerity(partition_size,verity_fec_supported)if not adjusted_size:return Falseprop_dict["partition_size"] = str(adjusted_size)prop_dict["original_partition_size"] = str(partition_size)prop_dict["verity_size"] = str(verity_size)# Adjust partition size for AVB hash footer or AVB hashtree footer.avb_footer_type = ''if prop_dict.get("avb_hash_enable") == "true":avb_footer_type = 'hash'elif prop_dict.get("avb_hashtree_enable") == "true":avb_footer_type = 'hashtree'if avb_footer_type:avbtool = prop_dict["avb_avbtool"]partition_size = prop_dict["partition_size"]# avb_add_hash_footer_args or avb_add_hashtree_footer_args.additional_args = prop_dict["avb_add_" + avb_footer_type + "_footer_args"]max_image_size = AVBCalcMaxImageSize(avbtool, avb_footer_type, partition_size,additional_args)if max_image_size == 0:return Falseprop_dict["partition_size"] = str(max_image_size)prop_dict["original_partition_size"] = partition_sizeif fs_type.startswith("ext"):build_command = [prop_dict["ext_mkuserimg"]]if "extfs_sparse_flag" in prop_dict:build_command.append(prop_dict["extfs_sparse_flag"])run_fsck = Truebuild_command.extend([in_dir, out_file, fs_type,prop_dict["mount_point"]])build_command.append(prop_dict["partition_size"])if "journal_size" in prop_dict:build_command.extend(["-j", prop_dict["journal_size"]])if "timestamp" in prop_dict:build_command.extend(["-T", str(prop_dict["timestamp"])])if fs_config:build_command.extend(["-C", fs_config])if target_out:build_command.extend(["-D", target_out])if "block_list" in prop_dict:build_command.extend(["-B", prop_dict["block_list"]])if "base_fs_file" in prop_dict:base_fs_file = ConvertBlockMapToBaseFs(prop_dict["base_fs_file"])if base_fs_file is None:return Falsebuild_command.extend(["-d", base_fs_file])build_command.extend(["-L", prop_dict["mount_point"]])if "extfs_inode_count" in prop_dict:build_command.extend(["-i", prop_dict["extfs_inode_count"]])if "flash_erase_block_size" in prop_dict:build_command.extend(["-e", prop_dict["flash_erase_block_size"]])if "flash_logical_block_size" in prop_dict:build_command.extend(["-o", prop_dict["flash_logical_block_size"]])# Specify UUID and hash_seed if using mke2fs.if prop_dict["ext_mkuserimg"] == "mkuserimg_mke2fs.sh":if "uuid" in prop_dict:build_command.extend(["-U", prop_dict["uuid"]])if "hash_seed" in prop_dict:build_command.extend(["-S", prop_dict["hash_seed"]])if "selinux_fc" in prop_dict:build_command.append(prop_dict["selinux_fc"])elif fs_type.startswith("squash"):build_command = ["mksquashfsimage.sh"]build_command.extend([in_dir, out_file])if "squashfs_sparse_flag" in prop_dict:build_command.extend([prop_dict["squashfs_sparse_flag"]])build_command.extend(["-m", prop_dict["mount_point"]])if target_out:build_command.extend(["-d", target_out])if fs_config:build_command.extend(["-C", fs_config])if "selinux_fc" in prop_dict:build_command.extend(["-c", prop_dict["selinux_fc"]])if "block_list" in prop_dict:build_command.extend(["-B", prop_dict["block_list"]])if "squashfs_compressor" in prop_dict:build_command.extend(["-z", prop_dict["squashfs_compressor"]])if "squashfs_compressor_opt" in prop_dict:build_command.extend(["-zo", prop_dict["squashfs_compressor_opt"]])if "squashfs_block_size" in prop_dict:build_command.extend(["-b", prop_dict["squashfs_block_size"]])if "squashfs_disable_4k_align" in prop_dict and prop_dict.get("squashfs_disable_4k_align") == "true":build_command.extend(["-a"])elif fs_type.startswith("f2fs"):build_command = ["mkf2fsuserimg.sh"]build_command.extend([out_file, prop_dict["partition_size"]])else:print("Error: unknown filesystem type '%s'" % (fs_type))return Falseif in_dir != origin_in:# Construct a staging directory of the root file system.ramdisk_dir = prop_dict.get("ramdisk_dir")if ramdisk_dir:shutil.rmtree(in_dir)shutil.copytree(ramdisk_dir, in_dir, symlinks=True)staging_system = os.path.join(in_dir, "system")shutil.rmtree(staging_system, ignore_errors=True)shutil.copytree(origin_in, staging_system, symlinks=True)has_reserved_blocks = prop_dict.get("has_ext4_reserved_blocks") == "true"ext4fs_output = Nonetry:if fs_type.startswith("ext4"):(ext4fs_output, exit_code) = RunCommand(build_command)else:(_, exit_code) = RunCommand(build_command)finally:if in_dir != origin_in:# Clean up temporary directories and files.shutil.rmtree(in_dir, ignore_errors=True)if fs_config:os.remove(fs_config)if base_fs_file is not None:os.remove(base_fs_file)if exit_code != 0:return False# Bug: 21522719, 22023465# There are some reserved blocks on ext4 FS (lesser of 4096 blocks and 2%).# We need to deduct those blocks from the available space, since they are# not writable even with root privilege. It only affects devices using# file-based OTA and a kernel version of 3.10 or greater (currently just# sprout).# Separately, check if there's enough headroom space available. This is useful for# devices with low disk space that have system image variation between builds.if (has_reserved_blocks or "partition_headroom" in prop_dict) and fs_type.startswith("ext4"):assert ext4fs_output is not Noneext4fs_stats = re.compile(r'Created filesystem with .* (?P<used_blocks>[0-9]+)/'r'(?P<total_blocks>[0-9]+) blocks')m = ext4fs_stats.match(ext4fs_output.strip().split('\n')[-1])used_blocks = int(m.groupdict().get('used_blocks'))total_blocks = int(m.groupdict().get('total_blocks'))reserved_blocks = 0headroom_blocks = 0adjusted_blocks = total_blocksif has_reserved_blocks:reserved_blocks = min(4096, int(total_blocks * 0.02))adjusted_blocks -= reserved_blocksif "partition_headroom" in prop_dict:headroom_blocks = int(prop_dict.get('partition_headroom')) / BLOCK_SIZEadjusted_blocks -= headroom_blocksif used_blocks > adjusted_blocks:mount_point = prop_dict.get("mount_point")print("Error: Not enough room on %s (total: %d blocks, used: %d blocks, ""reserved: %d blocks, headroom: %d blocks, available: %d blocks)" % (mount_point, total_blocks, used_blocks, reserved_blocks,headroom_blocks, adjusted_blocks))return Falseif not fs_spans_partition:mount_point = prop_dict.get("mount_point")partition_size = int(prop_dict.get("partition_size"))image_size = GetSimgSize(out_file)if image_size > partition_size:print("Error: %s image size of %d is larger than partition size of ""%d" % (mount_point, image_size, partition_size))return Falseif verity_supported and is_verity_partition:ZeroPadSimg(out_file, partition_size - image_size)# create the verified image if this is to be verifiedif verity_supported and is_verity_partition:if not MakeVerityEnabledImage(out_file, verity_fec_supported, prop_dict):return False# Add AVB HASH or HASHTREE footer (metadata).if avb_footer_type:avbtool = prop_dict["avb_avbtool"]original_partition_size = prop_dict["original_partition_size"]partition_name = prop_dict["partition_name"]# key_path and algorithm are only available when chain partition is used.key_path = prop_dict.get("avb_key_path")algorithm = prop_dict.get("avb_algorithm")salt = prop_dict.get("avb_salt")# avb_add_hash_footer_args or avb_add_hashtree_footer_argsadditional_args = prop_dict["avb_add_" + avb_footer_type + "_footer_args"]if not AVBAddFooter(out_file, avbtool, avb_footer_type, original_partition_size,partition_name, key_path, algorithm, salt, additional_args):return Falseif run_fsck and prop_dict.get("skip_fsck") != "true":success, unsparse_image = UnsparseImage(out_file, replace=False)if not success:return False# Run e2fsck on the inflated image filee2fsck_command = ["e2fsck", "-f", "-n", unsparse_image](_, exit_code) = RunCommand(e2fsck_command)os.remove(unsparse_image)return exit_code == 0

这里面有一堆的参数,其实都非常有深意后,我们在学习阶段可以不必考虑,当我们遇到相关问题时,那时可能就会对照这些参数,了解其功能和作用。 而我们这里重点查看的,如下:

 if prop_dict["ext_mkuserimg"] == "mkuserimg_mke2fs.sh":if "uuid" in prop_dict:build_command.extend(["-U", prop_dict["uuid"]])if "hash_seed" in prop_dict:build_command.extend(["-S", prop_dict["hash_seed"]])

这里是执行了mkuserimg_mke2fs.sh脚本,我们再去看看这个脚本吧
路径:system/extras/ext4_utils/mkuserimg_mke2fs.sh
同样,打开该文件后发现又是一堆的参数命令,看也看不懂,我们依然只是关心其核心的部分,截取如下:

MAKE_EXT4FS_CMD="mke2fs $MKE2FS_OPTS -t $EXT_VARIANT -b $BLOCKSIZE $OUTPUT_FILE $SIZE"
echo $MAKE_EXT4FS_ENV $MAKE_EXT4FS_CMD
env $MAKE_EXT4FS_ENV $MAKE_EXT4FS_CMD
if [ $? -ne 0 ]; thenexit 4
fiif [[ $E2FSPROGS_FAKE_TIME ]]; thenE2FSDROID_ENV="E2FSPROGS_FAKE_TIME=$E2FSPROGS_FAKE_TIME"
fiE2FSDROID_CMD="e2fsdroid $E2FSDROID_OPTS -f $SRC_DIR -a $MOUNT_POINT $OUTPUT_FILE"
echo $E2FSDROID_ENV $E2FSDROID_CMD
env $E2FSDROID_ENV $E2FSDROID_CMD
if [ $? -ne 0 ]; thenrm -f $OUTPUT_FILEexit 4
fi

这里做了两件事:
(1)mke2fs打包生成了system.img
(2)e2fsdroid制作了system.map
mke2fs对应的源码:external/e2fsprogs/misc/mke2fs.c
e2fsdroid对应的源码 : external/e2fsprogs/contrib/android/e2fsdroid.c

深思:
其实呢,在正常的android编译,并不会生成system.map,因为最后一个参数$OUTPUT_FILE为空. 在android的设计中system.map是在制作OTA的target-files文件时生成的,然后在制作block差分别时候,会用到system.map,一个block一个block的去求diff。
在制作OTA的target-files时,会重新打包system.img,其流程:
add_img_to_target_files直接调用了build_image.py中的CreateImage()函数,与正常的打包system.img参数稍微不同,这里增加了一个block_list="system.map"参数,所以其打包结束后,生成了system.map

Q & A:
1、system.img是怎样制作的?
答:使用mke2fs工具制作的
2、system.map是做什么用的?先有的system.img,还是先用的system.map?
答:system.map是制作OTA的target-files文件时,重新打包system.img后,根据system.img做出的system.map,制作差分别时候,会用到system.map文件

不足之处,欢迎指正!

System.img是如何打包的相关推荐

  1. android系统system镜像解包打包制作过程

    ** android系统system镜像解包打包制作过程 首先确认你的system是哪种类型镜像:yaffs2 ? 还是sparse? 这两种镜像使用的解包工具也不一样,下面以sparse类型镜像描述 ...

  2. system.img解包打包工具

    最近需要对system.img进行解包,修改系统属性和添加自己的APK,再打包烧录,整理俩个方法. system.img解包打包工具方法一 1.把system.img转换成ext4格式 ./simg2 ...

  3. linux环境systwm.img解包,[教程] system.img解包打包的方法,方便菜鸟们制作直刷ROM...

    操作系统:ubuntu10.10可虚拟机可其他linux可其他版本 & Windows 7 Ubuntu下操作: 下载unyaffs和yaffs2.tar.gz,并编译yaffs2再复制到/b ...

  4. system.img解包打包工具_好程序员云计算学习路线分享文件打包及压缩

    好程序员云计算学习路线分享文件打包及压缩 好程序员 建议针对目录 Demo: 复制未打包的文件到远程主机 [root@yangs ~]# du -sh /etc 39M /etc [root@yang ...

  5. Android 系统(137)---android打包解包boot.img,system.img

    android打包解包boot.img,system.img 2017年04月28日 15:00:36 阅读数:1822 原帖地址:http://www.52pojie.cn/thread-48802 ...

  6. Image打包流程-Android10.0编译系统(四)

    摘要:本节主要来进行Android10.0 Image打包流程,理解system.img是如何打包的 阅读本文大约需要花费28分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源 ...

  7. 压缩base 64字符串_ftp下载多个文件,ftp下载多个文件打包成一个压缩包

    在一些日常的网络批量维护工作中,经常需要使用ftp计划任务,定时上传或下载多个文件.对不太了解ftp命令和windows计划任务的新手来说,确实是一个很棘手的问题.今天我们来看看如何简单的实现这功能. ...

  8. linux rom打包工具,Android rom解包打包工具

    eMMC主要是针对手机和平板电脑等产品的内嵌式存储器,由于其在封装中集成了一个控制器,且提供标准接口并管理闪存等优势,越来越受到Android手机厂商的青睐,以eMMC为存储设备的android手机, ...

  9. FTP下载多个文件打包成一个压缩包

    @RequestMapping("downloadsByplFromFTP")     @ResponseBody     public  void downloadsByplFr ...

最新文章

  1. 跨域请求获取Solr json检索结果并高亮显示
  2. Java实现CSV读写操作源代码
  3. 局域网聊天程序 java MySQL_课内资源 - 基于JAVA的局域网聊天软件的设计与实现(仿制QQ)...
  4. 芬兰诺基亚获得三个欧洲市场的5G订单
  5. 回家_洛谷U3427_dfsbfs
  6. 手动安装Apache+PHP+MYSQL及环境配置
  7. Matlab 2021b安装
  8. shred如果说它Linux系统是文件粉碎机它就更有名了
  9. 英文大写字母A~Z,小写字母a~z对应的ASCII码快速查询
  10. Hibernate源码解析
  11. win服务器系统无法切换输入法,win8系统中文输入法切换不出来
  12. over()分析函数
  13. win10并排显示窗口怎么不能占据全屏
  14. 计算机课件制作ppt,计算机应用基础_幻灯片制作ppt课件
  15. 第二章:1、复合函数求导
  16. python数据分析 - numpy | ndarray数组 | numpy常用函数
  17. taobao.user.avatar.get
  18. SNIPER python3.5环境配置成功记录
  19. 五子棋-进阶版:C#窗体编写
  20. 上手即用亏大了!教你发掘Win10真正的好用之处

热门文章

  1. 数据中心日常维护工作有哪些?
  2. java if赋值语句_Java基础第3天+运算符(算术运算符、赋值运算符、比较运算符、逻辑运算符、位运算符、三元运算符)、Scanner键盘录入、if语句...
  3. DL中版本配置问题:TensorFlow、Keras、Python版本完美搭配推荐
  4. 成功解决UserWarning: Update your `Conv2D` call to the Keras 2 API问题
  5. 成功解决sklearn\grid_search.py:42: DeprecationWarning: This module was deprecated in version 0.18 in fav
  6. 成功解决SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame See
  7. 计算机视觉的基石-滤波
  8. Python常用扩展包
  9. 简单分析synchronized不会锁泄漏的原因
  10. 第三次作业-介绍一款原型设计工具