306 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			306 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/env python3
 | |
| # -*- coding: utf-8 -*-
 | |
| 
 | |
| #
 | |
| # Copyright (c) 2023 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 sys
 | |
| import os
 | |
| from enum import Enum
 | |
| 
 | |
| from containers.status import throw_exception
 | |
| from exceptions.ohos_exception import OHOSException
 | |
| from services.interface.build_file_generator_interface import BuildFileGeneratorInterface
 | |
| from resources.config import Config
 | |
| from containers.arg import Arg, ModuleType
 | |
| from util.system_util import SystemUtil
 | |
| from util.io_util import IoUtil
 | |
| from util.log_util import LogUtil
 | |
| 
 | |
| 
 | |
| class CMDTYPE(Enum):
 | |
|     GEN = 1
 | |
|     PATH = 2
 | |
|     DESC = 3
 | |
|     LS = 4
 | |
|     REFS = 5
 | |
|     FORMAT = 6
 | |
|     CLEAN = 7
 | |
| 
 | |
| 
 | |
| class Gn(BuildFileGeneratorInterface):
 | |
| 
 | |
|     def __init__(self):
 | |
|         super().__init__()
 | |
|         self.config = Config()
 | |
|         self._regist_gn_path()
 | |
| 
 | |
|     def run(self):
 | |
|         self.execute_gn_cmd(CMDTYPE.GEN)
 | |
| 
 | |
|     @throw_exception
 | |
|     def execute_gn_cmd(self, cmd_type: int, **kwargs):
 | |
|         if cmd_type == CMDTYPE.GEN:
 | |
|             return self._execute_gn_gen_cmd()
 | |
|         elif cmd_type == CMDTYPE.PATH:
 | |
|             return self._execute_gn_path_cmd(**kwargs)
 | |
|         elif cmd_type == CMDTYPE.DESC:
 | |
|             return self._execute_gn_desc_cmd(**kwargs)
 | |
|         elif cmd_type == CMDTYPE.LS:
 | |
|             return self._execute_gn_ls_cmd(**kwargs)
 | |
|         elif cmd_type == CMDTYPE.REFS:
 | |
|             return self._execute_gn_refs_cmd(**kwargs)
 | |
|         elif cmd_type == CMDTYPE.FORMAT:
 | |
|             return self._execute_gn_format_cmd(**kwargs)
 | |
|         elif cmd_type == CMDTYPE.CLEAN:
 | |
|             return self._execute_gn_clean_cmd(**kwargs)
 | |
|         else:
 | |
|             raise OHOSException(
 | |
|                 'You are tring to use an unsupported gn cmd type "{}"'.format(cmd_type), '3001')
 | |
| 
 | |
|     '''Description: Get gn excutable path and regist it
 | |
|     @parameter: none
 | |
|     @return: Status
 | |
|     '''
 | |
| 
 | |
|     @throw_exception
 | |
|     def _regist_gn_path(self):
 | |
|         gn_path = os.path.join(self.config.root_path, 'prebuilts/build-tools/{}-x86/bin/gn'
 | |
|                 .format(sys.platform))
 | |
|         if os.path.exists(gn_path):
 | |
|             self.exec = gn_path
 | |
|         else:
 | |
|             raise OHOSException(
 | |
|                 'There is no gn executable file at {}'.format(gn_path), '0001')
 | |
| 
 | |
|     '''Description: Convert all registed args into a list
 | |
|     @parameter: none
 | |
|     @return: list of all registed args
 | |
|     '''
 | |
| 
 | |
|     def _convert_args(self) -> list:
 | |
|         args_list = []
 | |
| 
 | |
|         for key, value in self.args_dict.items():
 | |
|             if isinstance(value, bool):
 | |
|                 args_list.append('{}={}'.format(key, str(value).lower()))
 | |
| 
 | |
|             elif isinstance(value, str):
 | |
|                 args_list.append('{}="{}"'.format(key, value))
 | |
| 
 | |
|             elif isinstance(value, int):
 | |
|                 args_list.append('{}={}'.format(key, value))
 | |
| 
 | |
|             elif isinstance(value, list):
 | |
|                 args_list.append('{}="{}"'.format(key, "&&".join(value)))
 | |
| 
 | |
|         return args_list
 | |
| 
 | |
|     '''Description: Convert all registed flags into a list
 | |
|     @parameter: none
 | |
|     @return: list of all registed flags
 | |
|     '''
 | |
| 
 | |
|     def _convert_flags(self) -> list:
 | |
|         flags_list = []
 | |
| 
 | |
|         for key, value in self.flags_dict.items():
 | |
|             if key == 'gn_flags' and isinstance(value, list):
 | |
|                 flags_list += value
 | |
|             elif value == '':
 | |
|                 flags_list.append('{}'.format(key))
 | |
|             else:
 | |
|                 flags_list.append('{}={}'.format(key, str(value)).lower())
 | |
| 
 | |
|         return flags_list
 | |
| 
 | |
|     '''Description: Option validity check
 | |
|     @parameter: "option": Option to be checked
 | |
|                 "args_file": Option config file
 | |
|     @return: Inspection result(True|False)
 | |
|     '''
 | |
| 
 | |
|     def _check_options_validity(self, option: str, args_file: dict):
 | |
|         support_sub_options = args_file.get(
 | |
|             "arg_attribute").get("support_sub_options")
 | |
|         option_name = option.lstrip('-')
 | |
|         option_value = ""
 | |
|         if '=' in option:
 | |
|             option_name, option_value = option.lstrip('-').split('=')
 | |
|         if option_name in support_sub_options:
 | |
|             sub_optional_list = support_sub_options.get(
 | |
|                 option_name).get("arg_attribute").get("optional")
 | |
|             if sub_optional_list and option_value not in sub_optional_list:
 | |
|                 if not len(option_value):
 | |
|                     raise OHOSException('ERROR argument "--{}": Invalid choice "{}". '
 | |
|                                         'choose from {}'.format(option_name, option_value, sub_optional_list), '3006')
 | |
|                 else:
 | |
|                     raise OHOSException('ERROR argument "--{}": Invalid choice "{}". '
 | |
|                                         'choose from {}'.format(option_name, option_value, sub_optional_list), '3003')
 | |
|         else:
 | |
|             raise OHOSException('ERROR argument "{}": Invalid choice "{}". '
 | |
|                                 'choose from {}'.format(args_file.get("arg_name"),
 | |
|                                                         option, list(support_sub_options.keys())), '3003')
 | |
| 
 | |
|     '''Description: Execute 'gn gen' command using registed args
 | |
|     @parameter: kwargs TBD
 | |
|     @return: None
 | |
|     '''
 | |
| 
 | |
|     @throw_exception
 | |
|     def _execute_gn_gen_cmd(self, **kwargs):
 | |
|         gn_gen_cmd = [self.exec, 'gen',
 | |
|                       '--args={}'.format(' '.join(self._convert_args())),
 | |
|                       self.config.out_path] + self._convert_flags()
 | |
|         if self.config.os_level == 'mini' or self.config.os_level == 'small':
 | |
|             gn_gen_cmd.append(f'--script-executable={sys.executable}')
 | |
|         try:
 | |
|             LogUtil.write_log(self.config.log_path, 'Excuting gn command: {} {} --args="{}" {}'.format(
 | |
|                 self.exec, 'gen',
 | |
|                 ' '.join(self._convert_args()).replace('"', "\\\""),
 | |
|                 ' '.join(gn_gen_cmd[3:])),
 | |
|                 'info')
 | |
|             SystemUtil.exec_command(gn_gen_cmd, self.config.log_path)
 | |
|         except OHOSException:
 | |
|             raise OHOSException('GN phase failed', '3000')
 | |
| 
 | |
|     '''Description: Execute 'gn path' command using registed args
 | |
|     @parameter: kwargs TBD
 | |
|     @return: None
 | |
|     '''
 | |
| 
 | |
|     @throw_exception
 | |
|     def _execute_gn_path_cmd(self, **kwargs):
 | |
|         out_dir = kwargs.get("out_dir")
 | |
|         default_options = ['--all']
 | |
|         args_file = Arg.read_args_file(ModuleType.TOOL)['path']
 | |
|         if (os.path.exists(os.path.join(out_dir, "args.gn"))):
 | |
|             gn_path_cmd = [self.exec, 'path', out_dir]
 | |
|             for arg in kwargs.get('args_list'):
 | |
|                 if arg.startswith('-'):
 | |
|                     self._check_options_validity(arg, args_file)
 | |
|                 gn_path_cmd.append(arg)
 | |
|             gn_path_cmd.extend(default_options)
 | |
|             sort_index = gn_path_cmd.index
 | |
|             gn_path_cmd = list(set(gn_path_cmd))
 | |
|             gn_path_cmd.sort(key=sort_index)
 | |
|             SystemUtil.exec_command(gn_path_cmd)
 | |
|         else:
 | |
|             raise OHOSException(
 | |
|                 '"{}" Not a build directory.'.format(out_dir), '3004')
 | |
| 
 | |
|     '''Description: Execute 'gn desc' command using registed args
 | |
|     @parameter: kwargs TBD
 | |
|     @return: None
 | |
|     '''
 | |
| 
 | |
|     @throw_exception
 | |
|     def _execute_gn_desc_cmd(self, **kwargs):
 | |
|         out_dir = kwargs.get("out_dir")
 | |
|         default_options = ['--tree', '--blame']
 | |
|         args_file = Arg.read_args_file(ModuleType.TOOL)['desc']
 | |
|         if (os.path.exists(os.path.join(out_dir, "args.gn"))):
 | |
|             gn_desc_cmd = [self.exec, 'desc', out_dir]
 | |
|             for arg in kwargs.get('args_list'):
 | |
|                 if arg.startswith('-'):
 | |
|                     self._check_options_validity(arg, args_file)
 | |
|                 gn_desc_cmd.append(arg)
 | |
|             gn_desc_cmd.extend(default_options)
 | |
|             sort_index = gn_desc_cmd.index
 | |
|             gn_desc_cmd = list(set(gn_desc_cmd))
 | |
|             gn_desc_cmd.sort(key=sort_index)
 | |
|             SystemUtil.exec_command(gn_desc_cmd)
 | |
|         else:
 | |
|             raise OHOSException(
 | |
|                 '"{}" Not a build directory.'.format(out_dir), '3004')
 | |
| 
 | |
|     '''Description: Execute 'gn ls' command using registed args
 | |
|     @parameter: kwargs TBD
 | |
|     @return: None
 | |
|     '''
 | |
| 
 | |
|     @throw_exception
 | |
|     def _execute_gn_ls_cmd(self, **kwargs):
 | |
|         out_dir = kwargs.get("out_dir")
 | |
|         args_file = Arg.read_args_file(ModuleType.TOOL)['ls']
 | |
|         if (os.path.exists(os.path.join(out_dir, "args.gn"))):
 | |
|             gn_ls_cmd = [self.exec, 'ls', out_dir]
 | |
|             for arg in kwargs.get('args_list'):
 | |
|                 if arg.startswith('-'):
 | |
|                     self._check_options_validity(arg, args_file)
 | |
|                 gn_ls_cmd.append(arg)
 | |
|             SystemUtil.exec_command(gn_ls_cmd)
 | |
|         else:
 | |
|             raise OHOSException(
 | |
|                 '"{}" Not a build directory.'.format(out_dir), '3004')
 | |
| 
 | |
|     '''Description: Execute 'gn refs' command using registed args
 | |
|     @parameter: kwargs TBD
 | |
|     @return: None
 | |
|     '''
 | |
| 
 | |
|     @throw_exception
 | |
|     def _execute_gn_refs_cmd(self, **kwargs):
 | |
|         out_dir = kwargs.get("out_dir")
 | |
|         args_file = Arg.read_args_file(ModuleType.TOOL)['refs']
 | |
|         if (os.path.exists(os.path.join(out_dir, "args.gn"))):
 | |
|             gn_refs_cmd = [self.exec, 'refs', out_dir]
 | |
|             for arg in kwargs.get('args_list'):
 | |
|                 if arg.startswith('-'):
 | |
|                     self._check_options_validity(arg, args_file)
 | |
|                 gn_refs_cmd.append(arg)
 | |
|             SystemUtil.exec_command(gn_refs_cmd)
 | |
|         else:
 | |
|             raise OHOSException(
 | |
|                 '"{}" Not a build directory.'.format(out_dir), '3004')
 | |
| 
 | |
|     '''Description: Execute 'gn format' command using registed args
 | |
|     @parameter: kwargs TBD
 | |
|     @return: None
 | |
|     '''
 | |
| 
 | |
|     @throw_exception
 | |
|     def _execute_gn_format_cmd(self, **kwargs):
 | |
|         gn_format_cmd = [self.exec, 'format']
 | |
|         args_file = Arg.read_args_file(ModuleType.TOOL)['format']
 | |
|         for arg in kwargs.get("args_list"):
 | |
|             if (arg.endswith('.gn')):
 | |
|                 if (os.path.exists(arg)):
 | |
|                     gn_format_cmd.append(arg)
 | |
|                 else:
 | |
|                     raise OHOSException(
 | |
|                         "ERROR Couldn't read '{}'".format(arg), '3005')
 | |
|             else:
 | |
|                 if arg.startswith('-'):
 | |
|                     self._check_options_validity(arg, args_file)
 | |
|                 gn_format_cmd.append(arg)
 | |
|         SystemUtil.exec_command(gn_format_cmd)
 | |
| 
 | |
|     '''Description: Execute 'gn clean' command using registed args
 | |
|     @parameter: kwargs TBD
 | |
|     @return: None
 | |
|     '''
 | |
| 
 | |
|     @throw_exception
 | |
|     def _execute_gn_clean_cmd(self, **kwargs):
 | |
|         out_dir = kwargs.get("out_dir")
 | |
|         if (os.path.exists(os.path.join(out_dir, "args.gn"))):
 | |
|             gn_clean_cmd = [self.exec, 'clean', out_dir]
 | |
|             SystemUtil.exec_command(gn_clean_cmd)
 | |
|         else:
 | |
|             raise OHOSException('"{}" Not a build directory.'
 | |
|                                 'Usage: "gn clean <out_dir>"'.format(out_dir), '3004')
 |