• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4#
5# Copyright (c) 2024 Huawei Device Co., Ltd.
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19import os
20import re
21import sys
22import stat
23import subprocess
24import csv
25
26from datetime import datetime
27from distutils.spawn import find_executable
28from containers.arg import Arg
29from containers.status import throw_exception
30from exceptions.ohos_exception import OHOSException
31from modules.interface.build_module_interface import BuildModuleInterface
32from resources.config import Config
33from resources.global_var import CURRENT_OHOS_ROOT, DEFAULT_BUILD_ARGS
34from resolver.interface.args_resolver_interface import ArgsResolverInterface
35from util.type_check_util import TypeCheckUtil
36from util.io_util import IoUtil
37from util.log_util import LogUtil
38from util.system_util import SystemUtil
39from util.type_check_util import TypeCheckUtil
40from util.component_util import ComponentUtil
41from util.product_util import ProductUtil
42from util.prebuild.patch_process import Patch
43from util.post_build.part_rom_statistics import output_part_rom_status
44
45
46def rename_file(source_file, target_file):
47    try:
48        os.rename(source_file, target_file)
49    except FileNotFoundError as rename_error:
50        LogUtil.hb_warning(rename_error)
51
52
53class BuildArgsResolver(ArgsResolverInterface):
54
55    def __init__(self, args_dict: dict):
56        super().__init__(args_dict)
57
58    @staticmethod
59    def resolve_product(target_arg: Arg, build_module: BuildModuleInterface):
60        """resolve '--product-name' arg.
61        :param target_arg: arg object which is used to get arg value.
62        :param build_module [maybe unused]: build module object which is used to get other services.
63        :phase: prebuild.
64        """
65        config = Config()
66        target_generator = build_module.target_generator
67        target_generator.regist_arg('product_name', config.product)
68        target_generator.regist_arg('product_path', config.product_path)
69        target_generator.regist_arg(
70            'product_config_path', config.product_config_path)
71
72        target_generator.regist_arg('device_name', config.board)
73        target_generator.regist_arg('device_path', config.device_path)
74        target_generator.regist_arg('device_company', config.device_company)
75        target_generator.regist_arg(
76            'device_config_path', config.device_config_path)
77
78        target_generator.regist_arg('target_cpu', config.target_cpu)
79        target_generator.regist_arg('precise_branch', config.precise_branch)
80        target_generator.regist_arg(
81            'is_{}_system'.format(config.os_level), True)
82
83        target_generator.regist_arg('ohos_kernel_type', config.kernel)
84        target_generator.regist_arg('ohos_build_compiler_specified',
85                                    ProductUtil.get_compiler(config.device_path))
86
87        target_generator.regist_arg('ohos_build_time',
88                                    SystemUtil.get_current_time(time_type='timestamp'))
89        target_generator.regist_arg('ohos_build_datetime',
90                                    SystemUtil.get_current_time(time_type='datetime'))
91
92        features_dict = ProductUtil.get_features_dict(config.product_json)
93        for key, value in features_dict.items():
94            target_generator.regist_arg(key, value)
95
96        if ProductUtil.get_compiler(config.device_path) == 'clang':
97            target_generator.regist_arg(
98                'ohos_build_compiler_dir', config.clang_path)
99
100        if target_arg.arg_value == 'ohos-sdk':
101            target_generator = build_module.target_generator
102            target_generator.regist_arg('build_ohos_sdk', True)
103            target_generator.regist_arg('build_ohos_ndk', True)
104            target_generator.regist_arg('enable_enhanced_opt', False)
105            if len(build_module.args_dict['build_target'].arg_value) == 0:
106                build_module.args_dict['build_target'].arg_value = [
107                    'build_ohos_sdk']
108            build_module.args_dict['target_cpu'].arg_value = 'arm64'
109        elif target_arg.arg_value == 'arkui-x':
110            target_generator = build_module.target_generator
111            target_generator.regist_arg('is_arkui_x', True)
112            target_generator.regist_arg('enable_ng_build', True)
113            target_generator.regist_arg('is_component_build', False)
114            target_generator.regist_arg('use_musl', False)
115            target_generator.regist_arg('is_use_check_deps', False)
116            if len(build_module.args_dict['build_target'].arg_value) == 0:
117                build_module.args_dict['build_target'].arg_value = [
118                    'arkui_targets']
119
120    @staticmethod
121    def resolve_target_cpu(target_arg: Arg, build_module: BuildModuleInterface):
122        """resolve '--target-cpu' arg.
123        :param target_arg: arg object which is used to get arg value.
124        :param build_module [maybe unused]: build module object which is used to get other services.
125        :phase: prebuild.
126        """
127        config = Config()
128        default_build_args = IoUtil.read_json_file(DEFAULT_BUILD_ARGS)
129        if config.target_cpu == "":
130            config.target_cpu = target_arg.arg_value
131        elif target_arg.arg_value != default_build_args.get("target_cpu").get("argDefault"):
132            config.target_cpu = target_arg.arg_value
133
134    @staticmethod
135    def resolve_target_os(target_arg: Arg, build_module: BuildModuleInterface):
136        """resolve '--target-os' arg.
137        :param target_arg: arg object which is used to get arg value.
138        :param build_module [maybe unused]: build module object which is used to get other services.
139        :phase: prebuild.
140        """
141        config = Config()
142        default_build_args = IoUtil.read_json_file(DEFAULT_BUILD_ARGS)
143        if config.target_os == "":
144            config.target_os = target_arg.arg_value
145        elif target_arg.arg_value != default_build_args.get("target_os").get("argDefault"):
146            config.target_os = target_arg.arg_value
147
148    @staticmethod
149    def resolve_precise_branch(target_arg: Arg, build_module: BuildModuleInterface):
150        """resolve '--precise-branch' arg.
151        :param target_arg: arg object which is used to get arg value.
152        :param build_module [maybe unused]: build module object which is used to get other services.
153        :phase: prebuild.
154        """
155        config = Config()
156        default_build_args = IoUtil.read_json_file(DEFAULT_BUILD_ARGS)
157        if config.precise_branch == "":
158            config.precise_branch = target_arg.arg_value
159        elif target_arg.arg_value != default_build_args.get("precise_branch").get("argDefault"):
160            config.precise_branch = target_arg.arg_value
161
162    @staticmethod
163    def get_tdd_repository(input_file):
164        if not os.path.isfile(input_file):
165            raise OHOSException(f'{input_file} not found')
166        config = Config()
167        target_set = set()
168        with open(input_file, 'r') as input_f:
169            data = csv.DictReader(input_f)
170            for csv_row in data:
171                if csv_row.get(config.precise_branch) == 'Y':
172                    target_set.add(csv_row['repoistory'])
173        return target_set
174
175    @staticmethod
176    def get_tdd_build_target(build_target_arg, build_module: BuildModuleInterface):
177        parts_file = os.path.join(CURRENT_OHOS_ROOT, 'test/testfwk/developer_test/precise_compilation/part_tdd.json')
178        tdd_manifest_file = os.path.join(CURRENT_OHOS_ROOT, '.repo/manifests/matrix_product.csv')
179        parts_data = IoUtil.read_json_file(parts_file)
180        repository_set = BuildArgsResolver.get_tdd_repository(tdd_manifest_file)
181        config = Config()
182        prefix = 'out/{}/build_configs/'.format(config.product)
183        target_name = build_target_arg[len('TDD'):]
184        build_targets = []
185        for target in target_name.split(','):
186            if target not in repository_set:
187                print('{} not find in csv!'.format(target))
188                continue
189            for item in parts_data:
190                if item['name'] == target:
191                    new_targets = [prefix + test_target for test_target in item['buildTarget'].split(',')]
192                    build_targets.extend(new_targets)
193                    break
194            else:
195                build_targets = ['build/ohos/packages:build_all_test_pkg']
196                target_generator = build_module.target_generator
197                target_generator.regist_arg('use_thin_lto', False)
198                break
199        return build_targets
200
201    @staticmethod
202    @throw_exception
203    def resolve_build_target(target_arg: Arg, build_module: BuildModuleInterface):
204        """resolve '--build-target' arg.
205        :param target_arg: arg object which is used to get arg value.
206        :param build_module [maybe unused]: build module object which is used to get other services.
207        :phase: prebuild.
208        :raise OHOSException: when build target not exist in compiling product.
209        """
210        config = Config()
211        build_executor = build_module.target_compiler
212        target_list = []
213        test_target_list = ['build_all_test_pkg', 'package_testcase', 'package_testcase_mlf']
214        if len(target_arg.arg_value):
215            for target_name in target_arg.arg_value:
216                if target_name.endswith('make_test') or target_name.split(':')[-1] in test_target_list:
217                    target_generator = build_module.target_generator
218                    target_generator.regist_arg('use_thin_lto', False)
219                    target_list.append(target_name)
220                elif target_name.startswith('TDD'):
221                    target_list.extend(BuildArgsResolver.get_tdd_build_target(target_name, build_module))
222                else:
223                    target_list.append(target_name)
224        else:
225            if os.getcwd() == CURRENT_OHOS_ROOT:
226                target_list = ['images']
227            elif ComponentUtil.is_in_component_dir(os.getcwd()) and \
228                    ComponentUtil.is_component_in_product(
229                    ComponentUtil.get_component_name(os.getcwd()), Config().product):
230                component_name = ComponentUtil.get_component_name(os.getcwd())
231                LogUtil.write_log(Config().log_path, 'In the component "{}" directory,'
232                                  'this compilation will compile only this component'.format(
233                                      component_name),
234                                  'warning')
235                target_list.append(component_name)
236                target_list.append(component_name + '_test')
237            else:
238                component_name = ComponentUtil.get_component_name(os.getcwd())
239                component_name = os.path.basename(
240                    os.getcwd()) if component_name == '' else component_name
241                raise OHOSException('There is no target component "{}" for the current product "{}"'
242                                    .format(component_name, Config().product), "4001")
243        build_executor.regist_arg('build_target', target_list)
244
245    @staticmethod
246    def resolve_rename_last_log(target_arg: Arg, build_module: BuildModuleInterface):
247        """resolve '--rename-last-log' arg
248        :param target_arg: arg object which is used to get arg value.
249        :param build_module [maybe unused]: build module object which is used to get other services.
250        :phase: prebuild.
251        """
252        if target_arg.arg_value:
253            config = Config()
254            out_path = config.out_path
255            logfile = os.path.join(out_path, 'build.log')
256            if os.path.exists(logfile):
257                mtime = os.stat(logfile).st_mtime
258                rename_file(logfile, '{}/build.{}.log'.format(out_path, mtime))
259
260    @staticmethod
261    def resolve_log_mode(target_arg: Arg, build_module: BuildModuleInterface):
262        """resolve '--log-mode' arg
263        :param target_arg: arg object which is used to get arg value.
264        :param build_module: build module object which is used to get other services.
265        :phase: prebuild.
266        """
267        if target_arg.arg_value:
268            config = Config()
269            config.log_mode = target_arg.arg_value
270
271    @staticmethod
272    def resolve_ccache(target_arg: Arg, build_module: BuildModuleInterface):
273        """resolve '--ccache' arg
274        :param target_arg: arg object which is used to get arg value.
275        :param build_module [maybe unused]: build module object which is used to get other services.
276        :phase: prebuild.
277        """
278        if target_arg.arg_value:
279            config = Config()
280            ccache_path = find_executable('ccache')
281            if ccache_path is None:
282                LogUtil.hb_warning('Failed to find ccache, ccache disabled.')
283                return
284            else:
285                target_generator = build_module.target_generator
286                target_generator.regist_arg(
287                    'ohos_build_enable_ccache', target_arg.arg_value)
288
289            ccache_local_dir = os.environ.get('CCACHE_LOCAL_DIR')
290            ccache_base = os.environ.get('CCACHE_BASE')
291            if not ccache_local_dir:
292                ccache_local_dir = '.ccache'
293            if not ccache_base:
294                ccache_base = os.environ.get('HOME')
295            ccache_base = os.path.join(ccache_base, ccache_local_dir)
296            if not os.path.exists(ccache_base):
297                os.makedirs(ccache_base, exist_ok=True)
298
299            ccache_log_suffix = os.environ.get('CCACHE_LOG_SUFFIX')
300            if ccache_log_suffix:
301                logfile = os.path.join(
302                    ccache_base, "ccache.{}.log".format(ccache_log_suffix))
303            elif os.environ.get('CCACHE_LOGFILE'):
304                logfile = os.environ.get('CCACHE_LOGFILE')
305                if not os.path.exists(os.path.dirname(logfile)):
306                    os.makedirs(os.path.dirname(logfile), exist_ok=True)
307            else:
308                logfile = os.path.join(ccache_base, "ccache.log")
309            if os.path.exists(logfile):
310                oldfile = '{}.old'.format(logfile)
311                if os.path.exists(oldfile):
312                    os.unlink(oldfile)
313                rename_file(logfile, oldfile)
314
315            os.environ['CCACHE_EXEC'] = ccache_path
316            os.environ['CCACHE_LOGFILE'] = logfile
317            os.environ['USE_CCACHE'] = '1'
318            os.environ['CCACHE_DIR'] = ccache_base
319            os.environ['CCACHE_UMASK'] = '002'
320            os.environ['CCACHE_BASEDIR'] = config.root_path
321            ccache_max_size = os.environ.get('CCACHE_MAXSIZE')
322            if not ccache_max_size:
323                ccache_max_size = '100G'
324
325            cmd = ['ccache', '-M', ccache_max_size]
326
327            SystemUtil.exec_command(cmd, log_path=config.log_path)
328
329    @staticmethod
330    def resolve_xcache(target_arg: Arg, build_module: BuildModuleInterface):
331        """resolve '--xcache' arg
332        :param target_arg: arg object which is used to get arg value.
333        :param build_module [maybe unused]: build module object which is used to get other services.
334        :phase: prebuild.
335        """
336        if target_arg.arg_value:
337            config = Config()
338            xcache_path = "/opt/buildtools/nextbuild/xcache"
339            if not os.path.exists(xcache_path):
340                LogUtil.hb_warning('Failed to find xcache, xcache disabled.')
341                return
342            else:
343                target_generator = build_module.target_generator
344                target_generator.regist_arg(
345                    'ohos_build_enable_xcache', target_arg.arg_value)
346                os.environ['XCACHE_EXEC'] = xcache_path
347                os.environ['USE_XCACHE'] = '1'
348
349    @staticmethod
350    def resolve_pycache(target_arg: Arg, build_module: BuildModuleInterface):
351        """resolve '--enable-pycache' arg
352        :param target_arg: arg object which is used to get arg value.
353        :param build_module [maybe unused]: build module object which is used to get other services.
354        :phase: prebuild.
355        """
356        if target_arg.arg_value:
357            config = Config()
358            pycache_dir = os.environ.get('CCACHE_BASE')
359            # The default value is HOME for local users
360            if not pycache_dir:
361                pycache_dir = os.environ.get('HOME')
362            pycache_dir = os.path.join(pycache_dir, '.pycache')
363            os.environ['PYCACHE_DIR'] = pycache_dir
364            pyd_start_cmd = [
365                'python3',
366                '{}/build/scripts/util/pyd.py'.format(config.root_path),
367                '--root',
368                pycache_dir,
369                '--start',
370            ]
371            cmd = ['/bin/bash', '-c', ' '.join(pyd_start_cmd), '&']
372            subprocess.Popen(cmd)
373
374    @staticmethod
375    def resolve_full_compilation(target_arg: Arg, build_module: BuildModuleInterface):
376        """resolve '--full-compilation' arg
377        :param target_arg: arg object which is used to get arg value.
378        :param build_module [maybe unused]: build module object which is used to get other services.
379        :phase: prebuild.
380        """
381        if target_arg.arg_value:
382            build_executor = build_module.target_compiler
383            target_list = build_executor.args_dict.get('build_target', None)
384            if isinstance(target_list, list):
385                target_list.append('make_all')
386                target_list.append('make_test')
387            else:
388                build_executor.regist_arg(
389                    'build_target', ['make_all', 'make_test'])
390            target_generator = build_module.target_generator
391            target_generator.regist_arg('use_thin_lto', False)
392
393    @staticmethod
394    @throw_exception
395    def resolve_gn_args(target_arg: Arg, build_module: BuildModuleInterface):
396        """resolve '--gn-args' arg
397        :param target_arg: arg object which is used to get arg value.
398        :param build_module [maybe unused]: build module object which is used to get other services.
399        :phase: prebuild.
400        :raise OHOSException: when some gn_arg is not in 'key=value' format.
401        """
402        target_generator = build_module.target_generator
403        target_generator.regist_arg(
404            'device_type', build_module.args_dict['device_type'].arg_value)
405        target_generator.regist_arg(
406            'build_variant', build_module.args_dict['build_variant'].arg_value)
407        if target_generator.args_dict['product_name'] == 'rk3568' and not build_module.loader.args_dict['build_xts']:
408            target_generator.regist_arg('ohos_components_checktype', 4)
409
410        for gn_args in target_arg.arg_value:
411            try:
412                gn_args_list = gn_args.split()
413                for gn_arg in gn_args_list:
414                    variable, value = gn_arg.split('=')
415                    if TypeCheckUtil.is_bool_type(value):
416                        if str(value).lower() == 'false':
417                            convert_value = False
418                        elif str(value).lower() == 'true':
419                            convert_value = True
420                    elif TypeCheckUtil.is_int_type(value):
421                        convert_value = int(value)
422                    elif isinstance(value, list):
423                        convert_value = list(value)
424                    else:
425                        convert_value = str(value).strip('"')
426                    target_generator.regist_arg(variable, convert_value)
427            except ValueError:
428                raise OHOSException(f'Invalid gn args: {gn_arg}', "0001")
429
430    @staticmethod
431    @throw_exception
432    def resolve_gn_flags(target_arg: Arg, build_module: BuildModuleInterface):
433        """resolve '--gn-flags' arg
434        :param target_arg: arg object which is used to get arg value.
435        :param build_module [maybe unused]: build module object which is used to get other services.
436        :phase: targetGenerate.
437        :raise OHOSException: when some gn_arg is not in 'key=value' format.
438        """
439        target_generator = build_module.target_generator
440        gn_flags_list = []
441        for gn_flags in target_arg.arg_value:
442            gn_flags = re.sub("'", "", gn_flags)
443            gn_flags_list.append(gn_flags)
444        target_generator.regist_flag('gn_flags', gn_flags_list)
445
446    @staticmethod
447    @throw_exception
448    def resolve_ninja_args(target_arg: Arg, build_module: BuildModuleInterface):
449        """resolve '--ninja-args' arg
450        :param target_arg: arg object which is used to get arg value.
451        :param build_module [maybe unused]: build module object which is used to get other services.
452        :phase: prebuild.
453        :raise OHOSException: when the value of the ninja parameter does not use quotation marks.
454        """
455        build_executor = build_module.target_compiler
456        ninja_args_list = []
457        for ninja_arg in target_arg.arg_value:
458            ninja_arg = re.sub("'", "", ninja_arg)
459            ninja_args_list.append(ninja_arg)
460        build_executor.regist_arg('ninja_args', ninja_args_list)
461
462    @staticmethod
463    @throw_exception
464    def resolve_strict_mode(target_arg: Arg, build_module: BuildModuleInterface):
465        """resolve '--strict-mode' arg.
466        :param target_arg: arg object which is used to get arg value.
467        :param build_module [maybe unused]: build module object which is used to get other services.
468        :phase: load.
469        :raise OHOSException: when preloader or loader results not correct
470        """
471        if target_arg.arg_value:
472            preloader = build_module.preloader
473            loader = build_module.loader
474            if not preloader.outputs.check_outputs():
475                raise OHOSException('Preloader result not correct', "1001")
476            if not loader.outputs.check_outputs():
477                raise OHOSException('Loader result not correct ', "2001")
478
479    @staticmethod
480    def resolve_scalable_build(target_arg: Arg, build_module: BuildModuleInterface):
481        """resolve '--scalable-build' arg.
482        :param target_arg: arg object which is used to get arg value.
483        :param build_module [maybe unused]: build module object which is used to get other services.
484        :phase: load.
485        """
486        loader = build_module.loader
487        loader.regist_arg("scalable_build", target_arg.arg_value)
488
489    @staticmethod
490    def resolve_build_example(target_arg: Arg, build_module: BuildModuleInterface):
491        """resolve '--build-example' arg.
492        :param target_arg: arg object which is used to get arg value.
493        :param build_module [maybe unused]: build module object which is used to get other services.
494        :phase: load.
495        """
496        loader = build_module.loader
497        loader.regist_arg("build_example", target_arg.arg_value)
498
499    @staticmethod
500    def resolve_build_platform_name(target_arg: Arg, build_module: BuildModuleInterface):
501        """resolve '---build-platform-name' arg
502        :param target_arg: arg object which is used to get arg value.
503        :param build_module [maybe unused]: build module object which is used to get other services.
504        :phase: load.
505        """
506        loader = build_module.loader
507        loader.regist_arg("build_platform_name", target_arg.arg_value)
508
509    @staticmethod
510    def resolve_build_xts(target_arg: Arg, build_module: BuildModuleInterface):
511        """resolve '--build-xts' arg
512        :param target_arg: arg object which is used to get arg value.
513        :param build_module [maybe unused]: build module object which is used to get other services.
514        :phase: load.
515        """
516        loader = build_module.loader
517        loader.regist_arg("build_xts", target_arg.arg_value)
518        for gn_arg in build_module.args_dict['gn_args'].arg_value:
519            if 'pr_path_list' in gn_arg:
520                build_module.args_dict['gn_args'].arg_value.append("precise_xts=true")
521                config = Config()
522                variable, value = gn_arg.split('=')
523                pyd_start_cmd = [
524                    'python3',
525                    '{}/test/xts/acts/get_dependency.py'.format(config.root_path),
526                    value,
527                ]
528                subprocess.call(pyd_start_cmd)
529            if 'build_xts' in gn_arg:
530                variable, value = gn_arg.split('=')
531                if str(value).lower() == 'false':
532                    value = False
533                elif str(value).lower() == 'true':
534                    value = True
535                loader.regist_arg(variable, value)
536
537    @staticmethod
538    def resolve_ignore_api_check(target_arg: Arg, build_module: BuildModuleInterface):
539        """resolve '--ignore-api-check' arg
540        :param target_arg: arg object which is used to get arg value.
541        :param build_module [maybe unused]: build module object which is used to get other services.
542        :phase: load.
543        """
544        loader = build_module.loader
545        if len(target_arg.arg_value):
546            loader.regist_arg("ignore_api_check", target_arg.arg_value)
547        else:
548            loader.regist_arg("ignore_api_check", [
549                              'xts', 'common', 'testfwk'])
550
551    @staticmethod
552    def resolve_load_test_config(target_arg: Arg, build_module: BuildModuleInterface):
553        """resolve '--load-test-config' arg
554        :param target_arg: arg object which is used to get arg value.
555        :param build_module [maybe unused]: build module object which is used to get other services.
556        :phase: load.
557        """
558        loader = build_module.loader
559        loader.regist_arg("load_test_config", target_arg.arg_value)
560
561    @staticmethod
562    @throw_exception
563    def resolve_export_para(target_arg: Arg, build_module: BuildModuleInterface):
564        """resolve '--export-para' arg
565        :param target_arg: arg object which is used to get arg value.
566        :param build_module [maybe unused]: build module object which is used to get other services.
567        :phase: targetGenerate.
568        """
569        target_generator = build_module.target_generator
570        for gn_arg in target_arg.arg_value:
571            try:
572                variable, value = gn_arg.split(':')
573                if TypeCheckUtil.is_bool_type(value):
574                    if str(value).lower() == 'false':
575                        value = False
576                    elif str(value).lower() == 'true':
577                        value = True
578                elif TypeCheckUtil.is_int_type(value):
579                    value = int(value)
580                else:
581                    value = str(value)
582                target_generator.regist_arg(variable, value)
583            except ValueError:
584                raise OHOSException(f'Invalid gn args: {gn_arg}', "0001")
585
586    @staticmethod
587    def resolve_log_level(target_arg: Arg, build_module: BuildModuleInterface):
588        """resolve '--log-level' arg.
589        :param target_arg: arg object which is used to get arg value.
590        :param build_module [maybe unused]: build module object which is used to get other services.
591        :phase: targetGenerate.
592        """
593        if target_arg.arg_value == 'debug':
594            target_generator = build_module.target_generator
595            target_compiler = build_module.target_compiler
596            target_generator.regist_flag('-v', ''),
597            target_generator.regist_flag(
598                '--tracelog', '{}/gn_trace.log'.format(Config().out_path))
599            target_generator.regist_flag('--ide', 'json')
600            target_compiler.regist_arg('-v', '')
601
602    @staticmethod
603    @throw_exception
604    def resolve_test(target_arg: Arg, build_module: BuildModuleInterface):
605        """resolve '--test' arg
606        :param target_arg: arg object which is used to get arg value.
607        :param build_module [maybe unused]: build module object which is used to get other services.
608        :phase: targetGenerate.
609        """
610        if len(target_arg.arg_value) > 1:
611            target_generator = build_module.target_generator
612            # TODO: Ask sternly why the xts subsystem passes parameters in this way?
613            if 'notest' in target_arg.arg_value:
614                target_generator.regist_arg('ohos_test_args', 'notest')
615            elif 'xts' in target_arg.arg_value:
616                test_target_index = 1
617                if target_arg.arg_value.index('xts') == 1:
618                    test_target_index = 0
619                target_generator.regist_arg(
620                    'ohos_xts_test_args', target_arg.arg_value[test_target_index])
621            else:
622                raise OHOSException('Test type value "{}" is not support'
623                                    .format(target_arg.arg_value), "0002")
624
625    @staticmethod
626    def resolve_build_type(target_arg: Arg, build_module: BuildModuleInterface):
627        """resolve '--build-type' arg
628        :param target_arg: arg object which is used to get arg value.
629        :param build_module [maybe unused]: build module object which is used to get other services.
630        :phase: targetGenerate.
631        """
632        target_generator = build_module.target_generator
633        if target_arg.arg_value == 'debug':
634            target_generator.regist_arg('is_debug', True)
635        elif target_arg.arg_value == 'profile':
636            target_generator.regist_arg('is_profile', True)
637        # For historical reasons, this value must be debug
638        target_generator.regist_arg('ohos_build_type', 'debug')
639
640    @staticmethod
641    def resolve_root_perf_main(target_arg: Arg, build_module: BuildModuleInterface):
642        """resolve '--root-perf-main' arg
643        :param target_arg: arg object which is used to get arg value.
644        :param build_module [maybe unused]: build module object which is used to get other services.
645        :phase: targetGenerate.
646        """
647        target_generator = build_module.target_generator
648        target_generator.regist_arg('root_perf_main', target_arg.arg_value)
649
650    @staticmethod
651    def resolve_runtime_mode(target_arg: Arg, build_module: BuildModuleInterface):
652        """resolve '--runtime-mode' arg
653        :param target_arg: arg object which is used to get arg value.
654        :param build_module [maybe unused]: build module object which is used to get other services.
655        :phase: targetGenerate.
656        """
657        target_generator = build_module.target_generator
658        target_generator.regist_arg('runtime_mode', target_arg.arg_value)
659
660    @staticmethod
661    def resolve_keep_ninja_going(target_arg: Arg, build_module: BuildModuleInterface):
662        """resolve '--keep-ninja-going' arg
663        :param target_arg: arg object which is used to get arg value.
664        :param build_module [maybe unused]: build module object which is used to get other services.
665        :phase: targetCompilation.
666        """
667        if target_arg.arg_value:
668            target_compiler = build_module.target_compiler
669            target_compiler.regist_arg('-k1000000', '')
670
671    @staticmethod
672    def resolve_build_variant(target_arg: Arg, build_module: BuildModuleInterface):
673        """resolve '--build-variant' arg
674        :param target_arg: arg object which is used to get arg value.
675        :param build_module [maybe unused]: build module object which is used to get other services.
676        :phase: postTargetCompilation.
677        """
678        pass
679
680    @staticmethod
681    def resolve_device_type(target_arg: Arg, build_module: BuildModuleInterface):
682        """resolve '--device-type' arg
683        :param target_arg: arg object which is used to get arg value.
684        :param build_module [maybe unused]: build module object which is used to get other services.
685        :phase: postTargetCompilation.
686        """
687        config = Config()
688        ohos_para_data = []
689        ohos_para_file_path = os.path.join(
690            config.out_path, 'packages/phone/system/etc/param/ohos.para')
691        if target_arg.arg_value != 'default':
692            with os.fdopen(os.open(ohos_para_file_path,
693                                   os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR),
694                           'r', encoding='utf-8') as ohos_para_file:
695                for line in ohos_para_file:
696                    ohos_para_data.append(line)
697            for i, line in enumerate(ohos_para_data):
698                if ohos_para_data[i].__contains__('const.build.characteristics'):
699                    ohos_para_data[i] = 'const.build.characteristics=' + \
700                        target_arg.arg_value + '\n'
701                    break
702            data = ''
703            for line in ohos_para_data:
704                data += line
705            with os.fdopen(os.open(ohos_para_file_path,
706                                   os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR),
707                           'w', encoding='utf-8') as ohos_para_file:
708                ohos_para_file.write(data)
709
710    @staticmethod
711    def resolve_archive_image(target_arg: Arg, build_module: BuildModuleInterface):
712        """resolve '--archive-image' arg
713        :param target_arg: arg object which is used to get arg value.
714        :param build_module [maybe unused]: build module object which is used to get other services.
715        :phase: postTargetCompilation
716        """
717        if target_arg.arg_value:
718            config = Config()
719            image_path = os.path.join(
720                config.out_path, 'packages', 'phone', 'images')
721            if os.path.exists(image_path):
722                packaged_file_path = os.path.join(
723                    config.out_path, 'images.tar.gz')
724                cmd = ['tar', '-zcvf', packaged_file_path, image_path]
725                SystemUtil.exec_command(cmd, log_path=config.out_path)
726            else:
727                LogUtil.hb_info(
728                    '"--archive-image" option not work, cause the currently compiled product is not a standard product')
729
730    @staticmethod
731    def resolve_patch(target_arg: Arg, build_module: BuildModuleInterface):
732        """resolve '--patch' arg
733        :param target_arg: arg object which is used to get arg value.
734        :param build_module [maybe unused]: build module object which is used to get other services.
735        :phase: postTargetCompilation
736        """
737        if target_arg.arg_value:
738            patch_obj = Patch()
739            patch_obj.patch_make()
740
741    @staticmethod
742    def resolve_rom_size_statistics(target_arg: Arg, build_module: BuildModuleInterface):
743        """resolve '--rom-size-statistics' arg
744        :param target_arg: arg object which is used to get arg value.
745        :param build_module [maybe unused]: build module object which is used to get other services.
746        :phase: postTargetCompilation
747        """
748        if target_arg.arg_value:
749            output_part_rom_status(CURRENT_OHOS_ROOT)
750
751    @staticmethod
752    def resolve_stat_ccache(target_arg: Arg, build_module: BuildModuleInterface):
753        """resolve "--stat-ccache' arg
754        :param target_arg: arg object which is used to get arg value.
755        :param build_module [maybe unused]: build module object which is used to get other services.
756        :phase: postTargetCompilation
757        """
758        if target_arg.arg_value:
759            config = Config()
760            ccache_path = find_executable('ccache')
761            if ccache_path is None:
762                LogUtil.hb_warning('Failed to find ccache, ccache disabled.')
763                return
764            ccache_log_suffix = os.environ.get('CCACHE_LOG_SUFFIX')
765            if ccache_log_suffix:
766                logfile = "ccache.{}.log".format(ccache_log_suffix)
767            else:
768                logfile = "ccache.log"
769            ccache_local_dir = os.environ.get('CCACHE_LOCAL_DIR')
770            if not ccache_local_dir:
771                ccache_local_dir = '.ccache'
772            ccache_base = os.environ.get('CCACHE_BASE')
773
774            # The default value is HOME for local users
775            if not ccache_base:
776                ccache_base = os.environ.get('HOME')
777            ccache_base = os.path.join(ccache_base, ccache_local_dir)
778            if os.environ.get('CCACHE_LOGFILE'):
779                logfile = os.environ.get('CCACHE_LOGFILE')
780            else:
781                logfile = os.path.join(ccache_base, logfile)
782            cmd = [
783                'python3', '{}/build/scripts/summary_ccache_hitrate.py'.format(
784                    config.root_path), logfile
785            ]
786            if os.path.isfile(logfile):
787                SystemUtil.exec_command(cmd, log_path=config.log_path, log_stage="[POSTBUILD]")
788
789    @staticmethod
790    def resolve_get_warning_list(target_arg: Arg, build_module: BuildModuleInterface):
791        """resolve "--get-warning-list' arg
792        :param target_arg: arg object which is used to get arg value.
793        :param build_module [maybe unused]: build module object which is used to get other services.
794        :phase: postTargetCompilation
795        """
796        if target_arg.arg_value:
797            config = Config()
798            cmd = [
799                'python3',
800                '{}/build/scripts/get_warnings.py'.format(config.root_path),
801                '--build-log-file',
802                '{}/build.log'.format(config.out_path),
803                '--warning-out-file',
804                '{}/packages/WarningList.txt'.format(config.out_path),
805            ]
806            SystemUtil.exec_command(cmd, log_path=config.log_path, log_stage="[POSTBUILD]")
807
808    @staticmethod
809    def resolve_generate_ninja_trace(target_arg: Arg, build_module: BuildModuleInterface):
810        """resolve "--generate-ninja-trace' arg
811        :param target_arg: arg object which is used to get arg value.
812        :param build_module [maybe unused]: build module object which is used to get other services.
813        :phase: postTargetCompilation
814        """
815        if target_arg.arg_value:
816            config = Config()
817            # 中国标准时间与UTC标准时间差8h, _start_time记录为中国标准时间
818            epoch = datetime.utcfromtimestamp(28800)
819            unixtime = '%f' % (
820                (build_module.target_compiler._start_time - epoch).total_seconds() * 10**9)
821            cmd = [
822                'python3',
823                '{}/build/scripts/ninja2trace.py'.format(config.root_path),
824                '--ninja-log',
825                '{}/.ninja_log'.format(config.out_path),
826                "--trace-file",
827                "{}/build.trace".format(config.out_path),
828                "--ninja-start-time",
829                str(unixtime),
830                "--duration-file",
831                "{}/sorted_action_duration.txt".format(config.out_path),
832            ]
833            SystemUtil.exec_command(cmd, log_path=config.log_path, log_stage="[POSTBUILD]")
834
835    @staticmethod
836    def resolve_compute_overlap_rate(target_arg: Arg, build_module: BuildModuleInterface):
837        """resolve "--compute-overlap-rate' arg
838        :param target_arg: arg object which is used to get arg value.
839        :param build_module [maybe unused]: build module object which is used to get other services.
840        :phase: postTargetCompilation
841        """
842        if target_arg.arg_value:
843            config = Config()
844            subsystem_config_overlay_path = os.path.join(config.product_path,
845                                                         'subsystem_config_overlay.json')
846            if os.path.isfile(subsystem_config_overlay_path):
847                cmd = [
848                    'python3',
849                    '{}/build/ohos/statistics/build_overlap_statistics.py'.format(
850                        config.root_path), "--build-out-dir", config.out_path,
851                    "--subsystem-config-file",
852                    "{}/build/subsystem_config.json".format(config.root_path),
853                    "--subsystem-config-overlay-file",
854                    "{}/subsystem_config_overlay.json".format(
855                        config.product_path),
856                    "--root-source-dir", config.root_path
857                ]
858            else:
859                cmd = [
860                    'python3',
861                    '{}/build/ohos/statistics/build_overlap_statistics.py'.format(
862                        config.root_path), "--build-out-dir", config.out_path,
863                    "--subsystem-config-file",
864                    "{}/build/subsystem_config.json".format(config.root_path),
865                    "--root-source-dir", config.root_path
866                ]
867            SystemUtil.exec_command(cmd, log_path=config.log_path, log_stage="[POSTBUILD]")
868
869    @staticmethod
870    def resolve_deps_guard(target_arg: Arg, build_module: BuildModuleInterface):
871        """resolve '--deps-guard' arg
872        :param target_arg: arg object which is used to get arg value.
873        :param build_module [maybe unused]: build module object which is used to get other services.
874        :phase: postbuild
875        """
876        if target_arg.arg_value:
877            config = Config()
878            if config.os_level == "standard":
879                sys.path.append(os.path.join(
880                    config.root_path, "developtools/integration_verification/tools/deps_guard"))
881                from deps_guard import deps_guard
882                deps_guard(config.out_path, config.target_cpu)
883
884    @staticmethod
885    def resolve_skip_partlist_check(target_arg: Arg, build_module: BuildModuleInterface):
886        """resolve '--skip-partlist-check' arg
887        :param target_arg: arg object which is used to get arg value.
888        :param build_module [maybe unused]: build module object which is used to get other services.
889        :phase: load.
890        """
891        loader = build_module.loader
892        loader.regist_arg("skip_partlist_check", target_arg.arg_value)
893
894    @staticmethod
895    def resolve_clean_args(target_arg: Arg, build_module: BuildModuleInterface):
896        """resolve '--clean-args' arg
897        :param target_arg: arg object which is used to get arg value.
898        :param build_module [maybe unused]: build module object which is used to get other services.
899        :phase: postbuild
900        """
901        if target_arg.arg_value:
902            Arg.clean_args_file()
903
904    # PlaceHolder
905    @staticmethod
906    def resolve_compiler(target_arg: Arg, build_module: BuildModuleInterface):
907        return
908
909    # PlaceHolder
910    @staticmethod
911    def resolve_jobs(target_arg: Arg, build_module: BuildModuleInterface):
912        return
913
914    # PlaceHolder
915    @staticmethod
916    def resolve_disable_part_of_post_build(target_arg: Arg, build_module: BuildModuleInterface):
917        return
918
919    # PlaceHolder
920    @staticmethod
921    def resolve_disable_package_image(target_arg: Arg, build_module: BuildModuleInterface):
922        return
923
924    # PlaceHolder
925    @staticmethod
926    def resolve_disable_post_build(target_arg: Arg, build_module: BuildModuleInterface):
927        return
928
929    # PlaceHolder
930    @staticmethod
931    def resolve_build_only_load(target_arg: Arg, build_module: BuildModuleInterface):
932        return
933
934    # PlaceHolder
935    @staticmethod
936    def resolve_build_only_gn(target_arg: Arg, build_module: BuildModuleInterface):
937        return
938
939    # PlaceHolder
940    @staticmethod
941    def resolve_fast_rebuild(target_arg: Arg, build_module: BuildModuleInterface):
942        return
943