摘要:本文介紹了build lite 輕量級編譯建構系統hb指令的源碼,主要分析了_\entry__.py檔案。
本文分享自華為雲社群《移植案例與原理 - build lite源碼分析 之 hb指令__entry__.py》,作者:zhushy 。
hb指令可以通過python pip包管理器進行安裝,應該是OpenHarmony Build的縮寫,在python包名稱是ohos-build。hb作為編譯建構子系統提供的指令行,用于編譯建構産品、晶片廠商元件或者單個元件。我們來學習hb指令行工具的源碼,本文主要分析下檔案openharmony/build/lite/hb/__entry__.py。
1、find_top()函數
find_top()函數用于擷取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、get_hb_commands()函數
get_hb_commands()函數用于傳回hb指令行工具支援的指令集。hb支援的指令定義在檔案’build/lite/hb_internal/hb_command_set.json’中,支援的指令主要為build、set、env、clean和tool。
def get_hb_commands(config_file):
if not os.path.exists(config_file):
raise Exception('Error: {} not exist, couldnot get hb command set'.format(config_file))
with open(config_file, 'r') as file:
config = json.load(file)
return config
3、main()函數
在main()函數中,首先擷取OpenHarmony源代碼根目錄,然後把路徑'build/lite'插入到sys.path系統搜尋路徑,為後續調用importlib.import_module接口進行動态加載做準備。⑴處定義hb指令行的支援的選項,使用和指令輸出hb -h結合起來學習源代碼。⑵處擷取hb指令行工具支援的指令集合,然後添加到指令行解析參數清單裡parser_list。⑶和⑷配置支援的positional arguments(見 hb -h的輸出),⑶處動态引入支援的子產品,這些對應檔案build/lite/hb_internal/hb_internal/XXX/XXX.py,其中XXX的取值為build、set、clean、env和tool。在這幾個python檔案中,都會有add_options()函數,用于提供具體指令的參數選項,還有個函數exec_command(),執行具體的指令時,會調用這些函數。⑷處的代碼會配置剛才描述的add_options()函數和函數exec_command()。
⑸處的語句擷取hb指令傳入的參數選項,接下來動态加載’hb_internal.common.utils’,獲得函數位址,分别用于控制台輸出日志、異常處理等。接下來處理hb指令行傳入的選項,⑹處如果指定了’-root’|’–root_path’選項時,開發者主動提供OpenHarmony源代碼根目錄,會執行args[0].root_path = topdir把根目錄傳入到參數清單裡。⑺根據是hb tool還是其他指令,分别調用對應的函數exec_command(),指令行選項不一樣時,傳入的參數稍有差異,分别是args和args[0]。對于hb tool,args[1]會傳遞些要傳遞給gn指令行的參數gn_args。
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'))
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')))
⑷ 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:
status = args[0].command(args[0])
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
4、參考站點
- OpenHarmony / build_lite
- 編譯建構指導