1#!/usr/bin/env python
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 sys
21import platform
22
23sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
24from .global_var import CURRENT_OHOS_ROOT
25from .global_var import BUILD_CONFIG_FILE
26from .global_var import ROOT_CONFIG_FILE
27from exceptions.ohos_exception import OHOSException
28from helper.singleton import Singleton
29from util.io_util import IoUtil
30from containers.status import throw_exception
31
32
33def get_config_path():
34    if not os.path.exists(ROOT_CONFIG_FILE):
35        IoUtil.copy_file(BUILD_CONFIG_FILE, ROOT_CONFIG_FILE)
36    return ROOT_CONFIG_FILE
37
38
39class Config(metaclass=Singleton):
40    def __init__(self):
41        self.config_json = ""
42        self._root_path = ""
43        self._board = ""
44        self._kernel = ""
45        self._product = ""
46        self._product_path = ""
47        self._device_path = ""
48        self._device_company = ""
49        self._patch_cache = ""
50        self._version = ""
51        self._os_level = ""
52        self._product_json = ""
53        self._target_os = ""
54        self._target_cpu = ""
55        self._out_path = ""
56        self._compile_config = ""
57        self._component_type = ""
58        self._device_config_path = ""
59        self._product_config_path = ""
60        self._subsystem_config_json = ""
61        self._subsystem_config_overlay_json = ""
62        self._support_cpu = ""
63        self._log_mode = ""
64        self.fs_attr = set()
65        self.platform = platform.system()
66        self.__post__init()
67
68    @property
69    def component_type(self):
70        return self._component_type
71
72    @component_type.setter
73    def component_type(self, value: str):
74        self._component_type = value
75        self.config_update('component_type', self._component_type)
76
77    @property
78    def target_os(self):
79        return self._target_os
80
81    @target_os.setter
82    def target_os(self, value: str):
83        self._target_os = value
84        self.config_update('target_os', self._target_os)
85
86    @property
87    def target_cpu(self):
88        return self._target_cpu
89
90    @target_cpu.setter
91    def target_cpu(self, value: str):
92        self._target_cpu = value
93        self.config_update('target_cpu', self._target_cpu)
94
95    @property
96    def version(self):
97        return self._version
98
99    @version.setter
100    def version(self, value: str):
101        self._version = value
102        self.config_update('version', self._version)
103
104    @property
105    def compile_config(self):
106        return self._compile_config
107
108    @compile_config.setter
109    def compile_config(self, value: str):
110        self._compile_config = value
111        self.config_update('compile_config', self._compile_config)
112
113    @property
114    def os_level(self):
115        return self._os_level
116
117    @os_level.setter
118    def os_level(self, value: str):
119        self._os_level = value
120        self.config_update('os_level', self._os_level)
121
122    @property
123    def product_json(self):
124        return self._product_json
125
126    @product_json.setter
127    def product_json(self, value: str):
128        self._product_json = value
129        self.config_update('product_json', self._product_json)
130
131    @property
132    @throw_exception
133    def root_path(self):
134        if self._root_path is None:
135            raise OHOSException('Failed to init compile config', '0019')
136
137        return self._root_path
138
139    @root_path.setter
140    def root_path(self, value: str):
141        self._root_path = os.path.abspath(value)
142        self.config_update('root_path', self._root_path)
143
144    @property
145    def board(self):
146        if self._board is None:
147            raise OHOSException('Failed to init compile config', '0019')
148        return self._board
149
150    @board.setter
151    def board(self, value: str):
152        self._board = value
153        self.config_update('board', self._board)
154
155    @property
156    def device_company(self):
157        if self._device_company is None:
158            raise OHOSException('Failed to init compile config', '0019')
159        return self._device_company
160
161    @device_company.setter
162    def device_company(self, value: str):
163        self._device_company = value
164        self.config_update('device_company', self._device_company)
165
166    @property
167    def kernel(self):
168        return self._kernel
169
170    @kernel.setter
171    def kernel(self, value: str):
172        self._kernel = value
173        self.config_update('kernel', self._kernel)
174
175    @property
176    def product(self):
177        if self._product is None:
178            raise OHOSException('Failed to init compile config', '0019')
179        return self._product
180
181    @product.setter
182    def product(self, value: str):
183        self._product = value
184        self.config_update('product', self._product)
185
186    @property
187    def product_path(self):
188        if self._product_path is None:
189            raise OHOSException('Failed to init compile config', '0019')
190        return self._product_path
191
192    @product_path.setter
193    def product_path(self, value: str):
194        self._product_path = value
195        self.config_update('product_path', self._product_path)
196
197    @property
198    def gn_product_path(self):
199        return self.product_path.replace(self.root_path, '/')
200
201    @property
202    def device_path(self):
203        if self._device_path is None:
204            raise OHOSException('Failed to init compile config', '0019')
205        return self._device_path
206
207    @device_path.setter
208    def device_path(self, value: str):
209        self._device_path = value
210        self.config_update('device_path', self._device_path)
211
212    @property
213    def gn_device_path(self):
214        return self.device_path.replace(self.root_path, '/')
215
216    @property
217    def build_path(self):
218        _build_path = os.path.join(self.root_path, 'build', 'lite')
219        if not os.path.isdir(_build_path):
220            raise OHOSException(f'Invalid build path: {_build_path}')
221        return _build_path
222
223    @property
224    def out_path(self):
225        return self._out_path
226
227    @out_path.setter
228    def out_path(self, value: str):
229        self._out_path = value
230        self.config_update('out_path', self._out_path)
231
232    @property
233    def device_config_path(self):
234        return self._device_config_path
235
236    @device_config_path.setter
237    def device_config_path(self, value: str):
238        self._device_config_path = value
239        self.config_update('device_config_path', self._device_config_path)
240
241    @property
242    def product_config_path(self):
243        return self._product_config_path
244
245    @product_config_path.setter
246    def product_config_path(self, value: str):
247        self._product_config_path = value
248        self.config_update('product_config_path', self._product_config_path)
249
250    @property
251    def subsystem_config_json(self):
252        return self._subsystem_config_json
253
254    @subsystem_config_json.setter
255    def subsystem_config_json(self, value: str):
256        self._subsystem_config_json = value
257        self.config_update('subsystem_config_json',
258                           self._subsystem_config_json)
259
260    @property
261    def subsystem_config_overlay_json(self):
262        return self._subsystem_config_overlay_json
263
264    @subsystem_config_overlay_json.setter
265    def subsystem_config_overlay_json(self, value: str):
266        self._subsystem_config_overlay_json = value
267        self.config_update('subsystem_config_overlay_json',
268                           self._subsystem_config_overlay_json)
269
270    @property
271    def support_cpu(self):
272        return self._support_cpu
273
274    @property
275    def log_mode(self):
276        return self._log_mode
277
278    @log_mode.setter
279    def log_mode(self, value):
280        self._log_mode = value
281        self.config_update('log_mode', self._log_mode)
282
283    @support_cpu.setter
284    def support_cpu(self, value: str):
285        self._support_cpu = value
286        self.config_update('support_cpu', self._support_cpu)
287
288    @property
289    def log_path(self):
290        if self.out_path is not None:
291            return os.path.join(self.out_path, 'build.log')
292        else:
293            raise OHOSException(f'Failed to get log_path')
294
295    @property
296    def vendor_path(self):
297        _vendor_path = os.path.join(self.root_path, 'vendor')
298        if not os.path.isdir(_vendor_path):
299            _vendor_path = ''
300        return _vendor_path
301
302    @property
303    def built_in_product_path(self):
304        _built_in_product_path = os.path.join(self.root_path,
305                                              'productdefine/common/products')
306        if not os.path.isdir(_built_in_product_path):
307            raise OHOSException(
308                f'Invalid built-in product path: {_built_in_product_path}')
309        return _built_in_product_path
310
311    @property
312    def built_in_product_path_for_llvm(self):
313        _built_in_product_path_for_llvm = os.path.join(self.root_path,
314                                              'toolchain/llvm-project/llvm_products')
315        return _built_in_product_path_for_llvm
316
317    @property
318    def build_tools_path(self):
319        try:
320            tools_path = IoUtil.read_json_file(
321                'build_tools/build_tools_config.json')[self.platform]['build_tools_path']
322            return os.path.join(self.root_path, tools_path)
323        except KeyError:
324            raise OHOSException(f'unidentified platform: {self.platform}')
325
326    @property
327    def gn_path(self):
328        repo_gn_path = os.path.join(self.build_tools_path, 'gn')
329        # gn exist.
330        if os.path.isfile(repo_gn_path):
331            return repo_gn_path
332        else:
333            raise OHOSException('There is no clang executable file at {}, \
334                          please execute build/prebuilts_download.sh'.format(repo_gn_path))
335
336    @property
337    def ninja_path(self):
338        repo_ninja_path = os.path.join(self.build_tools_path, 'ninja')
339        # ninja exist.
340        if os.path.isfile(repo_ninja_path):
341            return repo_ninja_path
342        else:
343            raise OHOSException('There is no clang executable file at {}, \
344                          please execute build/prebuilts_download.sh'.format(repo_ninja_path))
345
346    @property
347    def clang_path(self):
348        repo_clang_path = os.path.join('prebuilts', 'clang', 'ohos',
349                                       'linux-x86_64', 'llvm')
350        if not os.path.exists(repo_clang_path):
351            repo_clang_path = os.path.join('out', 'llvm-install')
352        # clang exist
353        if os.path.isdir(repo_clang_path):
354            return f'//{repo_clang_path}'
355        # clang installed manually or auto download
356        else:
357            raise OHOSException('There is no clang executable file at {}, \
358                          please execute build/prebuilts_download.sh'.format(repo_clang_path))
359
360    @property
361    def patch_cache(self):
362        return self._patch_cache
363
364    @patch_cache.setter
365    def patch_cache(self, value: str):
366        self._patch_cache = value
367        self.config_update('patch_cache', self._patch_cache)
368
369    def config_update(self, key: str, value: str):
370        config_content = IoUtil.read_json_file(self.config_json)
371        config_content[key] = value
372        IoUtil.dump_json_file(self.config_json, config_content)
373
374    def __post__init(self):
375        self.config_json = get_config_path()
376        config_content = IoUtil.read_json_file(self.config_json)
377        self.root_path = CURRENT_OHOS_ROOT
378        self.board = config_content.get('board', None)
379        self.kernel = config_content.get('kernel', None)
380        self.product = config_content.get('product', None)
381        self.product_path = config_content.get('product_path', None)
382        self.device_path = config_content.get('device_path', None)
383        self.device_company = config_content.get('device_company', None)
384        self.patch_cache = config_content.get('patch_cache', None)
385        self.version = config_content.get('version', '3.0')
386        self.os_level = config_content.get('os_level', 'small')
387        self.product_json = config_content.get('product_json', None)
388        self.target_os = config_content.get('target_os', None)
389        self.target_cpu = config_content.get('target_cpu', None)
390        self.out_path = config_content.get('out_path', None)
391        self.compile_config = config_content.get('compile_config', None)
392        self.component_type = config_content.get('component_type', None)
393        self.device_config_path = config_content.get('device_config_path',
394                                                     None)
395        self.product_config_path = config_content.get('product_config_path',
396                                                      None)
397        self.subsystem_config_json = config_content.get(
398            'subsystem_config_json', None)
399        self.support_cpu = config_content.get('support_cpu', None)
400        self.fs_attr = set()
401        self.platform = platform.system()
402        self.precise_branch = ""