深入了解编译构建子系统

基于4.1-release,(因为本人主c++,对于python中的一些方法可能有误欢迎大家指出)

一.build.py解读

命令行执行./build.py --product-name oriole –ccache --no-prebuilt-sdk

调用当前目录下的build.py脚本文件后面为相应参数

1.进入main函数

def main():
    root_path = find_top()
    return build(root_path, sys.argv[1:])
​
​
if __name__ == "__main__":
    sys.exit(main())

因此,执行到到 if __name__ == "__main__": 这个条件,调用 main() 函数,

root_path = find_top()调用前面定义的函数

2.进入find_top()函数

def find_top() -> str:
    cur_dir = os.getcwd()
    while cur_dir != "/":
        build_config_file = os.path.join(
            cur_dir, 'build/config/BUILDCONFIG.gn')
        if os.path.exists(build_config_file):
            return cur_dir
        cur_dir = os.path.dirname(cur_dir)

#find_top() -> str 以字符串的格式返回结果

类似python导入os,在 C++ 中,你可以使用 <filesystem> 标准库(C++17 引入)来进行文件系统操作,其中包含了一系列用于文件路径操作的函数和类。比如,你可以使用 std::filesystem::path 类来表示文件路径,并进行路径的拼接、分解等操作。

举个例子,你可以像这样使用 <filesystem> 标准库来构建文件路径:

#include <iostream>
#include <filesystem>
​
namespace fs = std::filesystem;
​
int main() {
    fs::path cur_dir = fs::current_path();
    fs::path build_config_file = cur_dir / "build" / "config" / "BUILDCONFIG.gn";
​
    std::cout << "Build config file path: " << build_config_file << std::endl;
​
    return 0;
}

这段代码会输出构建的文件路径,其中 cur_dir 是当前工作目录的路径,build_config_file 是要构建的文件的路径。通过使用 <filesystem> 标准库,你可以方便地进行跨平台的文件系统操作。

while cur_dir != "/": #当路径不为顶级目录 os.getcwd() 在根目录执行时会返回空字符串而不是根目录本身,所以即使是根目录也会执行循环

build_config_file = os.path.join(cur_dir, 'build/config/BUILDCONFIG.gn')

#os.path.join拼接两个路径并传给build_config_file

if os.path.exists(build_config_file): return cur_dir

cur_dir = os.path.dirname(cur_dir) # 在则跳出循环返回cur_dir给主函数,否则就向上(父级目录)找

3.进入主函数

root_path = find_top() #主函数读取到字符串, return build(root_path, sys.argv[1:])

4,进入build函数

#执行build函数(当前路径,接受敲入命令行第一个以外的所有参数)及./build.py除外 --product-name oriole –ccache -- no-prebuilt-sdk 其作用既是构建该路径下的项目

def build(path: str, args_list: list) -> str:
    python_dir = None
    if "--python-dir" in args_list:
        index = args_list.index("--python-dir")
        if index < len(args_list) - 1:
            python_dir = args_list[index + 1]
            del args_list[index: index + 2]
        else:
            print("-python-dir parmeter missing value.")
            sys.exit()
    python_executable = get_python(python_dir)
    cmd = [python_executable, 'build/hb/main.py', 'build'] + args_list
    return check_output(cmd, cwd=path)

--python-dir 是一个选项,用于指定 Python 的安装目录或路径。通常情况下,它可以让用户指定程序在哪里找到 Python 解释器或 Python 模块

如果 --python-dir 存在于参数列表中,就会找到它在列表中的位置, if index < len(args_list) - 1:python_dir = args_list[index + 1]检查其后是否存在对应的值。如果存在值,则将其赋给 python_dir 变量,并从参数列表中删除 --python-dir 及其对应的值。如果不存在对应的值,则输出错误信息并退出程序。

所以命令行中没有指定python路径不进入判断

python_executable = get_python(python_dir) 这行代码的作用是根据指定的 Python 路径(python_dir)来获取 Python 解释器的可执行文件路径。

在 Unix/Linux 系统上,Python 解释器通常被安装在 /usr/bin/python 或者 /usr/local/bin/python 等位置

5.进入get_python函数

函数的作用是根据给定的相对路径找到 Python 解释器的可执行文件路径。

def get_python(python_relative_dir: str) -> str:
    topdir = find_top()
    if python_relative_dir is None:
        python_relative_dir = 'prebuilts/python'
    python_base_dir = os.path.join(topdir, python_relative_dir)
​
    if os.path.exists(python_base_dir):
        python_dir = search(python_base_dir, 'python3')
        return os.path.join(python_dir, 'python3')
    else:
        print("please execute build/prebuilts_download.sh.",
            "if you used '--python-dir', check whether the input path is valid.")
        sys.exit()

get_python 函数,接受一个参数 python_relative_dir,(我们这里应该为none)。

函数调用了 find_top() 函数来获取顶级目录的路径,

然后,如果未提供 python_relative_dir 参数,函数将其默认设置为 'prebuilts/python'。这意味着如果用户没有指定 Python 的相对路径,将使用默认路径 'prebuilts/python'。也就是我们在配置环境时build/prebuilts_download.sh

接着,函数将顶级目录路径和 Python 相对路径拼接起来,得到 Python 的基础目录路径 python_base_dir

接下来,函数检查 python_base_dir 是否存在。如果存在,函数调用了 search() 函数来在 Python 基础目录中查找名为 'python3' 的文件。

def search(findir: str, target: str) -> str or bool:
    for root, _, files in os.walk(findir):
        if target in files:
            return root
    return False
​

这段代码定义了一个名为 search 的函数,它接受两个参数:findirtarget,分别表示要搜索的目录和目标文件名。

函数使用 os.walk() 函数来遍历指定目录及其子目录中的所有文件和目录。在每次迭代中,os.walk() 返回一个三元组 (root, dirs, files),其中 root 是当前正在遍历的目录的路径,dirs 是该目录中的子目录列表,files 是该目录中的文件列表。

在循环中,函数检查目标文件名 target 是否在当前目录的文件列表中。如果是,说明找到了目标文件,函数立即返回当前目录的路径 root,表示找到了目标文件所在的目录。

如果遍历完整个目录树后仍未找到目标文件,函数将返回 False,表示未找到目标文件

所以寻找python3解释器,找到了 Python 解释器的路径,函数将其与 'python3' 文件名拼接起来,并返回完整的 Python 可执行文件路径。

如果未找到 Python 基础目录,函数将打印一条错误消息,并提示用户执行 build/prebuilts_download.sh 脚本来下载 Python,或者检查提供的 --python-dir 参数是否有效。然后,程序将退出。

6.重回build函数开始构建

这里我们得到了python解释器的路径继续执行

**cmd = [python_executable, 'build/hb/main.py', 'build'] + args_list**

这一行构造了要执行的命令列表 cmd。该列表包含了 Python 解释器路径、 build/hb/main.py 文件路径、build 参数,以及传入的其他参数列表

return check_output(cmd, cwd=path)

7.check_output函数

def check_output(cmd: str, **kwargs) -> str:
    process = subprocess.Popen(cmd,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT,
                               universal_newlines=True,
                               **kwargs)
    for line in iter(process.stdout.readline, ''):
        sys.stdout.write(line)
        sys.stdout.flush()

    process.wait()
    ret_code = process.returncode

    return ret_code

让python以操作系统的身份运行这条编译命令

subprocess.Popen 创建子进程,这段代码会执行你提供的编译命令,并且通过管道捕获子进程的输出,使得你可以在 Python 中获取到编译结果,同时还能处理可能出现的错误信息。

后面一段则是打印编译构建的命令内容到终端

小结

我们可以看出build.py的主要作用就是检查构建的命令和相应构建环境

cmd = [python_executable, 'build/hb/main.py', 'build'] + args_list 才是关键的构建入口

process = subprocess.Popen执行命令

二.进入构建子系统build/hb/main.py

执行编译命令后我们开始构建,这里我们就不再次一 一讲解了

注意以下内容

1.理清重点内容,省略部分函数实现的过程只讲实现的功能

2.main.py中导入各种内置库,定义库,所以有些实现(路径变量赋值,等)是在定义函数之前

3.后创建main类执行定义的各类函数(函数是一层嵌套一层,执行完后,具体实例化实现时才是真正调用):

4.main.py函数其他的模块类似_init_build_module都是执行读懂命令行输入的参数进行相关操作,我们这里主要是讲解执行build操作

main中module_type = sys.argv[1] 读取第一个参数,我们的命令第一个是build则开始执行:

Ⅰ.进入_init_build_module函数

1.主干(作用:初始化各build模块)
def _init_build_module(self) -> BuildModuleInterface:
        args_dict = Arg.parse_all_args(ModuleType.BUILD)      #进入2   获取编译命令参数

        if args_dict.get("product_name").arg_value != '':      #取出product参数判断是需要进行一下设置操作
            set_args_dict = Arg.parse_all_args(ModuleType.SET)         #同理上为枚举类,获取各种产品参数
            set_args_resolver = SetArgsResolver(set_args_dict)        #进5 参数解析器类继承父类(抽象类)又可称接口,为对应产品设置各种参数   
            ohos_set_module = OHOSSetModule(set_args_dict, set_args_resolver, "")   #存入编译参数,产品参数
            ohos_set_module.set_product()            #进行产品实例化设置

        preloader = OHOSPreloader()             
        loader = OHOSLoader()                   
        generate_ninja = Gn()                   
        ninja = Ninja()                         
        build_args_resolver = BuildArgsResolver(args_dict)

        return OHOSBuildModule(args_dict, build_args_resolver, preloader, loader, generate_ninja, ninja)   进入7

后面几个代表编译构建的几个阶段:预加载、加载、生成ninja脚本,执行ninja脚本,以及初始化build阶段各参数的解析器。 最后用这些对象初始化构建模块,返回到OHOSBuildModule函数

这里说一下整个构建过程大致就分为:

2.进入arg.py的parse_all_args函数

调用build/hb/contains/下arg类的方法(python中允许直接用抽象类的方法)

作用:解析读取到所以可支持的命令行编译参数
def parse_all_args(module_type: ModuleType) -> dict:
        args_dict = {}
        parser = argparse.ArgumentParser()          #定义解释器
        all_args = Arg.read_args_file(module_type)     #进入3(读取到所以可支持的命令行编译参数)

        for arg in all_args.values():
            arg = dict(arg)                          #转化字典类型
            ArgsFactory.genetic_add_option(parser, arg)    
            oh_arg = Arg.create_instance_by_dict(arg)      
            args_dict[oh_arg.arg_name] = oh_arg          #将解析的内容存在对象中

        parser.usage = 'hb {} [option]'.format(module_type.name.lower())
        parser_args = parser.parse_known_args(sys.argv[2:])

        for oh_arg in args_dict.values():
            if isinstance(oh_arg, Arg):
                assigned_value = parser_args[0].__dict__[oh_arg.arg_name]
                if oh_arg.arg_type == ArgType.LIST:
                    convert_assigned_value = TypeCheckUtil.tile_list(assigned_value)
                    convert_assigned_value = list(set(convert_assigned_value))
                elif oh_arg.arg_type == ArgType.SUBPARSERS:
                    convert_assigned_value = TypeCheckUtil.tile_list(assigned_value)
                    if len(convert_assigned_value):
                        convert_assigned_value = list(set(convert_assigned_value))
                        convert_assigned_value.extend(parser_args[1])
                        convert_assigned_value.sort(key=sys.argv[2:].index)
                elif oh_arg.arg_type == ArgType.BOOL:
                    if str(assigned_value).lower() == 'false':
                        convert_assigned_value = False
                    elif str(assigned_value).lower() == 'true' or assigned_value is None:
                        convert_assigned_value = True
                else:
                    convert_assigned_value = assigned_value

                if oh_arg.arg_attribute.get('deprecated', None) and oh_arg.arg_value != convert_assigned_value:
                    LogUtil.hb_warning(
                        'compile option "{}" will be deprecated, \
                            please consider use other options'.format(oh_arg.arg_name))
                oh_arg.arg_value = convert_assigned_value
                Arg.write_args_file(
                    oh_arg.arg_name, oh_arg.arg_value, module_type)

        return args_dict

函数的作用是解析特定类型的模块参数,并将解析结果保存在一个字典中

具体来说,这个函数的实现包括以下几个步骤:

  1. 创建一个空字典 args_dict,用于保存解析后的参数。

  2. 使用 Arg.read_args_file(module_type) 读取特定类型模块的所有参数,并将其保存在 all_args 变量中。

  3. 遍历 all_args 中的所有参数,对每个参数进行以下操作:

    • 将参数转换为字典形式。

    • 使用 ArgsFactory.genetic_add_option(parser, arg) 将参数添加到命令行解析器 parser 中。

    • 使用 Arg.create_instance_by_dict(arg) 根据参数字典创建一个参数实例 oh_arg

    • 将参数实例 oh_arg 添加到 args_dict 字典中,键为参数名(就是解析的BUILD.gn中各种类型的参数:参数值)。

  4. 设置命令行解析器 parser 的用法信息,指定使用方式。

  5. 使用 parser.parse_known_args(sys.argv[2:]) 解析命令行参数,获取解析结果。

  6. args_dict 中的每个参数实例 oh_arg 进行以下操作:

    • 根据参数类型进行相应的值转换,如列表类型的参数进行去重操作。

    • 根据参数的属性判断是否已被弃用,如果是则打印警告信息。

    • 更新参数实例的值为转换后的值。

    • 将参数的值写入参数文件。

3.进入read_args_file

 def read_args_file(module_type: ModuleType):
        args_file_path = ''
        default_file_path = ''
        if module_type == ModuleType.BUILD:         #我们是这个类型
            args_file_path = CURRENT_BUILD_ARGS     #参数的路径是这个   在import中我们已经导入这个值   进4
            default_file_path = DEFAULT_BUILD_ARGS
        elif module_type == ModuleType.SET:
            args_file_path = CURRENT_SET_ARGS
            default_file_path = DEFAULT_SET_ARGS
        elif module_type == ModuleType.CLEAN:
            args_file_path = CURRENT_CLEAN_ARGS
            default_file_path = DEFAULT_CLEAN_ARGS
        elif module_type == ModuleType.ENV:
            args_file_path = CURRENT_ENV_ARGS
            default_file_path = DEFAULT_ENV_ARGS
        elif module_type == ModuleType.TOOL:
            args_file_path = CURRENT_TOOL_ARGS
            default_file_path = DEFAULT_TOOL_ARGS
        else:
            raise OHOSException(
                'You are trying to read args file, but there is no corresponding module "{}" args file'
                .format(module_type.name.lower()), "0018")
        if not os.path.exists(CURRENT_ARGS_DIR):
            os.makedirs(CURRENT_ARGS_DIR, exist_ok=True)
        if not os.path.exists(args_file_path):
            IoUtil.copy_file(src=default_file_path, dst=args_file_path)
        return IoUtil.read_json_file(args_file_path)

4进入global_var.py

import os

VERSION = "1.0.0"
CURRENT_OHOS_ROOT = os.path.dirname(os.path.dirname(
    os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
CURRENT_BUILD_DIR = os.path.join(CURRENT_OHOS_ROOT, 'build')
CURRENT_HB_DIR = os.path.join(CURRENT_BUILD_DIR, 'hb')
DEFAULT_CCACHE_DIR = os.path.join(CURRENT_OHOS_ROOT, '.ccache')

ARGS_DIR = os.path.join(CURRENT_HB_DIR, 'resources/args')

DEFAULT_BUILD_ARGS = os.path.join(
    CURRENT_HB_DIR, 'resources/args/default/buildargs.json')
DEFAULT_SET_ARGS = os.path.join(
    CURRENT_HB_DIR, 'resources/args/default/setargs.json')
DEFAULT_CLEAN_ARGS = os.path.join(
    CURRENT_HB_DIR, 'resources/args/default/cleanargs.json')
DEFAULT_ENV_ARGS = os.path.join(
    CURRENT_HB_DIR, 'resources/args/default/envargs.json')
DEFAULT_TOOL_ARGS = os.path.join(
    CURRENT_HB_DIR, 'resources/args/default/toolargs.json')

CURRENT_ARGS_DIR = os.path.join(CURRENT_OHOS_ROOT, 'out/hb_args')
CURRENT_BUILD_ARGS = os.path.join(                      #这里,就是这个文件buildargs.json,对应各种可支持的构建命令参数我们的命令有
                                                         #--ccache  -product-name等
    CURRENT_ARGS_DIR, 'buildargs.json')
CURRENT_SET_ARGS = os.path.join(
    CURRENT_ARGS_DIR, 'setargs.json')
CURRENT_CLEAN_ARGS = os.path.join(
    CURRENT_ARGS_DIR, 'cleanargs.json')
CURRENT_ENV_ARGS = os.path.join(
    CURRENT_ARGS_DIR, 'envargs.json')
CURRENT_TOOL_ARGS = os.path.join(
    CURRENT_ARGS_DIR, 'toolargs.json')

BUILD_CONFIG_FILE = os.path.join(
    CURRENT_HB_DIR, 'resources/config/config.json')
ROOT_CONFIG_FILE = os.path.join(CURRENT_OHOS_ROOT, 'out/ohos_config.json')
STATUS_FILE = os.path.join(CURRENT_HB_DIR, 'resources/status/status.json')

ENV_SETUP_FILE = os.path.join(
    CURRENT_BUILD_DIR, 'build_scripts', 'env_setup.sh')

5.SetArgsResolver类(参数解析器类)

作用:main中module_type = sys.argv[1] 读取第一个参数,我们的命令第一个是build则开始执行:给产品设定相关参数

有则直接从编译参数赋值,没有则进入产品参数设置参数

class SetArgsResolver(ArgsResolverInterface):

    def __init__(self, args_dict: dict):
        super().__init__(args_dict)     #调用ArgsResolverInterface父类方法

    @staticmethod
    def resolve_product_name(target_arg: Arg, set_module: SetModuleInterface):    //传入编译参数,产品设置参数
        config = Config()         
        product_info = dict()      #创建列表存储相关信息
        device_info = dict()
        if target_arg.arg_value == '':        //如果没有编译参数则进入菜单选择
            product_info = set_module._menu.select_product()     
        elif target_arg.arg_value.__contains__('@'):
            product_name, company_name = target_arg.arg_value.split('@', 2)    
            product_info = ProductUtil.get_product_info(
                product_name, company_name)
        else:
            product_info = ProductUtil.get_product_info(target_arg.arg_value)

        config.product = product_info.get('name')
        config.product_path = product_info.get('product_path')
        config.version = product_info.get('version')
        config.os_level = product_info.get('os_level')
        config.product_json = product_info.get('config')
        config.component_type = product_info.get('component_type')
        if product_info.get('product_config_path'):
            config.product_config_path = product_info.get(
                'product_config_path')
        else:
            config.product_config_path = product_info.get('path')

        device_info = ProductUtil.get_device_info(config.product_json)
        config.board = device_info.get('board')
        config.kernel = device_info.get('kernel')
        config.target_cpu = device_info.get('target_cpu')
        config.target_os = device_info.get('target_os')
        config.support_cpu = device_info.get("support_cpu")
        kernel_version = device_info.get('kernel_version')
        config.device_company = device_info.get('company')
        board_path = device_info.get('board_path')

        if product_info.get('build_out_path'):
            config.out_path = os.path.join(config.root_path,
                                           product_info.get('build_out_path'))
        else:
            if config.os_level == 'standard':
                config.out_path = os.path.join(config.root_path, 'out',
                                               config.board)
            else:
                config.out_path = os.path.join(config.root_path, 'out',
                                               config.board, config.product)

        if product_info.get('subsystem_config_json'):
            config.subsystem_config_json = product_info.get(
                'subsystem_config_json')
        else:
            config.subsystem_config_json = 'build/subsystem_config.json'

        subsystem_config_overlay_path = os.path.join(
            config.product_path, 'subsystem_config_overlay.json')
        if os.path.isfile(subsystem_config_overlay_path):
            if product_info.get('subsystem_config_overlay_json'):
                config.subsystem_config_overlay_json = product_info.get(
                    'subsystem_config_overlay_json')
            else:
                config.subsystem_config_overlay_json = subsystem_config_overlay_path

        if config.version == '2.0':
            config.device_path = board_path
        else:
            if config.os_level == "standard":
                config.device_path = board_path
            else:
                config.device_path = DeviceUtil.get_device_path(
                    board_path, config.kernel, kernel_version)

        if device_info.get('board_config_path'):
            config.device_config_path = device_info.get('board_config_path')
        else:
            config.device_config_path = config.device_path

        Arg.write_args_file(target_arg.arg_name,
                            product_info.get('name'), ModuleType.BUILD)
        Arg.write_args_file(target_arg.arg_name,
                            f"{product_info.get('name')}@{product_info.get('company')}", ModuleType.SET)

用于解析参数的工:

  1. 初始化方法 (__init__): 这个方法接受一个字典 args_dict 作为参数,并调用父类的初始化方法。在这里,父类应该是 ArgsResolverInterface,但在给出的代码中没有定义出来。通常,父类的初始化方法可能会做一些必要的准备工作,如设置一些属性。

  2. resolve_product_name 方法: 这是一个静态方法

    • 首先,它创建了一个 Config 对象,然后根据不同的情况获取产品信息和设备信息,并将它们存储在 config 对象中的相应属性中。

    • 接着,它根据获取的产品信息和设备信息设置了一系列 config 对象的属性,如产品路径、版本、操作系统级别、内核版本等。

    • 然后,它根据不同的条件设置了输出路径、子系统配置路径等。

    • 最后,它根据设备信息设置了设备路径和设备配置路径,并将参数信息写入相应的文件中。

这里就省略细节可自行了解

6.创建实例化对象ohos_set_module类

class OHOSSetModule(SetModuleInterface):

    _instance = None

    def __init__(self, args_dict: dict, args_resolver: ArgsResolverInterface, menu: MenuInterface):
        super().__init__(args_dict, args_resolver)
        self._menu = menu
        OHOSSetModule._instance = self

    @staticmethod
    def get_instance():
        if OHOSSetModule._instance is not None:
            return OHOSSetModule._instance
        else:
            raise OHOSException(
                'OHOSSetModule has not been instantiated', '0000')

    @property
    def menu(self):
        return self._menu

    def set_product(self):
        self.args_resolver.resolve_arg(self.args_dict['product_name'], self)

    def set_parameter(self):
        self.args_resolver.resolve_arg(self.args_dict['all'], self)

Ⅱ.开始构造OHOSBuildModule

第Ⅰ步中我们将所有的参数都返回到 OHOSBuildModule(args_dict编译参数, build_args_resolver各编译参数对应的解释器, preloader, loader, generate_ninja, ninja)中

class OHOSBuildModule(BuildModuleInterface):   #继承抽象类父类(接口)

    _instance = None

    def __init__(self,           #创建传入参数的实例
                 args_dict: dict,
                 args_resolver: ArgsResolverInterface,
                 preloader: PreloadInterface,
                 loader: LoadInterface,
                 target_generator: BuildFileGeneratorInterface,
                 target_compiler: BuildExecutorInterface):

        super().__init__(args_dict, args_resolver, preloader,   # super() 函数来调用父类的相同方法
                         loader, target_generator, target_compiler)
        OHOSBuildModule._instance = self
        self._start_time = SystemUtil.get_current_time()

    @property
    def build_time(self):     #计算构建花费时间
        return SystemUtil.get_current_time() - self._start_time

    @staticmethod
    def get_instance():       #获取实例,单例设计模式,保证该类只有一个实例
        if OHOSBuildModule._instance is not None:
            return OHOSBuildModule._instance
        else:
            raise OHOSException(
                'OHOSBuildModule has not been instantiated', '0000')

    @throw_exception     
    def run(self):         #构建
        try:
            super().run()
        except OHOSException as exception:
            raise exception
        else:
            LogUtil.hb_info('{} build success'.format(
                self.args_dict.get('product_name').arg_value))
            LogUtil.hb_info('Cost time:  {}'.format(self.build_time))

    def _prebuild(self):      
        self._run_phase(BuildPhase.PRE_BUILD)

    def _preload(self):
        self._run_phase(BuildPhase.PRE_LOAD)
        if self.args_dict.get('fast_rebuild', None) and not self.args_dict.get('fast_rebuild').arg_value:
            self.preloader.run()

    def _load(self):
        self._run_phase(BuildPhase.LOAD)
        if self.args_dict.get('fast_rebuild', None) and not self.args_dict.get('fast_rebuild').arg_value:
            self.loader.run()

    def _pre_target_generate(self):
        self._run_phase(BuildPhase.PRE_TARGET_GENERATE)

    def _target_generate(self):
        self._run_phase(BuildPhase.TARGET_GENERATE)
        if not self.args_dict.get("build_only_load").arg_value and not self.args_dict.get("fast_rebuild").arg_value:
            self.target_generator.run()

    def _post_target_generate(self):
        self._run_phase(BuildPhase.POST_TARGET_GENERATE)

    def _pre_target_compilation(self):
        self._run_phase(BuildPhase.PRE_TARGET_COMPILATION)

    def _target_compilation(self):
        self._run_phase(BuildPhase.TARGET_COMPILATION)
        if not self.args_dict.get("build_only_load").arg_value and not self.args_dict.get("build_only_gn").arg_value:
            self.target_compiler.run()

    def _post_target_compilation(self):
        self._run_phase(BuildPhase.POST_TARGET_COMPILATION)

    def _post_build(self):
        self._run_phase(BuildPhase.POST_BUILD)

    def _run_phase(self, phase: BuildPhase):
        '''Description: Traverse all registered parameters in build process and 
            execute the resolver function of the corresponding phase
        @parameter: [phase]:  Build phase corresponding to parameter
        @return :none
        '''
        for phase_arg in [arg for arg in self.args_dict.values()if arg.arg_phase == phase]:
            self.args_resolver.resolve_arg(phase_arg, self)
  • 28
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值