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