当前位置: 首页 > 科技观察

移植案例与原理——构建精简版Hb命令__Main__.Py

时间:2023-03-21 15:45:47 科技观察

了解更多开源请访问:开源基础软件社区https://ost.51cto.com可以通过pythonpip安装hb命令packagemanager,应该是OpenHarmonyBuild的缩写,python包名是ohos-build。hb作为编译构建子系统提供的命令行,用于编译构建产品、芯片厂商组件或单个组件。本篇我们来学习下hb的源码。一、hb的安装、卸载及简介在源码根目录下执行以下命令进行安装。python3-mpipinstall--userbuild/lite执行hb-h有相关的帮助信息,如果有打印信息,说明安装成功:usage:-c[-h][-v]{build,set,env,clean,tool}...OHOSBuildSystemversion0.4.6positionalarguments:{build,set,env,clean,tool}build构建源代码setOHOSbuildsettingsenvShowOHOSbuildenvcleanCleanoutputtool调用gn命令通过hb工具可选参数:-h,--help显示此帮助信息并退出-v,--version显示程序版本号并退出需要注意的是hb命令只能在源代码目录下执行OpenHarmony,否则会提示:hb_error:Pleasecallhbutilitiesinsidesourcerootdirectory.后面分析源码的时候会解释为什么hb只能在源码目录下执行。卸载执行以下命令:python3-mpipuninstallohos-build另外,你还需要知道一个比较有用的命令,如下,可以查看安装的python包的信息:python3-mpipshowohos-build执行后,输出如下信息。更重要的是,可以知道hb命令对应的源文件安装位置是...lib/python3.8/site-packages。.hb命令工具的位置可以通过whichhb查看。zhushangyuan@DESKTOP-RPE9R4O:~$python3-mpipshowohos-buildName:ohos-buildVersion:0.4.6总结:OHOSbuildcommandlinetoolHome-page:https://gitee.com/openharmony/build_liteAuthor:HuaweiAuthor-email:contact@openharmony.ioLicense:Apache2.0位置:/home/zhushangyuan/.local/lib/python3.8/site-packagesRequires:kconfiglib,prompt-toolkit,PyYAML,requestsRequired-by:在文件夹...lib/python3.8里面/site-packages/hb中有3个文件,__init__.py是代表python模块的空文件,__main__.py是执行入口文件,__entry__.py并没有实际使用。这三个文件与build/lite/hb目录下的文件完全一样。zhushangyuan@DESKTOP-RPE9R4O:~$ll/home/zhushangyuan/.local/lib/python3.8/site-packages/hb/total20drwxr-xr-x3zhushangyuanzhushangyuan4096Oct2520:36./drwx------33zhushangyuanzhushangyuan4096Oct2520:36../-rw-r--r--1zhushangyuanzhushangyuan3629Oct2520:56__entry__.py-rw-r--r--1zhushangyuanzhushangyuan0Oct2520:36__init__.py-rw-r--r--1zhushangyuanzhushangyuan2204Oct2520:36__main__.py2、hb源码分析使用whichhb查看hb命令工具所在位置。在我的环境中,位置是~/.local/bin/hb,通过pip安装,其实是一个python文件。让我们看看它的文件内容。⑴处导入的main函数来自...lib/python3.8/site-packages/hb/__main__.py。(2)sys.argv[0]指的是执行的程序名,这里等于hb,这条语句的意思是去掉以-script.pyw或.exe结尾的部分,例如假设sys.argv[0]是测试脚本。pyw,替换的sys.argv[0]是测试。使用pip安装的包一般都是这样写的。zhushangyuan@DESKTOP-RPE9R4O:~/openharmony$cat~/.local/bin/hb#!/usr/bin/python3#-*-coding:utf-8-*-importreimportsys⑴fromhb.__main__importmainif__name__=='__main__':⑵sys.argv[0]=re.sub(r'(-script\.pyw|\.exe)?$','',sys.argv[0])sys.exit(main())接下来我们分析一下源文件...lib/python3.8/site-packages/hb/__main__.py。zhushangyuan@DESKTOP-RPE9R4O:~/openharmony$cat/home/zhushangyuan/.local/lib/python3.8/site-packages/hb/__main__.py#!/usr/bin/envpython3#-*-编码:utf-8-*-##Copyright(c)2022HuaweiDeviceCo.,Ltd.#LicensedundertheApacheLicense,Version2.0(the"License");#除非遵守许可证,否则您不得使用此文件。#您可以在##http://www.apache.org/licenses/LICENSE-2.0##获得许可的副本,除非适用法律要求或书面同意,根据许可分发的软件#分发在“ASIS"BASIS,#WITHOUTWITHWITHWARRANTIESORCONDITIONSOFNYKIND,expressorimplied.#SeetheLicenseforthespecificlanguagegoverningpermissionsand#limitationsundertheLicense.#importosimportsysVERSION="0.4.6"#execvexecutionfragmentEXECV_FRAGMENT="""importsysimportimportlibsys.path.append(sys.argv.pop())entry=importlib.import_module("__entry__")sys.exit(entry.main())"""deffind_top():cur_dir=os.getcwd()whilecur_dir!="/":hb_internal=os.path.join(cur_dir,'build/lite/hb_internal')如果os.path.exists(hb_internal):返回cur_dircur_dir=os.path.dirname(cur_dir)raiseException("Pleasecallhbutilitiesinsidesourcerootdirectory")defsearch(findir,target):forroot,dirs,filesinos.walk(findir):如果目标在文件中:返回rootdefmain():try:topdir=find_top()exceptExceptionasex:returnprint("hb_error:Pleasecallhbutilitiesinsidesourcerootdirectory")python_base_dir=os.path.join(topdir,'prebuilts/python')如果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]forarginsys.argv[1:]:param_list.append(arg)param_list.append(hb_dir)os.environ['PATH']=python_dir+":"+os.getenv('PATH')os.execv(python_executable,param_list)else:print("pleaseexecutebuild/prebuilts_download.sh")if__name__=="__main__":sys.exit(main())(1)hb/main.py动态执行python代码片段EXECV_FRAGMENTpython-ccommand可以在命令行直接调用python代码,其实-c就是command的意思,即python-c可以在命令行执行python代码,并将代码放在.py中文件,然后运行此文件具有相同的效果。__main__.py文件会动态执行python代码片段如下,下面(1)处的代码解释一下。当我们导入一个模块时:importXXX,默认情况下,python解释器会搜索当前目录,安装的内置模块和第三方模块,如果都找不到,就会报错。我们的搜索路径是存放在sys模块中的路径,sys.path是一个当前路径的列表。【即默认路径可以通过sys.path打印查看】。当我们想添加自己的引用模块搜索目录时,可以使用list的append方法。sys.argv.pop()表示参数列表的最后一项,指的是openharmony\build\lite\hb\目录,下面会详细说明。⑵动态导入模块对象,“入口”是指openharmony\build\lite\hb\__entry__.py。所以,我们只使用openharmony\build\lite\hb\__entry__.py而不是使用python3.8/site-packages/hb/__entry__.py.py。EXECV_FRAGMENT="""importsysimportimportlib⑴sys.path.append(sys.argv.pop())⑵entry=importlib.import_module("__entry__")sys.exit(entry.main())"""(2)hb/main.pyfind_top()函数find_top()函数用于获取OpenHarmony源码的根目录。(1)先获取当前工作目录,hb命令所在的目录就是当前工作目录。⑵开始while循环,结束条件为遍历到系统根目录或返回。(3)判断'build/lite/hb_internal'目录是否存在,如果存在,则可以得到OpenHarmony源码的根目录。如果不存在,则执行(4)获取上层目录,继续循环。如果遍历的目录中没有'build/lite/hb_internal'目录,则会抛出异常。从这些源码可以看出,hb不能在非OpenHarmony源码目录下执行,但是可以在OpenHarmony源码目录下的任意目录下执行。deffind_top():⑴cur_dir=os.getcwd()⑵whilecur_dir!="/":hb_internal=os.path.join(cur_dir,'build/lite/hb_internal')⑶ifos.path.exists(hb_internal):returncur_dir⑷cur_dir=os.path.dirname(cur_dir)raiseException("Pleasecallhbutilitiesinsidesourcerootdirectory")(3)hb/main.pysearch()函数search()函数查询是否来自指定目录指定的文件存在,如果存在,则返回包含指定文件的目录的路径。代码如下,这段代码也很容易被挑战。对于指定文件不存在的情况,没有return语句,所以代码不规范。defsearch(findir,target):forroot,dirs,filesinos.walk(findir):iftargetinfiles:returnroot(4)hb/main.pymain()函数接下来我们看main()函数.首先调用find_top()函数获取OpenHarmony源码根目录。⑴判断'prebuilts/python'文件是否存在,不存在则打印,并告知开发者“请执行build/prebuilts_download.sh”完成环境准备。从⑵开始,获取4个变量的值,如下表所示:变量值说明python_diropenharmony/prebuilts/python/linux-x86/3.9.2/bin包含python3可执行文件目录python_executableopenharmony/prebuilts/python/Linux-x86/3.9。2/bin/python3python3执行文件路径lite_diropenharmony/build/litebuildlite目录hb_diropenharmony/build/lite/hb__entry__.py⑶封装参数列表的目录,要动态执行的脚本EXECV_FRAGMENT上面已经解释过了。(4)将命令行执行hb命令时传入的参数添加到param_list变量中,(5)最后添加的参数为__entry__.py所在目录。在讲解python代码片段EXECV_FRAGMENT的动态执行时,提到的sys.argv.pop()就是刚才添加的目录。接着在⑴处的代码设置环境变量,然后调用函数os.execv执行。后面我们会详细分析__entry__.py。defmain():try:topdir=find_top()exceptExceptionasex:returnprint("hb_error:Pleasecallhbutilitiesinsidesourcerootdirectory")python_base_dir=os.path.join(topdir,'prebuilts/python')⑴如果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]⑷forarginsys.argv[1:]:param_list.append(arg)⑸param_list.append(hb_dir)⑴os.environ['PATH']=python_dir+":"+os.getenv('PATH')os.execv(python_executable,param_list)else:print("请执行build/prebuilts_download.sh")3,参考站点OpenHarmony/build_lite编译搭建指南4.总结本文介绍buildlite轻量级编译搭建系统的hb命令源码,主要分析了__main__.py文件。了解更多开源请访问:开源基础软件社区https://ost.51cto.com