首页 > 其他分享 >#打卡不停更# 移植案例与原理 - build lite hb命令__main__.py

#打卡不停更# 移植案例与原理 - build lite hb命令__main__.py

时间:2022-11-01 10:34:55浏览次数:94  
标签:__ python py build hb 打卡 dir

移植案例与原理 - build lite源码分析 之 hb命令__main__.py

hb命令可以通过python pip包管理器进行安装,应该是OpenHarmony Build的缩写,在python包名称是ohos-build。hb作为编译构建子系统提供的命令行,用于编译构建产品、芯片厂商组件或者单个组件。本文,我们来学习hb的源码。

1、hb的安装、卸载与简单介绍

在源码根目录下执行下述命令可以进行安装。

python3 -m pip install --user build/lite

执行hb -h有相关帮助信息,有打印信息即表示安装成功:

usage: -c [-h] [-v] {build,set,env,clean,tool} ...

OHOS Build System version 0.4.6

positional arguments:
  {build,set,env,clean,tool}
    build               Build source code
    set                 OHOS build settings
    env                 Show OHOS build env
    clean               Clean output
    tool                Call the gn command through the hb tool

optional arguments:
  -h, --help            show this help message and exit
  -v, --version         show program's version number and exit

需要注意的是,需要在OpenHarmony的源代码目录下才能执行hb命令,否则会提示:hb_error: Please call hb utilities inside source root directory。后文源码分析时,会讲述为啥要在源码目录下才能执行该hb。

卸载方法,执行下述命令即可:

python3 -m pip uninstall ohos-build

另外,需要了解的一个比较好用的命令,如下,可以查看安装的python包的信息:

python3 -m pip show ohos-build

执行后,输出如下信息。比较关键的是,可以知道hb命令对应源文件的安装位置在...lib/python3.8/site-packages。 。hb命令工具的位置可以通过which hb来查看。

zhushangyuan@DESKTOP-RPE9R4O:~$ python3 -m pip show ohos-build
Name: ohos-build
Version: 0.4.6
Summary: OHOS build command line tool
Home-page: https://gitee.com/openharmony/build_lite
Author: Huawei
Author-email: [email protected]
License: Apache 2.0
Location: /home/zhushangyuan/.local/lib/python3.8/site-packages
Requires: kconfiglib, prompt-toolkit, PyYAML, requests
Required-by:

在文件夹...lib/python3.8/site-packages/hb有3个文件,__init__.py是空文件表示python模块,__main__.py是执行入口文件,__entry__.py事实上并没有使用到。这3个文件和目录build/lite/hb下的文件是一模一样的。

zhushangyuan@DESKTOP-RPE9R4O:~$ ll /home/zhushangyuan/.local/lib/python3.8/site-packages/hb/
total 20
drwxr-xr-x  3 zhushangyuan zhushangyuan 4096 Oct 25 20:36 ./
drwx------ 33 zhushangyuan zhushangyuan 4096 Oct 25 20:36 ../
-rw-r--r--  1 zhushangyuan zhushangyuan 3629 Oct 25 20:56 __entry__.py
-rw-r--r--  1 zhushangyuan zhushangyuan    0 Oct 25 20:36 __init__.py
-rw-r--r--  1 zhushangyuan zhushangyuan 2204 Oct 25 20:36 __main__.py

2、hb源码分析

通过which hb来查看hb命令工具的位置,我的环境上,位置为~/.local/bin/hb,该文件是通过pip安装的,其实是个python文件。我们来查看其文件内容。⑴处导入的main函数来自...lib/python3.8/site-packages/hb/__main__.py。⑵处sys.argv[0]指的是执行的程序名称,这里等于hb,该语句表示以-script.pyw或者.exe结尾的部分去除,例如,假设sys.argv[0]为test-script.pyw,则替换后的sys.argv[0]为test。使用pip安装的包通常都是这样的写法。

    zhushangyuan@DESKTOP-RPE9R4O:~/openharmony$ cat ~/.local/bin/hb
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
    import re
    import sys
⑴  from hb.__main__ import main
    if __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/env python3
# -*- coding: utf-8 -*-

#
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import os
import sys


VERSION = "0.4.6"
# execv execution fragment
EXECV_FRAGMENT = """
import sys
import importlib

sys.path.append(sys.argv.pop())
entry = importlib.import_module("__entry__")
sys.exit(entry.main())
"""


def find_top():
    cur_dir = os.getcwd()
    while cur_dir != "/":
        hb_internal = os.path.join(cur_dir, 'build/lite/hb_internal')
        if os.path.exists(hb_internal):
            return cur_dir
        cur_dir = os.path.dirname(cur_dir)
    raise Exception("Please call hb utilities inside source root directory")


def search(findir, target):
    for root, dirs, files in os.walk(findir):
        if target in files:
            return root


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')
        os.execv(python_executable, param_list)
    else:
        print("please execute build/prebuilts_download.sh")


if __name__ == "__main__":
    sys.exit(main())

2.1、hb/main.py 动态执行python代码片段EXECV_FRAGMENT

python -c命令可以直接在命令行中调用python代码, 实际上-c就是command的意思,就是python -c可以在命令行中执行python代码, 跟把代码放置在.py文件中,然后运行这个文件是一样的效果。

__main__.py文件中会动态执行python代码片段如下,解释下⑴处的代码。当我们导入一个模块时:import XXX,默认情况下python解释器会搜索当前目录、已安装的内置模块和第三方模块,如果都搜索不到,则会报错。 我们的搜索路径存放在sys模块中的path中,sys.path是当前路径的一个列表。[即默认路径可以通过sys.path来打印查看]。当我们要添加自己的引用模块搜索目录时,可以通过list的append方法。sys.argv.pop()表示参数列表中的最后一项,指的是openharmony\build\lite\hb\目录,下文会详细解释。

⑵处动态导入模块对象,"entry"指的是openharmony\build\lite\hb\__entry__.py。所以,我们只使用到了openharmony\build\lite\hb\__entry__.py,而不是使用python3.8/site-packages/hb/__entry__.py.py

    EXECV_FRAGMENT = """
    import sys
    import importlib

⑴  sys.path.append(sys.argv.pop())
⑵  entry = importlib.import_module("__entry__")
    sys.exit(entry.main())
    """

2.2、hb/main.py find_top()函数

find_top()函数用于获取OpenHarmony源代码根目录。⑴处先获取当前工作目录,hb命令在哪个目录下执行,就是当前的工作目录。⑵处开始while循环,结束条件是遍历到系统根目录或者return返回。⑶处判断是否存在目录'build/lite/hb_internal',如果存在,即可获得OpenHarmony源码根目录。如果不存在,则执行⑷获取上一级目录,继续循环。遍历的目录不存在'build/lite/hb_internal'目录,则抛出异常。从这些源码可知,hb不能在非OpenHarmony源代码目录下执行,但又可以在OpenHarmony源码目录下的任何一个目录执行。

    def find_top():
⑴      cur_dir = os.getcwd()
⑵      while cur_dir != "/":
            hb_internal = os.path.join(cur_dir, 'build/lite/hb_internal')
⑶          if os.path.exists(hb_internal):
                return cur_dir
⑷          cur_dir = os.path.dirname(cur_dir)
        raise Exception("Please call hb utilities inside source root directory")

2.3、hb/main.py search()函数

search()函数从指定的目录下查询是否存在指定的文件,如果存在,则返回包含指定文件的目录路径。代码如下,这代码也容易被挑战。对于不存在指定文件的情况下,就没有return语句,这样代码不规范。

    def search(findir, target):
        for root, dirs, files in os.walk(findir):
            if target in files:
                return root

2.4、hb/main.py main()函数

接下来,我们来看下main()函数。首先调用find_top()函数获得OpenHarmony源码根目录。⑴处判断是否存在文件'prebuilts/python',如果不存在则打印,告知开发者需要"please execute build/prebuilts_download.sh"来完成环境准备。⑵处开始,获取4个变量的值,如下表:

变量 说明
python_dir openharmony/prebuilts/python/linux-x86/3.9.2/bin 包含python3执行文件的目录
python_executable openharmony/prebuilts/python/linux-x86/3.9.2/bin/python3 python3执行文件路径
lite_dir openharmony/build/lite build lite目录
hb_dir openharmony/build/lite/hb __entry__.py所在的目录

⑶处封装要参数列表,要动态执行的脚本EXECV_FRAGMENT,已经在前文解释。⑷处把命令行执行hb命令时传入的参数,添加到param_list变量,⑸处最后添加的参数是__entry__.py所在的目录。在解释动态执行python代码片段EXECV_FRAGMENT时,提到的sys.argv.pop()就是刚刚添加的这个目录。接下来,⑹处的代码设置环境变量,然后调用函数os.execv来执行。后文再详细分析__entry__.py。

    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')
            os.execv(python_executable, param_list)
        else:
            print("please execute build/prebuilts_download.sh")

3、参考站点

4、小结

本文介绍了build lite 轻量级编译构建系统hb命令的源码,主要分析了__main__.py文件。因为时间关系,仓促写作,或能力限制,若有失误之处,请各位读者多多指正。遗漏之处,欢迎补充。感谢阅读,有什么问题,请留言。

本文作者:zhushangyuan_

想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com/#bkwz​

标签:__,python,py,build,hb,打卡,dir
From: https://blog.51cto.com/harmonyos/5811970

相关文章

  • Leetcode第1662题:检查两个字符串数组是否相等(Check if two string arrays are equival
    解题思路输入是两个字符串数组,包含的元素数目不一定相同,每个元素包含的字符数目也不一定相同。使用两个指针p和i分别记录遍历的元素位置和字符位置。指针p1和p2分别表示......
  • 做好这三点,让家装少点后悔事
    做好这三点,让家装少点后悔事前言还是要坚持写作,写作是与自己对话。现在刷一下视频、玩一下游戏,一天就过去了,没有一点点积累。每天都有事,又好像每天都没干点事。闲来无事就写......
  • Java学习之位运算(操作)总结
    最近在反思工作第四年的深度,故而写此系列。其他Java系列文章:​​Java学习之编译、反编译以及字节码入门​​​​Java学习之String​​​​Java学习之JDK9新特性​​位操作,......
  • 共享带来的问题
    4.1共享带来的问题小故事老王(操作系统)有一个功能强大的算盘(CPU),现在想把它租出去,赚一点外快小南、小女(线程)来使用这个算盘来进行一些计算,并按照时间给老王支付费用......
  • Keras可视化神经网络架构的4种方法
    我们在使用卷积神经网络或递归神经网络或其他变体时,通常都希望对模型的架构可以进行可视化的查看,因为这样我们可以在定义和训练多个模型时,比较不同的层以及它们放置的顺序......
  • node.js - http、模块化、npm
    今天是node学习的第二天,其实越往后面学越感觉有点熟悉的味道了,光针对于node来说哈,为什么呢,因为我之前学过一点云计算的东西,当时感觉没什么用搞了下服务器客户端这些,没想到这......
  • 一台虚拟机,基于docker搭建大数据HDP集群
    前言好多人问我,这种基于大数据平台的xxxx的毕业设计要怎么做。这个可以参考之前写得关于我大数据毕业设计的文章。这篇文章是将对之前的毕设进行优化。个人觉得可以分为......
  • Java学习之NoClassDefFoundError、ClassNotFoundException、NoSuchMethodError
    在菜逼如我短短的三年职业编码生涯中,无数次遇到这两个异常,故而总结一下。Java异常体系大致提一些,不是本文的重点。两者都是标准异常,平时碰到最多的是ClassNotFoundExceptio......
  • SPI介绍
    @目录前言组成结构优缺点接线方式工作模式读写时序前言SPI是串行外设接口(SerialPeripheralInterface)的缩写,是串行外围设备接口,是一种高速,全双工,同步的通信总线。常规只......
  • 推导四万全屋装修的可能性
    究极穷装,暴打装修公司,挑战三万搞定全屋装修事先声明,这个没有具体装修案例,只是推算,不过可以借鉴。类似DIY电脑一样,三千预算进图吧,减钱减到二百八,一堆垃圾抱回家,开开心心开网......