[文章]OpenHarmony-3.0 编译构建流程

阅读量0
0
5
前言
OpenHarmony-2.0 编译构建流程
早就打算研究下OH3.0的编译框架了,最近一直在搞移植,总算有点进展了,抽个空来分析下3.0的编译框架。大体看了下和2.0的差别不是特别大,OHOS3.0的打包镜像脚本由原来2.0的buildadapterbuild_image.sh 全部修改替换为 buildohosimagesbuild_image.py 将打包image镜像的部分制作成build_target,以前是通过shell脚本来调用,现在是通过gn和ninja来调用。主要文件在buildohosimages这个文件夹下。没有修改的部分就不说了,有需要的可以看我之前的帖子 这篇主要说下不一样的地方,看OH3.0是如何将编译好的文件打包成镜像的。
一、增加编译参数
3.0之后在buildbuild_scriptsbuild_common.sh 增加了 build_cmd+=" build_target=images",这句的意思约等于在执行默认编译命令 ./build.sh --product-name Hi3516DV300 会有个默认的参数 --build-target images,具体流程是这样的:
buildbuild_scriptsbuild_common.sh => buildcoregnBUILD.gn => buildohosimagesBUILD.gn
  1. action_with_pydeps("${_platform}_${_image_name}_image") {
  2.     script = "//build/ohos/images/build_image.py"
  3.     depfile = "$target_gen_dir/$target_name.d"
  4.     deps = [ "//build/ohos/packages:${_platform}_install_modules" ]

  5.     image_config_file =
  6.     "//build/ohos/images/mkimage/${_image_name}_image_conf.txt"
  7.     output_image_file = "$current_platform_dir/images/${_image_name}.img"

  8.     image_input_path = "$current_platform_dir/${_image_name}"
  9.     if (_image_name == "userdata") {
  10.         image_input_path = "$current_platform_dir/data"
  11.     }

  12.     sources = [
  13.         image_config_file,
  14.         system_module_info_list,
  15.         system_modules_list,
  16.     ]
  17.     outputs = [ output_image_file ]
  18.     args = [
  19.         "--depfile",
  20.         rebase_path(depfile, root_build_dir),
  21.         "--image-name",
  22.         _image_name,
  23.         "--input-path",
  24.         rebase_path(image_input_path, root_build_dir),
  25.         "--image-config-file",
  26.         rebase_path(image_config_file, root_build_dir),
  27.         "--output-image",
  28.         rebase_path(output_image_file, root_build_dir),
  29.         "--build-image-tools-path",
  30.         rebase_path(build_image_tools_path, root_build_dir),
  31.     ]
  32.     if (sparse_image) {
  33.         args += [ "--sparse-image" ]
  34.     }
  35. }
复制代码

通常情况下,gn会使用 action 运行一个脚本来生成一个文件,但是这里使用的是 action_with_pydeps,应该也是内置的目标类型。查看官方手册是这么说明的
Inputs and Depfiles
List all files read (or executed) by an action as inputs.
  • It is not enough to have inputs listed by dependent targets. They must be listed directly by targets that use them, or added by a depfile.
  • Non-system Python imports are inputs! For scripts that import such modules, use action_with_pydeps to ensure all dependent Python files are captured as inputs.


前面还定义了一个image_list,然后使用 foreach 执行 action_with_pydeps,要生成几个img文件,就执行几次action_with_pydeps。

  1.   image_list = [
  2.     "system",
  3.     "vendor",
  4.     "userdata",
  5.     "updater",
  6.   ]
  7.   foreach(_image_name, image_list) {... ...}
复制代码

二、调用python脚本
既然知道了img镜像是由 buildohosimagesbuild_image.py 来创建的,那就来分析下这个python脚本。
  1.     if os.path.exists(args.output_image_path):
  2.         os.remove(args.output_image_path)                        # 删除之前生成的镜像文件夹
  3.     if args.image_name == 'userdata':
  4.         _prepare_userdata(args.input_path)                        # 准备好 userdata.img 需要的文件
  5.     if os.path.isdir(args.input_path):
  6.         _make_image(args)
  7.         _dep_files = []
  8.         for _root, _, _files in os.walk(args.input_path):
  9.             for _file in _files:
  10.                 _dep_files.append(os.path.join(_root, _file))
  11.         build_utils.write_depfile(args.depfile,
  12.                                   args.output_image_path,
  13.                                   _dep_files,
  14.                                   add_pydeps=False)
  15. ===================================================================

  16. <!--StartFragment--><!--EndFragment-->
  17. def _make_image(args):
  18.     if args.image_name == 'system':
  19.         _prepare_root(args.input_path)                                # 准备好 system.img 需要的文件
  20.     elif args.image_name == 'updater':
  21.         _prepare_updater(args.input_path)                        # 准备好 updater.img 需要的文件
  22.     image_type = "raw"
  23.     if args.sparse_image:
  24.         image_type = "sparse"
  25.     mk_image_args = [
  26.         args.input_path, args.image_config_file, args.output_image_path,
  27.         image_type
  28.     ]
  29.     env_path = "../../build/ohos/images/mkimage"
  30.     if args.build_image_tools_path:
  31.         env_path = '{}:{}'.format(env_path, args.build_image_tools_path)
  32.     os.environ['PATH'] = '{}:{}'.format(env_path, os.environ.get('PATH'))
  33.     mkimages.mk_images(mk_image_args)                        # 而真正制作镜像使用的下面的函数
  34. ===================================================================

  35. <!--StartFragment--><!--EndFragment-->
  36. # buildohosimagesmkimagemkimages.py
  37. def mk_images(args):
  38.     ... ...
  39.     if "system.img" in device:
  40.         src_dir = build_rootdir(src_dir)
  41.     mkfs_tools, mk_configs = load_config(config_file)
  42.     mk_configs = src_dir + " " + device + " " + mk_configs

  43.     res = run_cmd(mkfs_tools + " " + mk_configs)        # 制作镜像命令使用的是mkfs_tools
  44. ===================================================================

  45. <!--StartFragment--><!--EndFragment-->
  46.     if "ext4" in mk_configs:
  47.         fs_type = "ext4"
  48.         mkfs_tools = "mkextimage.py"                                # 而mkfs_tools根据文件系统类型,分别调用对应的python脚本
  49.     elif "f2fs" in mk_configs:
  50.         mkfs_tools = "mkf2fsimage.py"
  51.         fs_type = "f2fs"
  52. ===================================================================
  53. # buildohosimagesmkimagemkextimage.py # 制作ext4文件系统
  54. def build_run_mke2fs(args):
  55.     .. ...
  56.     blocks = int(int(args.fs_size) / BLOCKSIZE)
  57.     mke2fs_cmd += ("mke2fs " + str(mke2fs_opts) + " -t " + FS_TYPE + " -b "
  58.                    + str(BLOCKSIZE) + " " + args.device + " " + str(blocks))
  59.     res = run_cmd(mke2fs_cmd)                # mke2fs:制作文件系统
  60. ===================================================================

  61. <!--StartFragment--><!--EndFragment-->
  62. def build_run_e2fsdroid(args):
  63.         ... ...
  64.     e2fsdroid_cmd += ("e2fsdroid" + e2fsdroid_opts + " -f " +
  65.                       args.src_dir + " -a " + args.mount_point +
  66.                       " " + args.device)
  67.     res = run_cmd(e2fsdroid_cmd)        # e2fsdroid:制作镜像文件  
复制代码

无论前面执行了什么操作,最终都是为了执行mke2fs、e2fsdroid。
关于这两个命令:
mke2fs:Linux下的命令,用于建立ext文件系统。
e2fsdroid:来自三方库,third_partye2fsprogs。详情可以参考 http://e2fsprogs.sourceforge.net

回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友