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