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