• 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: Default configrations of the project.
19'''
20
21import os
22import hashlib
23
24from scons_utils import colors
25from scons_utils import flag_r
26from scons_utils import flag
27from scons_utils import scons_pre_check
28from scons_utils import scons_usr_bool_option
29from scons_utils import SconsBuildError
30from scripts.common_env import *
31from scripts.common_env import module_dir
32
33class SconsEnvCfg:
34    def __init__(self):
35        """
36        Make sure compiler is ready
37        """
38        if (scons_pre_check([]) == False):
39            raise SconsBuildError("%s============== COULD NOT FIND COMPILER! =============%s"%
40                (colors['red'], colors['end']))
41        self.root = os.path.realpath(os.path.join(__file__, '..', '..', '..'))
42        self.os_root = os.path.realpath(os.path.join(self.root, 'platform', 'os', 'Huawei_LiteOS'))
43        self.tools_prefix = 'riscv32-unknown-elf-'
44
45        #Set input/output folders
46        tmp_dir = os.path.join('build', 'build_tmp')
47        final_dir = 'output'
48        self.log_path = os.path.join(tmp_dir, 'logs')
49        self.obj_path = os.path.join(tmp_dir, 'objs')
50        self.lib_path = os.path.join(tmp_dir, 'libs')
51        self.cache_path = os.path.join(tmp_dir, 'cache')
52        self.link_path = os.path.join(tmp_dir, 'scripts')
53        self.nv_path = os.path.join(tmp_dir, 'nv')
54        self.bin_path = os.path.join(final_dir, 'bin')
55
56        #NV settings.
57        self.nv_src_path = os.path.join('app', 'demo', 'nv')
58        self.nv_factory_name = 'hi3861_demo_factory.hnv'
59        self.nv_normal_name = 'hi3861_demo_normal.hnv'
60        #mss_nvi_db_fcc.xml  FCC
61        #mss_nvi_db.xml      CE
62        #mss_nvi_db_max.xml  MAX_POWER
63        if scons_usr_bool_option('CONFIG_CE_SUPPORT') == 'y':
64            self.nv_cfg_name = 'mss_nvi_db.xml'
65
66        if scons_usr_bool_option('CONFIG_FCC_SUPPORT') == 'y':
67            self.nv_cfg_name = 'mss_nvi_db_fcc.xml'
68
69        if scons_usr_bool_option('CONFIG_MAX_POWER_SUPPORT') == 'y':
70            self.nv_cfg_name = 'mss_nvi_db_max.xml'
71
72        #chip type
73        if scons_usr_bool_option('CONFIG_TARGET_CHIP_HI3861') == 'y':
74            self.chip_type = "Hi3861"
75        else:
76            self.chip_type = "Hi3861L"
77
78        #Link settings
79        self.base_sum = 'd11133fff0d435d699e27817e165cf1d10c1a951452bd07d40da5bcfc41ef773'
80        self.link_file = os.path.join(self.link_path, 'link.lds')
81        self.map_file = os.path.join(self.bin_path, '%s_demo.map'%(self.chip_type))
82        self.gcc_ver_num = '7.3.0'
83        self.app_name = None
84        self.target_name = None
85        self.app_builder = None
86        self.clean_list = [tmp_dir, final_dir]
87        self.clean_list.append(os.path.join('build', 'scripts', '__pycache__'))
88
89    def set_tools(self, env, tool_name='all', tool_value='default'):
90        #set compiler
91        if tool_name != 'all' and tool_value != 'default' and env.get(tool_name):
92            env[tool_name] = tool_value
93            return
94
95        if self.tools_prefix:
96            env['CC'] = '%sgcc'%self.tools_prefix
97            env['AR'] = '%sar'%self.tools_prefix
98            env['AS'] = '%sas'%self.tools_prefix
99            env['CXX'] = '%scpp'%self.tools_prefix
100            env['LINK'] = '%sld'%self.tools_prefix
101            env['RANLIB'] = '%sranlib'%self.tools_prefix
102            env['OBJCOPY'] = '%sobjcopy'%self.tools_prefix
103            env['OBJDUMP'] = '%sobjdump'%self.tools_prefix
104        else:
105            #default compiler without prefix, like gcc, g++, etc.
106            print("USE DEFAULT COMPILER...")
107
108    def get_tools(self, env, tool_name):
109        if env.get(tool_name) is None:
110            print('Not find tool:%s'%tool_name)
111        return env.get(tool_name)
112
113    def set_environs(self, env, env_name='all', env_value=None, module='common'):
114        #Set default compile environment.
115        if env_name != 'all' and env_value is not None and env.get(env_name):
116            env[env_name] = env_value
117            return
118
119        env['CHIP_TYPE'] = self.chip_type
120        env['ARFLAGS'] = get_proj_env_value('ar_flags', module)
121        env.Append(CCFLAGS=get_proj_env_value('opts', module))
122        env.Append(ASLAGS=get_proj_env_value('as_flags', module))
123        env.Append(LINKFLAGS=get_proj_env_value('link_flags', module))
124        env['LINK_SCRIPTS_FLAG'] = get_proj_env_value('link_scripts_flag', module)
125        env['CCCOMSTR'] = 'Compiling $SOURCE'
126        env['ARCOMSTR'] = 'Archiving $TARGET'
127        env.Append(CPPPATH=get_proj_env_value('common_inc_path', module))
128        env.Append(CPPDEFINES=get_proj_env_value('defines', module))
129        if get_proj_env_value('liteos_inc_path', module) is not None:
130            env.Append(CPPPATH = [os.path.join(self.os_root, x) for x in get_proj_env_value('liteos_inc_path', module)])
131
132    def append_environs(self, env, module, env_name = None):
133        if env_name is None:
134            env_name = []
135            for key in get_proj_env():
136                if get_proj_env_value(key, module) is not None:
137                    env_name.append(flag_r[key])
138
139        for x in set(env_name):
140            if x != 'CPPPATH':
141                env[x].extend(get_proj_env_value(flag[x], module))
142            else:
143                env[x].extend(get_proj_env_value('common_inc_path', module))
144                if get_proj_env_value('liteos_inc_path', module) is not None:
145                    env[x].extend([os.path.join(self.os_root, y) for y in get_proj_env_value('liteos_inc_path', module)])
146
147    def get_module_cfg(self, module, env_name, fixed=False):
148        if env_name != 'CPPPATH':
149            return get_proj_env_value(flag[env_name], module)
150        else:
151            cfg_list = []
152            inc_path = get_proj_env_value('common_inc_path', module)
153            if inc_path is not None:
154                for x in inc_path:
155                    if x.startswith('#'):
156                        cfg_list.append(x[2:])
157                    else:
158                        cfg_list.append(x)
159            if get_proj_env_value('liteos_inc_path', module) is not None:
160                cfg_list.extend([os.path.join(os.path.relpath(self.os_root, self.root), y) for y in get_proj_env_value('liteos_inc_path', module)])
161            return cfg_list
162
163    def get_module_dir(self, module):
164        """
165        Get module folder.
166        """
167        if module in module_dir:
168            return '%s'%(module_dir[module])
169        else:
170            print('PROJECT HAS NO MODULE NAMED [%s]'%module)
171            sys.exit(1)
172
173    def get_all_modules(self):
174        module_names = list(module_dir.keys())
175        return module_names
176
177    def get_module_libs(self, module, lib_name_only=False):
178        """
179        Get build module library settings
180        """
181        if module in proj_lib_cfg:
182            if lib_name_only == True:
183                return [lib_name for lib_name in proj_lib_cfg[module]]
184            else:
185                return proj_lib_cfg[module]
186        else:
187            print('PROJECT HAS NO MODULE NAMED [%s]'%module)
188            sys.exit(1)
189
190    def get_build_modules(self):
191        """
192        Get default build modules
193        """
194        return compile_module
195
196    def get_bootlib_path(self):
197        """
198        Get boot library path to be inclouded.
199        """
200        lib_paths = os_boot_path
201        return list(map(lambda x:'-L%s'%x, lib_paths))
202
203    def get_lib_path(self):
204        """
205        Get library path to be inclouded.
206        """
207        lib_paths = os_lib_path
208        gcc = '%sgcc'%self.tools_prefix
209        gcc_lib_path = ''
210        # found and include libgcc.a
211        env_path_param = os.environ['PATH'].split(':')
212        for param in env_path_param:
213            compiler = os.path.join(param, 'riscv32-unknown-elf-gcc')
214            if os.path.isfile(compiler): # make sure the dir is accessable
215                gcc_lib_path = param
216                break
217
218        gcc_lib_path = os.path.join(gcc_lib_path, '..', 'lib', 'gcc', 'riscv32-unknown-elf', self.gcc_ver_num)
219        lib_paths.append(gcc_lib_path)
220        lib_paths.extend([os.path.join(self.lib_path, self.get_module_dir(module)) for module in self.get_build_modules()])
221        lib_paths.append(self.link_path)
222        return list(map(lambda x:'-L%s'%x, lib_paths))
223
224    def get_boot_libs(self):
225        """
226        Get library name to be inclouded. Linker option -l follows the lib name without
227        prefix "lib" and surffix ".a", has to remove those parts from a library file name.
228        """
229        libs = [lib[3:-2] for lib in os.listdir(os.path.join(self.root, 'build', 'libs', 'boot_libs')) if lib.startswith('lib') and lib.endswith('.a')]
230        return libs
231
232    def get_libs(self):
233        """
234        Get library name to be inclouded. Linker option -l follows the lib name without
235        prefix "lib" and surffix ".a", has to remove those parts from a library file name.
236        """
237        libs = [lib[3:-2] for lib in os.listdir(os.path.join(self.root, 'build', 'libs')) if lib.startswith('lib') and lib.endswith('.a')]
238        libs.append('gcc')
239        for module_lib in [self.get_module_libs(module, True) for module in self.get_build_modules()]:
240            libs.extend(module_lib)
241        if scons_usr_bool_option('CONFIG_I2S_SUPPORT') == 'n':
242            libs.remove('i2s')
243        if scons_usr_bool_option('CONFIG_HILINK') == 'y':
244            libs.extend(['hilinkdevicesdk', 'hilinkota'])
245        return libs
246
247    def get_ohos_libs(self):
248        """
249        Get library name to be inclouded. Linker option -l follows the lib name without
250        prefix "lib" and surffix ".a", has to remove those parts from a library file name.
251        """
252        libs = [lib[3:-2] for lib in os.listdir(os.path.join(self.root, 'ohos', 'libs')) \
253                if lib.startswith('lib') and lib.endswith('.a')]
254        return libs
255
256    def del_tmp_files(self, file_path):
257        if os.path.isfile(file_path):
258            os.unlink(file_path)
259
260    def base_bin_check(self, target):
261        """
262        Check the output base bin everytime to make sure the binary would not break the core.
263        """
264        sha256sum = ''
265        with open (target, "rb") as base_bin:
266            bytes = base_bin.read()
267            sha256sum = hashlib.sha256(bytes).hexdigest()
268        #self.del_tmp_files(target)
269        if self.base_sum == sha256sum:
270            return None
271        raise SconsBuildError("%s============== BASE BIN IS DIFFERENT WITH FIRST COMPILE! =============%s" %
272            (colors['red'], colors['end']))
273
274    def set_clean_items(self, items):
275        """
276        Hook the clean items. Items would be deleted with "scons -c".
277        """
278        if items is None:
279            return
280        if isinstance(items, list):
281            self.clean_list.extend(items)
282            return
283        if isinstance(items, str):
284            self.clean_list.append(items)
285            return
286        raise SconsBuildError("%s============== PLEASE INPUT A LIST OR A STRING! =============%s" %
287            (colors['red'], colors['end']))
288
289    def set_app_builder(self, builder):
290        """
291        For new app.
292        """
293        self.app_builder = builder
294        self.app_builder.read_env()
295        self.app_param_update(builder.get_app_name())
296
297    def app_param_update(self, app_name):
298        """
299        Get settings for the new app.
300        """
301        self.app_name = app_name
302        self.target_name = '%s_%s'%((self.chip_type), self.app_name)
303        self.map_file = os.path.join(self.bin_path, '%s_%s.map'%((self.chip_type), self.app_name))
304
305        self.nv_src_path = os.path.join('app', app_name, 'nv')
306        self.nv_factory_name = '%s_%s_factory.hnv'%((self.chip_type), app_name)
307        self.nv_normal_name = '%s_%s_normal.hnv'%((self.chip_type), app_name)
308
309        if self.app_builder:
310            items = self.app_builder.get_app_cfg('CLEAN')
311            self.set_clean_items(items)
312            self.set_clean_items([os.path.join("tools", "nvtool", "out_nv_bin"),
313                                  os.path.join("tools", "nvtool", "__pycache__")])
314
315    def get_makefile_environs(self, module = 'common'):
316        makefile_environs = {
317            'var' : {
318                'RM':'rm -rf',
319                'MAKE':'make',
320                'MV':'mv',
321                'MAKE_DIR':'mkdir -p',
322
323                # set compiler
324                'CC':'$(TOOLS_PREFIX)gcc',
325                'AR':'$(TOOLS_PREFIX)ar',
326                'AS':'$(TOOLS_PREFIX)as',
327                'CXX':'$(TOOLS_PREFIX)cpp',
328                'LINK':'$(TOOLS_PREFIX)ld',
329                'RANLIB':'$(TOOLS_PREFIX)ranlib',
330                'OBJCOPY':'$(TOOLS_PREFIX)objcopy',
331                'OBJDUMP':'$(TOOLS_PREFIX)objdump',
332                'NV_CFG_NAME':self.nv_cfg_name,
333                'BASE_NUM':   self.base_sum,
334                'LOG_PATH':   self.log_path,
335                'OBJ_PATH':   self.obj_path,
336                'LIB_PATH':   self.lib_path,
337                'CACHE_PATH': self.cache_path,
338                'LINK_PATH':  self.link_path,
339                'NV_PATH':    self.nv_path
340            },
341            'append_var' : {
342                'LIBPATH':'-L%s -L%s'%(' -L'.join(os_lib_path), self.link_path),
343                #'LIBS':'-l%s'%(' -l'.join(self.get_libs())),
344                'LIBS':'-l%s'%(' -l'.join(['wifi', 'wifi_flash', 'system', 'litekernel_flash', 'gcc'])),
345            },
346            'mod_dir': {
347            }
348        }
349
350        for mod in module_dir:
351            makefile_environs['mod_dir']['%s_dir'%mod] = module_dir[mod]
352        print('-'*50,'\n',makefile_environs)
353        # Set input/output folders
354        '''
355        for flg in flag:
356            flg_cfg = self.get_module_cfg(module, flg, fixed=True)
357            if flg_cfg is None:
358                continue
359            makefile_environs[flg] = flg_cfg
360        '''
361        return makefile_environs
362