赞
踩
云将东游,过扶摇之枝,而适遭鸿蒙。—《庄子·在宥》
OpenHarmony构建工具由shell(.sh)、python(.py)、gn(.gn/.gni)、ninja(.ninja)、clang/llvm、gcc等构成。编译过程中有大量的python命令都是通过importlib.import_module方式导入(比如hb build/ hb set/ hb clean),对分析编译过程增加了一定的难度。本文以 OpenHarmony-v3.2.4-release为例,附上
OpenHarmony-v3.2.4-release下载链接。
OpenHarmony编译完成后镜像img文件所在的目录out/{product_name}/packages/phone/images。
out/rk3568/packages/phone/images# ls -al
-rw-r--r-- 1 root root 67108864 1月 7 10:00 boot_linux.img
-rw-r--r-- 1 root root 52428800 1月 7 12:52 chip_prod.img
-rw-r--r-- 1 root root 7959 1月 7 10:00 config.cfg
-rw-r--r-- 1 root root 455104 1月 7 10:00 MiniLoaderAll.bin
-rw-r--r-- 1 root root 655 1月 7 10:00 parameter.txt
-rw-rw-r-- 1 root root 2265062 1月 7 12:52 ramdisk.img
-rw-r--r-- 1 root root 5639680 1月 7 10:00 resource.img
-rw-r--r-- 1 root root 52428800 1月 7 12:52 sys_prod.img
-rw-r--r-- 1 root root 1610608640 1月 7 12:52 system.img
-rwxr-xr-x 1 root root 4194304 1月 7 10:00 uboot.img
-rw-rw-r-- 1 root root 10323639 1月 7 12:52 updater.img
-rw-r--r-- 1 root root 1468006400 1月 7 12:52 userdata.img
-rw-r--r-- 1 root root 268431360 1月 7 12:52 vendor.img
镜像名称 | 文件格式 | 文件说明 |
---|---|---|
boot_linux.img | ext2 | linux内核 |
chip_prod.img | ext2 | 芯片相关 |
MiniLoaderAll.bin | 二进制 | 二进制镜像 |
ramdisk.img | gzip压缩cpio | ram disk |
resource.img | 二进制 | 资源文件 |
sys_prod.img | ext2 | 产品相关 |
system.img | ext2 | 系统文件 |
uboot.img | 二进制 | boot |
updater.img | ext2 | 升级文件 |
userdata.img | ext2 | 用户数据 |
vendor.img | ext2 | 厂商 |
config.cfg | 配置文件 | 配置文件 |
parameter.txt | 文本格式 | 分区文件 |
镜像文件格式可以使用file命令进行查看,如果是二进制格式则显示data类型
packages/phone/images# file boot_linux.img chip_prod.img MiniLoaderAll.bin ramdisk.img resource.img sys_prod.img system.img uboot.img updater.img userdata.img vendor.img
boot_linux.img: Linux rev 0.0 ext2 filesystem data, UUID=00000000-0000-0000-0000-000000000000
chip_prod.img: Linux rev 1.0 ext2 filesystem data, UUID=9972d61c-2903-4218-b280-c0bc5228266d (extents) (64bit) (large files) (huge files)
MiniLoaderAll.bin: data
ramdisk.img: gzip compressed data, was "ramdisk.img", last modified: Tue Dec 26 06:16:21 2023, from Unix, original size modulo 2^32 4331520
resource.img: data
sys_prod.img: Linux rev 1.0 ext2 filesystem data, UUID=0a2da78c-c4ab-44a7-b1c8-8383098758e4 (extents) (64bit) (large files) (huge files)
system.img: Linux rev 1.0 ext2 filesystem data, UUID=a2757491-4407-4139-aa26-4cac86a28ec0 (extents) (64bit) (large files) (huge files)
uboot.img: Device Tree Blob version 17, size=2560, boot CPU=0, string block size=197, DT structure block size=1964
updater.img: gzip compressed data, was "updater.img", last modified: Tue Dec 26 06:16:21 2023, from Unix, original size modulo 2^32 18057216
userdata.img: F2FS filesystem, UUID=cf1dd758-c179-4876-9518-54ee72d3f9e9, volume name "/data"
vendor.img: Linux rev 1.0 ext2 filesystem data, UUID=21ef10b2-6522-4980-bc55-79a54d4a8d0f (extents) (64bit) (large files) (huge files)
boot_linux.img为ext2格式,可以在编译电脑上进行解包,操作命令如下
/out/rk3568/packages/phone/images# mkdir boot_linux
/out/rk3568/packages/phone/images# mount -o loop boot_linux.img boot_linux
/out/rk3568/packages/phone/images# cd boot_linux
/out/rk3568/packages/phone/images/boot_linux# ls -al
total 8708
drwxr-xr-x 4 root root 4096 12月 16 13:57 .
drwxr-xr-x 3 root root 4096 12月 27 10:51 ..
drwxr-xr-x 2 root root 4096 12月 16 13:57 extlinux
-rwxr-xr-x 1 root root 2764854 12月 16 13:57 logo.bmp
-rwxr-xr-x 1 root root 2764854 12月 16 13:57 logo_kernel.bmp
drwx------ 2 root root 3354624 12月 16 13:57 lost+found
system.img为ext2格式,可以在编译电脑上进行解包,操作命令如下
/out/rk3568/packages/phone/images# mkdir system /out/rk3568/packages/phone/images# mount -o loop system.img system /out/rk3568/packages/phone/images# cd system /out/rk3568/packages/phone/images/system# ls -al total 76 drwxr-xr-x. 16 root root 4096 12月 26 14:16 . drwxr-xr-x 4 root root 4096 12月 27 10:54 .. lrw-r--r--. 1 root root 11 12月 26 14:16 bin -> /system/bin drwxr-xr-x. 2 2000 root 4096 12月 26 14:16 chip_prod lrw-r--r--. 1 root root 7 12月 26 14:16 chipset -> /vendor dr-xr-xr-x. 2 root root 4096 12月 26 14:16 config drwxrwx--x. 2 hxd root 4096 12月 26 14:16 data drwxr-xr-x. 2 root root 4096 12月 26 14:16 dev lrw-r--r--. 1 root root 11 12月 26 14:16 etc -> /system/etc lrw-r--r--. 1 root root 16 12月 26 14:16 init -> /system/bin/init lrw-r--r--. 1 root root 11 12月 26 14:16 lib -> /system/lib drwx------. 2 root root 16384 12月 26 14:16 lost+found drwxr-xr-x. 2 hxd root 4096 12月 26 14:16 mnt drwxr-xr-x. 2 root root 4096 12月 26 14:16 proc drwxr-xr-x. 2 root root 4096 12月 26 14:16 storage drwxr-xr-x. 2 root root 4096 12月 26 14:16 sys drwxr-xr-x. 2 2000 root 4096 12月 26 14:16 sys_prod drwxr-xr-x. 9 root root 4096 12月 26 14:16 system drwxr-xr-x. 2 root root 4096 12月 26 14:16 tmp drwxr-xr-x. 2 root root 4096 12月 26 14:16 updater drwxr-xr-x. 2 2000 root 4096 12月 26 14:16 vendor
ramdisk.img为压缩的cpio格式,先使用gzip进行解压缩,然后使用cpio进行挂载,操作如下
/out/rk3568/packages/phone/images# cp ramdisk.img ramdisk.img.gz //加上.gz后缀 /out/rk3568/packages/phone/images# mv ramdisk.img ramdisk.img.compile //备份原始镜像 /out/rk3568/packages/phone/images# gzip -d ramdisk.img.gz //解压缩镜像 /out/rk3568/packages/phone/images# file ramdisk.img //查看镜像格式 ramdisk.img: ASCII cpio archive (SVR4 with no CRC) /out/rk3568/packages/phone/images# cp ramdisk.img ramdisk /out/rk3568/packages/phone/images# cd ramdisk /out/rk3568/packages/phone/images# mkdir ramdisk /out/rk3568/packages/phone/images/ramdisk# cpio -idmv < ramdisk.img . lib lib/libc.so lib/libinit_module_engine.so lib/libclang_rt.asan.so lib/libselinux.z.so sys dev storage mnt usr init system etc bin bin/mknod proc
当在源代码目录下输入./build.sh --product-name rk3568 --ccache
都发生了什么?整个编译过程又是怎样的?本章将为您进行详细分析。源码目录下build.sh为软链接,其真实文件为./build/build_scripts/build.sh。
//build.sh
--product-name rk3568 --ccache
#检查工具链脚本build/scripts/tools_checker.py
${PYTHON3} ${source_root_dir}/build/scripts/tools_checker.py
#启动编译build/scripts/entry.py
${PYTHON3} ${source_root_dir}/build/scripts/entry.py --source-root-dir ${source_root_dir} $@
#上面命令替换成如下
#//build/scripts/entry.py --source-root-dir /usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony --product-name rk3568 --ccache
#执行结果判断
if [[ "$?" -ne 0 ]]; then #如果上条命令(build/scripts/entry.py)的返回值非0
echo -e "\033[31m=====build ${product_name} error=====\033[0m" #输出编译错误提示,\033[31m 用于控制输出显示字符颜色为红色
exit 1 #退出
fi
echo -e "\033[32m=====build ${product_name} successful=====\033[0m" #输出编译成功提示,\033[32m 用于控制输出显示字符颜色为绿色
//build/scripts/entry.py
--source-root-dir /usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony --product-name rk3568 --ccache
def check_output(cmd, **kwargs): process = subprocess.Popen(cmd, #启动子进程 stdout=subprocess.PIPE, #子进程标准输出到管道 stderr=subprocess.STDOUT, #子进程错误输出到显示器 universal_newlines=True, **kwargs) #父进程继续执行下面代码,通过iter循环读取子进程输出,写入标准输出即显示器。iter循环结束条件是缓冲区为空 for line in iter(process.stdout.readline, ''):#父进程循环读取子进程管道输出 sys.stdout.write(line) #父将子进程输出写入到标准输出 sys.stdout.flush() #父将子进程输出刷新到标准输出 process.wait() #等待子进程结束 return process.returncode def do_build(args): build_py = os.path.join(args.source_root_dir, 'build.py') cmd = [ 'python3', build_py, '-p', args.product_name, ] if args.disable_part_of_post_build: ... try: #cmd=['python3', '/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/build.py', '-p', 'rk3568', '--device-type=default', '--build-variant=root'] return check_output(cmd) #调用check_output def main(): ..... return do_build(args) #调用do_build if __name__ == '__main__': #判断结果为真 sys.exit(main()) #调用main函数
//build.py
-p rk3568 --device-type=default --build-variant=root
def check_output(cmd, **kwargs): process = subprocess.Popen(cmd, #启动子进程 stdout=subprocess.PIPE, #子进程标准输出到管道 stderr=subprocess.STDOUT, #子进程错误输出到显示器 universal_newlines=True, **kwargs) #父进程继续执行下面代码,通过iter循环读取子进程输出,写入标准输出即显示器。iter循环结束条件是缓冲区为空 for line in iter(process.stdout.readline, ''):#父进程循环读取子进程管道输出 sys.stdout.write(line) #父将子进程输出写入到标准输出 sys.stdout.flush() #父将子进程输出刷新到标准输出 process.wait() #等待子进程结束 ret_code = process.returncode return ret_code def set_root_path(path): sys.path.insert(0, os.path.join(path, 'build/lite')) module = importlib.import_module('hb_internal.set.set') #导入build/lite/hb_internal/set/set.py return module.set_root_path(root_path=path) def build(path, args_list): python_executable = get_python() cmd = [python_executable, 'build/lite/hb/__main__.py', 'build'] + args_list #cmd=['/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/prebuilts/python/linux-x86/3.9.2/bin/python3', 'build/lite/hb/__main__.py', 'build', '-p', 'rk3568', '--device-type=default', '--build-variant=root'] return check_output(cmd, cwd=path) #调用check_output函数 def main(): root_path = os.path.dirname(os.path.abspath(__file__)) ret_code = set_root_path(root_path) #调用set_root_path函数 if ret_code != 0: return ret_code return build(root_path, sys.argv[1:]) #调用build函数 if __name__ == "__main__": sys.exit(main())
//build/lite/hb/__main__.py
build -p rk3568 -device-type=default --build-variant=root
EXECV_FRAGMENT = """ import sys import importlib sys.path.append(sys.argv.pop()) entry = importlib.import_module("__entry__") #导入模块 sys.exit(entry.main()) """ def main(): try: topdir = find_top() except Exception as ex: return print("hb_error: Please call hb utilities inside source root directory") python_base_dir = os.path.join(topdir, 'prebuilts/python') if os.path.exists(python_base_dir): python_dir = search(python_base_dir, 'python3') python_executable = os.path.join(python_dir, 'python3') lite_dir = os.path.join(topdir, 'build/lite') hb_dir = search(lite_dir, '__entry__.py') param_list = ["python3", "-c", EXECV_FRAGMENT] for arg in sys.argv[1:]: param_list.append(arg) param_list.append(hb_dir) os.environ['PATH'] = python_dir + ":" + os.getenv('PATH') #/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/prebuilts/python/linux-x86/3.9.2/bin/python3 ['python3', '-c', '\nimport sys\nimport importlib\n\nsys.path.append(sys.argv.pop())\nentry = importlib.import_module("__entry__")\nsys.exit(entry.main())\n', 'build', '-p', 'rk3568', '--device-type=default', '--build-variant=root', '/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/build/lite/hb'] os.execv(python_executable, param_list) #第一个参数表示执行程序的路径,第二个参数为列表格式,不定长度,为想要执行程序的system argument参数,自动忽略列表中第一个参数,-c从第二个参数开始 if __name__ == "__main__": #判断结果为真 sys.exit(main()) #调用main函数
build/lite/hb/entry.py
def main(): try: topdir = find_top() except Exception as ex: return print("hb_error: Please call hb utilities inside source root directory") sys.path.insert(0, os.path.join(topdir, 'build/lite')) parser = argparse.ArgumentParser(description='OHOS Build System ' f'version {VERSION}') parser.add_argument('-v', '--version', action='version', version=f'[OHOS INFO] hb version {VERSION}') subparsers = parser.add_subparsers() parser_list = [] command_set = get_hb_commands(os.path.join(topdir, 'build/lite/hb_internal/hb_command_set.json')) #json存储需要导入命令列表和命令对应的描述 for key, val in command_set.items(): parser_list.append({'name': key, 'help': val}) for each in parser_list: module_parser = subparsers.add_parser(name=each.get('name'), help=each.get('help')) module = importlib.import_module('hb_internal.{0}.{0}'.format( each.get('name'))) #将hb_internal文件夹下的build、set、env、clear、tool命令一一导入 module.add_options(module_parser) module_parser.set_defaults(parser=module_parser, command=module.exec_command) args = parser.parse_known_args() module = importlib.import_module('hb_internal.common.utils') hb_error = getattr(module, 'hb_error') hb_warning = getattr(module, 'hb_warning') ohos_exception = getattr(module, 'OHOSException') try: if args[0].parser.prog == 'hb set' and 'root_path' in vars(args[0]): # Root_path is topdir. args[0].root_path = topdir if "tool" in args[0].parser.prog: status = args[0].command(args) else: #args[0]=Namespace(component=[], build_type=['debug'], compiler=['clang'], test=None, target_cpu='', compile_config=False, dmverity=False, tee=False, product=['rk3568'], full=False, ndk=False, target=[], verbose=False, sign_haps_by_server=False, patch=False, compact_mode=True, gn_args='', keep_ninja_going=False, build_only_gn=False, log_level='info', fast_rebuild=False, disable_package_image=False, disable_post_build=False, disable_part_of_post_build=[], device_type='default', build_variant='root', share_ccache='', parser=ArgumentParser(prog='-c build', usage=None, description=None, formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True), command=<function exec_command at 0x7f2e6c9ec160>) status = args[0].command(args[0]) #执行build/lite/hb/hb_internal/build/build.py参数如上 except KeyboardInterrupt: hb_warning('User Abort') status = -1 except ohos_exception as exception: hb_error(exception.args[0]) status = -1 except Exception as exception: if not hasattr(args[0], 'command'): parser.print_help() else: hb_error(traceback.format_exc()) hb_error(f'Unhandled error: {exception}') status = -1 return status if __name__ == "__main__": #importlib 调用次文件,判断为false sys.exit(main())
build/lite/hb/hb_internal/build/build.py
Namespace(component=[], build_type=[‘debug’], compiler=[‘clang’], test=None, target_cpu=‘’, compile_config=False, dmverity=False, tee=False, product=[‘rk3568’], full=False, ndk=False, target=[], verbose=False, sign_haps_by_server=False, patch=False, compact_mode=True, gn_args=‘’, keep_ninja_going=False, build_only_gn=False, log_level=‘info’, fast_rebuild=False, disable_package_image=False, disable_post_build=False, disable_part_of_post_build=[], device_type=‘default’, build_variant=‘root’, share_ccache=‘’, parser=ArgumentParser(prog=‘-c build’, usage=None, description=None, formatter_class=<class ‘argparse.HelpFormatter’>, conflict_handler=‘error’, add_help=True), command=<function exec_command at 0x7f2e6c9ec160>)
def exec_command(args):
if len(args.product):
if '@' in args.product[0]:
product, company = args.product[0].split('@')
else:
product = args.product[0]
company = None
set_product(product_name=product, company=company)
build = Build(args.component, args.compact_mode) #创建Build类build对象
....
return build.build(args.full,
patch=args.patch,
cmd_args=cmd_args,
ninja=ninja)
build/lite/hb/hb_internal/build/build_process.py
build_process.py是编译核心流程包含:PreBuild、Patch、Preloader、self.gn_build
、self.ninja_build
class Build(): ........ def build(self, full_compile, patch=False, ninja=True, cmd_args=None): cmd_list = self.get_cmd(full_compile, patch, ninja, cmd_args)//获取编译列表 if cmd_args.get('disable_part_of_post_build'): disable_post_build_args = cmd_args['disable_part_of_post_build'] else: disable_post_build_args = [] try: for exec_cmd in cmd_list: print("\033[93m build_process.py line 153 {0}--{1} \033[0m".format exec_cmd(cmd_args) #遍历执行命令列表 except OHOSException: raise except Exception: raise else: if not cmd_args.get('disable_post_build'): print("\033[93m build_process.py line 161 start postbuild\033[0m") post_build = PostBuild(self.config) if not cmd_args.get('disable_package_image'): print("\033[93m build_process.py line 165 start package_image\033[0m") post_build.package_image() if not disable_post_build_args or 'output_part_rom_status' not in disable_post_build_args: print("\033[93m build_process.py line 168 start romstatus\033[0m") output_part_rom_status(self.config.root_path) finally: if not cmd_args.get('disable_post_build'): if 'post_build' not in locals(): print("\033[93m build_process.py line 172 start postbuild\033[0m") post_build = PostBuild(self.config) print("\033[93m build_process.py line 174 start clean \033[0m") post_build.clean(self.start_time, disable_post_build_args) hb_info(f'{os.path.basename(self.config.out_path)} build success') hb_info(f'cost time: {self.build_time}') return 0 def get_cmd(self, full_compile, patch, ninja, cmd_args): cmd_list = [] if not cmd_args.get('fast_rebuild'): pre_build = PreBuild(self.config) cmd_list.append(pre_build.prepare) if patch: patch = Patch() cmd_list.append(patch.patch_make) if not cmd_args.get('fast_rebuild'): preloader = Preloader(self.config) cmd_list.append(preloader.run) # if full_compile is set, remove out and do full build # if build_only_gn is set, only do gn parse # else do incremental build. if full_compile: remove_path(self.config.out_path) makedirs(self.config.out_path, exist_ok=True) if not cmd_args.get('fast_rebuild'): cmd_list.append(self.gn_build) cmd_list.append(self.ninja_build) elif not ninja: makedirs(self.config.out_path, exist_ok=True) if not cmd_args.get('fast_rebuild'): cmd_list.append(self.gn_build) return cmd_list else: makedirs(self.config.out_path, exist_ok=True) if not cmd_args.get('fast_rebuild'): cmd_list.append(self.gn_build) cmd_list.append(self.ninja_build) return cmd_list def gn_build(self, cmd_args): # Gn cmd init and execute ...... print("\033[93mbuild_process.py line 259 {0}--{1}--{2}\033[0m".format(gn_cmd, self.config.log_path,self.env())) exec_command(gn_cmd, log_path=self.config.log_path, env=self.env()) def ninja_build(self, cmd_args): ....... print("\033[93mbuild_process.py line 290 {0}--{1}--{2}\033[0m".format(ninja_cmd, self.config.log_path,self.env())) exec_command(ninja_cmd, log_path=self.config.log_path, log_filter=True, env=self.env())
以上注释部分打印如下
build_process.py line 153 <bound method PreBuild.prepare of <hb_internal.common.misc.PreBuild object at 0x7f3fb12ed1f0>>--defaultdict(None, {'gn': [], 'ninja': {'default_target': 'packages'}, 'log_level': 'info', 'device_type': 'default', 'build_variant': 'root'})
build_process.py line 153 <bound method Preloader.run of <hb_internal.preloader.preloader.Preloader object at 0x7f3fb12ed550>>--defaultdict(None, {'gn': [], 'ninja': {'default_target': 'packages'}, 'log_level': 'info', 'device_type': 'default', 'build_variant': 'root'})
build_process.py line 153 <bound method Build.gn_build of <hb_internal.build.build_process.Build object at 0x7f3fafbde1c0>>--defaultdict(None, {'gn': [], 'ninja': {'default_target': 'packages'}, 'log_level': 'info', 'device_type': 'default', 'build_variant': 'root'})
build_process.py line 259 ['gn', 'gen', '--args=product_path="/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/vendor/hihope/rk3568" product_name="rk3568" device_name="rk3568" target_cpu="arm" is_standard_system=true device_path="/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/device/board/rockchip/rk3568" device_config_path="/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/device/board/rockchip/rk3568" product_config_path="/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/vendor/hihope/rk3568" ace_engine_feature_enable_accessibility=true ace_engine_feature_enable_web=true enable_ohos_startup_init_feature_ab_partition=true enable_ohos_startup_init_feature_loader=true dsoftbus_feature_conn_p2p=true dsoftbus_feature_disc_ble=true dsoftbus_feature_conn_br=true dsoftbus_feature_conn_ble=true dsoftbus_feature_trans_udp_stream=true graphic_standard_feature_ace_enable_gpu=true input_feature_combination_key=true input_feature_pointer_drawing=true input_feature_interceptor=true input_feature_monitor=true input_feature_keyboard=true input_feature_mouse=true input_feature_touchscreen=true input_feature_input_device=true wpa_supplicant_driver_nl80211=true drivers_peripheral_input_feature_model=true drivers_peripheral_sensor_feature_model=true drivers_peripheral_audio_full_test_suite=true drivers_peripheral_audio_alsa_lib=false drivers_peripheral_light_feature_model=true drivers_peripheral_vibrator_feature_model=true ohos_build_type="debug" ohos_build_time="1704430722501" ohos_build_datetime="2024-01-05 20:58:42" ohos_build_enable_ccache=true build_variant="root" device_type="default"', '/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/out/rk3568']--/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/out/rk3568/build.log
build_process.py line 153 <bound method Build.ninja_build of <hb_internal.build.build_process.Build object at 0x7f7e0561f190>>--defaultdict(None, {'gn': [], 'ninja': {'default_target': 'packages'}, 'log_level': 'info', 'device_type': 'default', 'build_variant': 'root'})
build_process.py line 290 ['ninja', '-w', 'dupbuild=warn', '-C', '/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/out/rk3568', 'images']--/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/out/rk3568/build.log
def exec_command(cmd, log_path='out/build.log', **kwargs): useful_info_pattern = re.compile(r'\[\d+/\d+\].+') #设置log过滤 is_log_filter = kwargs.pop('log_filter', False) with open(log_path, 'at', encoding='utf-8') as log_file: process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf-8', **kwargs) for line in iter(process.stdout.readline, ''): if is_log_filter: info = re.findall(useful_info_pattern, line) if len(info): hb_info(info[0]) else: hb_info(line) #打印log信息,即[OHOS INFO]开头的log log_file.write(line) process.wait() ret_code = process.returncode if ret_code != 0: if is_log_filter: get_failed_log(log_path) raise OHOSException('Please check build log in {}'.format(log_path))
exec_command(‘gn’, ‘gen’, ‘–args=product_path=“/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/vendor/hihope/rk3568” product_name=“rk3568” device_name=“rk3568” target_cpu=“arm” is_standard_system=true device_path=“/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/device/board/rockchip/rk3568” device_config_path=“/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/device/board/rockchip/rk3568” product_config_path=“/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/vendor/hihope/rk3568” ace_engine_feature_enable_accessibility=true ace_engine_feature_enable_web=true enable_ohos_startup_init_feature_ab_partition=true enable_ohos_startup_init_feature_loader=true dsoftbus_feature_conn_p2p=true dsoftbus_feature_disc_ble=true dsoftbus_feature_conn_br=true dsoftbus_feature_conn_ble=true dsoftbus_feature_trans_udp_stream=true graphic_standard_feature_ace_enable_gpu=true input_feature_combination_key=true input_feature_pointer_drawing=true input_feature_interceptor=true input_feature_monitor=true input_feature_keyboard=true input_feature_mouse=true input_feature_touchscreen=true input_feature_input_device=true wpa_supplicant_driver_nl80211=true drivers_peripheral_input_feature_model=true drivers_peripheral_sensor_feature_model=true drivers_peripheral_audio_full_test_suite=true drivers_peripheral_audio_alsa_lib=false drivers_peripheral_light_feature_model=true drivers_peripheral_vibrator_feature_model=true ohos_build_type=“debug” ohos_build_time=“1704430722501” ohos_build_datetime=“2024-01-05 20:58:42” ohos_build_enable_ccache=true build_variant=“root” device_type=“default”’, ‘/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/out/rk3568’],/usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony/out/rk3568/build.log,…)
上述命令exec_command会启动进程执行gn,gn会到根目录下寻找.gn文件,并从根.gn文件开始执行/.gn为软链接,真正文件位于//build/core/gn/dotfile.gn 内容如下,
buildconfig = "//build/config/BUILDCONFIG.gn"
# The source root location.
root = "//build/core/gn" #切换资源gn根目录为//build/core/gn,自动会执行根目录下BUILD.gn
# The executable used to execute scripts in action and exec_script.
script_executable = "/usr/bin/env"
//build/core/gn/BUILD.gn
内容如下,
print("root_out_dir=$root_out_dir") //编译log中的打印[OHOS INFO] print("root_build_dir=$root_build_dir") print("root_gen_dir=$root_gen_dir") print("current_toolchain=$current_toolchain") print("host_toolchain=$host_toolchain") # run loader import("//build/core/gn/loader.gni") # gn target defined if (product_name == "ohos-sdk") { group("build_ohos_sdk") { deps = [ "//build/ohos/ndk:ohos_ndk", "//build/ohos/sdk:ohos_sdk", ] } } else { group("make_all") { deps = [ ":make_inner_kits", ":packages", ] if (is_standard_system) { # Lite system uses different packaging scheme, which is called in hb. # So skip images for lite system since it's the mkimage # action for standard system. deps += [ ":images" ] } } group("images") { deps = [ "//build/ohos/images:make_images" ] } group("packages") { deps = [ "//build/ohos/packages:make_packages" ] } group("make_inner_kits") { deps = [ "$root_build_dir/build_configs:inner_kits" ] } group("build_all_test_pkg") { testonly = true deps = [ "$root_build_dir/build_configs:parts_test", "//test/testfwk/developer_test:make_temp_test", ] } group("make_test") { testonly = true deps = [ "//build/ohos/packages:build_all_test_pkg", "//build/ohos/packages:package_testcase", "//build/ohos/packages:package_testcase_mlf", ] if (archive_component) { deps += [ "//build/ohos/testfwk:archive_testcase" ] } } }
命令行打印log如下
[OHOS INFO] root_out_dir=//out/rk3568
[OHOS INFO] root_build_dir=//out/rk3568
[OHOS INFO] root_gen_dir=//out/rk3568/gen
[OHOS INFO] current_toolchain=//build/toolchain/ohos:ohos_clang_arm
[OHOS INFO] host_toolchain=//build/toolchain/linux:clang_x64
完整脚本调用过程如下
./build.sh --product-name rk3568 --ccache #--ccache可以不带,默认使用ccache加速编译 build/scripts/tools_checker.py build/scripts/entry.py --source-root-dir /usr/src/openharmony/OpenHarmony-v3.2.4-Release/OpenHarmony --product-name rk3568 --ccache build.py -p rk3568 --device-type=default --build-variant=root build/lite/hb/__main__.py build -p rk3568 -device-type=default --build-variant=root build/lite/hb/__entry__.py build/lite/hb/hb_internal/build/build.py build/lite/hb/hb_internal/build/build_process.py PreBuild #hb_internal.common.misc.PreBuild,1.设置ccache大小;2.备份上次编译log build.log->build.<上次修改时间>.log #并在屏幕输出第一行以[OHOS INFO]开头的log,为执行ccache -M 100GB命令自动输出 #[OHOS INFO] Set cache size limit to 100.0 GB Patch #默认不执行,代码路径build/lite/hb/hb_internal/build/patch_process.py Preloader #hb_internal.preloader.preloader.Preloader #创建out/preloader/rk3568文件夹,生成syscap.json,SystemCapability.json,part.json,part_config.json,feature.json,build_gnargs.prop,exclusion_module.json,build.prob,platforms.build, 创建system文件夹生成对应文件 self.gn_build #hb_internal.build.build_process.Build self.ninja_build #hb_internal.build.build_process.Build PostBuild #packiamge执行镜像打包 out_put_part_rom_status #统计各部件大小 clean #统计ccache命中率信息、ninja trace、计算c语言代码覆盖率
OpenHarmony编译过程已经分析完毕,如果想了解编译框架,可以看我的另一篇文章《OpenHarmony源码学习之编译构建》。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。