• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# coding=utf-8
3
4'''
5* Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
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* Description: Utilities.
19'''
20
21import os
22import shutil
23from copy import deepcopy
24
25from hi_config_parser import usr_cfg_main
26from hi_config_parser import sys_cfg_main
27
28class SconsBuildError(Exception):
29    """
30    Error exception.
31    """
32    pass
33
34"""
35Colors to display the messages.
36"""
37colors = {}
38colors['cyan']   = '\033[96m'
39colors['purple'] = '\033[95m'
40colors['blue']   = '\033[94m'
41colors['green']  = '\033[92m'
42colors['yellow'] = '\033[93m'
43colors['red']    = '\033[91m'
44colors['end']    = '\033[0m'
45
46flag = {
47    'ARFLAGS' : 'ar_flags',
48    'CCFLAGS' : 'opts', #'cc_flags',
49    'ASLAGS' : 'as_flags',
50    'CPPDEFINES' : 'defines',
51    'CPPPATH' : ['liteos_inc_path', 'common_inc_path'],
52    'LINKFLAGS' : 'link_flags',
53    'LINK_SCRIPTS_FLAG' : 'link_scripts_flag'
54}
55
56flag_r = {
57    'ar_flags' : 'ARFLAGS',
58    'opts' : 'CCFLAGS',
59    'as_flags' : 'ASLAGS',
60    'defines' : 'CPPDEFINES',
61    'liteos_inc_path' : 'CPPPATH',
62    'common_inc_path' : 'CPPPATH',
63    'link_flags' : 'LINKFLAGS',
64    'link_scripts_flag' : 'LINK_SCRIPTS_FLAG'
65}
66
67def traverse_subdir(search_dir = '.', full_path = False):
68    src_path = []
69    for root, dirs, files in os.walk(search_dir):
70        if files != []:
71            src_path.append(os.path.relpath(root, search_dir)) if full_path == False else src_path.append(root)
72            print('relative dir:',os.path.relpath(root, search_dir) if full_path == False else root)
73    return src_path
74
75#compiler check
76def scons_env_param_check():
77    env_path_param = os.environ['PATH'].split(':')
78    for param in env_path_param:
79        compiler = os.path.join(param, 'riscv32-unknown-elf-gcc')
80        if os.path.isfile(compiler):
81            return True
82    return False
83
84#settings check
85def scons_pre_check(dir_list):
86    if len(dir_list) > 0 :
87        for dir in dir_list:
88            os.makedir(dir)
89    usr_config_path = os.path.join('build', 'config', 'usr_config.mk')
90    if os.path.isfile(usr_config_path) == False:
91        shutil.copyfile(os.path.join('tools', 'menuconfig', 'default.config'), usr_config_path)
92    return scons_env_param_check()
93
94#delete files while compiling.
95def cleanup(target, source, env):
96    for src in source:
97        name = str(src)
98        try:
99            if os.path.isfile(name):
100                os.remove(name)
101            elif os.path.isdir(name):
102                shutil.rmtree(name)
103            else:
104                print("%s not found! Skipped!"%src)
105        except:
106            print("Remove %s error! Skipped!"%src)
107
108#Display tips
109def show_burn_tips():
110    burn_tips_str = ''.join(
111                ["%s\n< ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >\n"%colors['purple'],
112                 "                              BUILD SUCCESS                              \n",
113                 "< ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >\n%s"%colors['end']
114                ])
115    print(burn_tips_str)
116
117#Display alert
118def show_alert(msg):
119    print("%s%s%s"%(colors['red'], msg, colors['end']))
120
121#Simple dd tool.
122def scons_bin_dd(source, target, **kw):
123    seek = kw.get('seek')
124    skip = kw.get('skip')
125    count = kw.get('count')
126    bs = kw.get('bs', 1024)
127    data = None
128    img_data = None
129    if seek is not None:
130        with open(source, 'rb') as src:
131            data = bytearray(src.read())
132        mode = 'ab+'
133        if os.path.exists(target):
134            mode = 'rb+'
135        with open(target, mode) as image:
136            image.seek(0, 1)
137            img_data = bytearray(image.read())
138        with open(target, 'wb') as image:
139            if count is not None:
140                append_len = count*bs
141            else:
142                append_len = len(data)
143            old_len = len(img_data)
144            new_len = seek*bs + append_len
145            if new_len > old_len:
146                wr_data = bytearray(new_len)
147                if old_len > 0:
148                    wr_data[0:old_len] = img_data
149                img_data = wr_data
150            img_data[seek*bs : new_len] = data[0 : append_len]
151            image.seek(0, 1)
152            image.write(img_data)
153        return True
154    if skip is not None:
155        with open(source, 'rb') as src:
156            src.seek(skip*bs)
157            data = src.read()
158        with open(target, 'wb') as image:
159            image.write(data)
160        return True
161    raise SconsBuildError("%s============== dd PARAMETER INPUT ERROR! =============%s"%(colors['red'], colors['end']))
162
163def bf_to_str(bf):
164    if bf is None:
165        return '(unknown targets product None in list)'
166    elif bf.node:
167        return '%s: %s'%(str(bf.node), bf.errstr)
168    elif bf.filename:
169        return '%s: %s'%(bf.filename, bf.errstr)
170    else:
171        return str(bf)
172
173"""
174Interfaces for reading the settings made by menuconfig.
175"""
176def scons_usr_string_option(option):
177    options = usr_cfg_main()
178    value = options.get(option)
179    if value:
180        value = value.strip('"')
181    return value
182
183def scons_usr_int_option(option):
184    options = usr_cfg_main()
185    return int(options.get(option))
186
187def scons_usr_bool_option(option):
188    options = usr_cfg_main()
189    if option in options.keys():
190        return options[option].lower()
191    return 'n'
192
193"""
194Interfaces for reading the settings of system.
195"""
196def scons_sys_string_option(option):
197    options = sys_cfg_main()
198    if option in options.keys():
199        return options[option].strip('"')
200    return None
201
202def scons_sys_bool_option(option):
203    options = sys_cfg_main()
204    if option in options.keys():
205        return options[option].lower()
206    return 'n'
207
208def get_opt_val(options, option):
209    bool_list = ['Y', 'y', 'N', 'n']
210    if options[option].isdigit():
211        return int(options.get(option))
212    elif options[option] in bool_list:
213        return options[option].lower()
214    else:
215        return options[option].strip('"')
216
217def scons_get_cfg_val(option):
218    usr_config = usr_cfg_main()
219    sys_config = sys_cfg_main()
220    if option in usr_config.keys():
221        return get_opt_val(usr_config, option)
222    elif option in sys_config.keys():
223        return get_opt_val(sys_config, option)
224    else:
225        return 'n'
226
227def select_added_cfg(macro, macro_val, macro_cfg, depends=None):
228    if isinstance(macro_val, str) and scons_get_cfg_val(macro) == macro_val:
229        if depends is None:
230            temp = deepcopy(macro_cfg)
231            for cfg in macro_cfg:
232                if '$' not in cfg:
233                    pass
234                else:
235                    tmp_cfg = cfg.split('=')[1].strip('$').strip('(').strip(')').strip()
236                    tmp_cfg_val = '%s=%s'%(cfg.split('=')[0], scons_get_cfg_val(tmp_cfg))
237                    temp.append(tmp_cfg_val)
238                    temp.remove(cfg)
239            return temp
240        (macro_2, macro_2_val) = depends
241        if scons_get_cfg_val(macro_2) == macro_2_val:
242            return macro_cfg
243    elif not isinstance(macro_val, str):
244        val = scons_get_cfg_val(macro)
245        if 'others' in macro_val:
246            except_list = deepcopy(macro_val)
247            except_list.remove('others')
248            if val in except_list:
249                return macro_cfg[val]
250            else:
251                return macro_cfg['others']
252        elif val in macro_val:
253            return macro_cfg[val]
254
255    return None
256
257def translate_env_value_to_str(name, macro_cfg, mod_flag):
258    if name == 'defines':
259        if isinstance(macro_cfg, str):
260            return 'DEFINES += -D%s'%macro_cfg if mod_flag is False else 'CCFLAGS += -D%s'%macro_cfg
261        else:
262            defines = ['-D%s'%x for x in macro_cfg if isinstance(x, str)]
263            defines.extend(['-D%s=%s'%x for x in macro_cfg if isinstance(x, tuple)])
264            return 'DEFINES += %s'%(' '.join(defines)) if mod_flag is False else 'CCFLAGS += %s'%(' '.join(defines))
265    elif name == 'liteos_inc_path':
266        os_path = '$(MAIN_TOPDIR)/platform/os/Huawei_LiteOS'
267        if isinstance(macro_cfg, str):
268            return 'INCLUDE += -I%s/%s'%(os_path, macro_cfg) if mod_flag is False else 'CCFLAGS += -I%s/%s'%(os_path, macro_cfg)
269        else:
270            includes = ['-I%s/%s'%(os_path, x) for x in macro_cfg]
271            return 'INCLUDE += %s'%('\\\n\t'.join(includes)) if mod_flag is False else 'CCFLAGS += %s'%('\\\n\t'.join(includes))
272    elif name == 'common_inc_path':
273        if isinstance(macro_cfg, str):
274            inc_str = '-I%s'%(macro_cfg[2:] if macro_cfg.startswith('#') else macro_cfg)
275            return 'INCLUDE += %s'%inc_str if mod_flag is False else 'CCFLAGS += %s'%inc_str
276        else:
277            inc_str = '-I$(MAIN_TOPDIR)/%s'%('\\\n\t-I$(MAIN_TOPDIR)/'.join([x[2:] for x in macro_cfg]))
278            return 'INCLUDE += %s'%inc_str if mod_flag is False else 'CCFLAGS += %s'%inc_str
279    else:
280        if isinstance(macro_cfg, str):
281            return '%s += %s'%(flag_r[name], macro_cfg)
282        else:
283            return '%s += %s'%(flag_r[name], ' '.join(macro_cfg))
284
285def condition_str(macro, macro_val, macro_cfg, env_type, depends = None, mod_flag = False):
286    if isinstance(macro_val, str):
287        if depends is None:
288            return 'ifeq ($(%s), %s)\n\t%s\nendif\n'%(macro, macro_val, translate_env_value_to_str(env_type, macro_cfg, mod_flag))
289        else:
290            (macro_2, macro_2_val) = depends
291            return 'ifeq ($(%s)_$(%s), %s_%s)\n\t%s\nendif\n'%(macro, macro_2, macro_val, macro_2_val, translate_env_value_to_str(env_type, macro_cfg, mod_flag))
292    else:
293        strs = ''
294        val_list = deepcopy(macro_val)
295        val_list.remove('others') if 'others' in val_list else None
296        strs = '%sifeq ($(%s), %s)\n\t%s\n'%(strs, macro, val_list[0], translate_env_value_to_str(env_type, macro_cfg[val_list[0]], mod_flag))
297        for val in val_list[1:]:
298            strs = '%selse ifeq ($(%s), %s)\n\t%s\n'%(strs, macro, val, translate_env_value_to_str(env_type, macro_cfg[val], mod_flag))
299        strs = '%selse\n\t%s\n'%(strs, translate_env_value_to_str(env_type, macro_cfg['others'], mod_flag)) if 'others' in macro_val else None
300        strs = '%sendif\n'%strs
301        return strs
302