Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
__init__.py
00001 from __future__ import print_function, absolute_import 00002 from builtins import str 00003 00004 import os 00005 import copy 00006 import shutil 00007 00008 from os.path import relpath, join, exists, dirname, basename 00009 from os import makedirs, remove 00010 from json import load 00011 00012 from tools.export.exporters import Exporter, apply_supported_whitelist 00013 from tools.targets import TARGET_MAP 00014 from tools.utils import NotSupportedException 00015 from tools.build_api import prepare_toolchain 00016 00017 POST_BINARY_WHITELIST = set([ 00018 "TEENSY3_1Code.binary_hook", 00019 "MCU_NRF51Code.binary_hook", 00020 "LPCTargetCode.lpc_patch", 00021 "LPC4088Code.binary_hook" 00022 ]) 00023 00024 00025 class GNUARMNetbeans(Exporter): 00026 NAME = 'GNU ARM Netbeans' 00027 TOOLCHAIN = 'GCC_ARM' 00028 00029 @classmethod 00030 def is_target_supported(cls, target_name): 00031 target = TARGET_MAP[target_name] 00032 return apply_supported_whitelist( 00033 cls.TOOLCHAIN, POST_BINARY_WHITELIST, target) 00034 00035 @staticmethod 00036 def prepare_sys_lib(libname): 00037 return "-l" + libname 00038 00039 def toolchain_flags(self, toolchain): 00040 """Returns a dictionary of toolchain flags. 00041 Keys of the dictionary are: 00042 cxx_flags - c++ flags 00043 c_flags - c flags 00044 ld_flags - linker flags 00045 asm_flags - assembler flags 00046 common_flags - common options 00047 00048 The difference from the above is that it takes a parameter. 00049 """ 00050 00051 # Note: use the config options from the currently selected toolchain. 00052 config_header = self.toolchain.get_config_header() 00053 00054 flags = {key + "_flags": copy.deepcopy(value) for key, value 00055 in toolchain.flags.items()} 00056 if config_header: 00057 config_header = relpath(config_header, 00058 self.resources.file_basepath[config_header]) 00059 header_options = self.toolchain.get_config_option(config_header) 00060 flags['c_flags'] += header_options 00061 flags['cxx_flags'] += header_options 00062 return flags 00063 00064 @staticmethod 00065 def get_defines_and_remove_from_flags(flags_in, str_key): 00066 defines = [] 00067 flags_temp = copy.deepcopy(flags_in) 00068 for f in flags_temp[str_key]: 00069 f = f.strip() 00070 if f.startswith('-D'): 00071 defines.append(f[2:]) 00072 flags_in[str_key].remove(f) 00073 00074 return defines 00075 00076 @staticmethod 00077 def get_includes_and_remove_from_flags(flags_in, str_key): 00078 includes = [] 00079 flags_temp = copy.deepcopy(flags_in) 00080 next_is_include = False 00081 for f in flags_temp[str_key]: 00082 f = f.strip() 00083 if next_is_include: 00084 includes.append(f) 00085 flags_in[str_key].remove(f) 00086 next_is_include = False 00087 continue 00088 if f == "-include": 00089 flags_in[str_key].remove(f) 00090 next_is_include = True 00091 00092 return includes 00093 00094 @staticmethod 00095 def get_c_std_and_remove_from_flag(flags_in, str_key): 00096 comp_std = '' 00097 c_std = { 00098 'c90': 'c90', 'c89': 'c90', 'gnu90': 'gnu90', 'gnu89': 'gnu90', 00099 'c99': 'c99', 'c9x': 'c99', 'gnu99': 'gnu99', 'gnu9x': 'gnu98', 00100 'c11': 'c11', 'c1x': 'c11', 'gnu11': 'gnu11', 'gnu1x': 'gnu11' 00101 } 00102 cpp_std = { 00103 'c++98': 'cpp98', 'c++03': 'cpp98', 00104 'gnu++98': 'gnucpp98', 'gnu++03': 'gnucpp98', 00105 'c++0x': 'cpp0x', 'gnu++0x': 'gnucpp0x', 00106 'c++11': 'cpp11', 'gnu++11': 'gnucpp11', 00107 'c++1y': 'cpp1y', 'gnu++1y': 'gnucpp1y', 00108 'c++14': 'cpp14', 'gnu++14': 'gnucpp14', 00109 'c++1z': 'cpp1z', 'gnu++1z': 'gnucpp1z', 00110 } 00111 00112 flags_temp = copy.deepcopy(flags_in) 00113 for f in flags_temp[str_key]: 00114 f = f.strip() 00115 if f.startswith('-std='): 00116 comp_std = f[len('-std='):] 00117 flags_in[str_key].remove(f) 00118 elif f.startswith('-'): 00119 std = f[len('-'):] 00120 if std in c_std or std in cpp_std: 00121 comp_std = std 00122 flags_in[str_key].remove(f) 00123 return comp_std 00124 00125 def validate_resources(self): 00126 if not self.resources.linker_script: 00127 raise NotSupportedException("No linker script found.") 00128 00129 def create_jinja_ctx(self): 00130 self.options = {} 00131 flags = {} 00132 self.validate_resources() 00133 # Convert all Backslashes to Forward Slashes 00134 self.resources.win_to_unix() 00135 00136 self.ld_script = self.filter_dot( 00137 self.resources.linker_script) 00138 00139 # Read in all profiles, we'll extract compiler options. 00140 profiles = self.get_all_profiles() 00141 00142 profile_ids = [s.lower() for s in profiles] 00143 profile_ids.sort() 00144 for prof_id in profile_ids: 00145 # There are 4 categories of options, a category common too 00146 # all tools and a specific category for each of the tools. 00147 opts = {} 00148 opts['defines'] = {} 00149 opts['common'] = {} 00150 opts['as'] = {} 00151 opts['c'] = {} 00152 opts['cpp'] = {} 00153 opts['ld'] = {} 00154 00155 opts['id'] = prof_id 00156 opts['name'] = opts['id'].capitalize() 00157 00158 profile = profiles[prof_id] 00159 00160 # A small hack, do not bother with src_path again, 00161 # pass an empty string to avoid crashing. 00162 src_paths = [''] 00163 target_name = self.toolchain.target.name 00164 00165 toolchain = prepare_toolchain( 00166 src_paths, "", target_name, self.TOOLCHAIN, build_profile=[profile]) 00167 00168 flags = self.toolchain_flags(toolchain) 00169 00170 opts['defines'] = self.get_defines_and_remove_from_flags(flags, 'common_flags') 00171 opts['forced_includes'] = self.get_includes_and_remove_from_flags(flags, 'common_flags') 00172 opts['common'] = flags['common_flags'] 00173 opts['as'] = flags['asm_flags'] 00174 opts['c'] = flags['c_flags'] 00175 opts['cpp'] = flags['cxx_flags'] 00176 opts['ld'] = flags['ld_flags'] 00177 00178 self.options[prof_id] = opts 00179 00180 sources = [] # list of strings 00181 00182 forced_includes = self.get_includes_and_remove_from_flags(flags, 'c_flags') 00183 forced_includes += self.get_includes_and_remove_from_flags(flags, 'cxx_flags') 00184 00185 # Remove Duplicates 00186 forced_includes = list(set(forced_includes)) 00187 00188 c_std = self.get_c_std_and_remove_from_flag(flags, 'c_flags') 00189 cpp_std = self.get_c_std_and_remove_from_flag(flags, 'cxx_flags') 00190 00191 # Make one list of all resources 00192 for r_type in ['c_sources', 's_sources', 'cpp_sources']: 00193 sources.extend(getattr(self.resources, r_type)) 00194 00195 # Remove all leading './' 00196 c_sources = [self.filter_dot(field) for field in self.resources.c_sources] 00197 cpp_sources = [self.filter_dot(field) for field in self.resources.cpp_sources] 00198 s_sources = [self.filter_dot(field) for field in self.resources.s_sources] 00199 headers = [self.filter_dot(field) for field in self.resources.headers] 00200 sources = [self.filter_dot(field) for field in sources] 00201 include_paths = [self.filter_dot(field) for field in self.resources.inc_dirs] 00202 00203 sys_libs = [self.prepare_sys_lib(lib) for lib 00204 in self.toolchain.sys_libs] 00205 preproc = " ".join([basename(self.toolchain.preproc[0])] + 00206 self.toolchain.preproc[1:] + 00207 self.toolchain.ld[1:]) 00208 00209 if 'nbproject' in include_paths: 00210 include_paths.remove('nbproject') 00211 00212 jinja_ctx = { 00213 'name': self.project_name, 00214 'target': self.toolchain.target.name, 00215 'elf_location': join('BUILD', self.project_name) + '.elf', 00216 'c_symbols': self.toolchain.get_symbols(), 00217 'asm_symbols': self.toolchain.get_symbols(True), 00218 'c_flags': flags['c_flags'], 00219 'cxx_flags': flags['cxx_flags'], 00220 'ld_flags': self.flags['ld_flags'], 00221 'asm_flags': self.flags['asm_flags'], 00222 'common_flags': self.flags['common_flags'], 00223 'include_paths': include_paths, 00224 'forced_includes': forced_includes, 00225 'c_sources': c_sources, 00226 'cpp_sources': cpp_sources, 00227 's_sources': s_sources, 00228 'headers': headers, 00229 'headers_folder': self.get_netbeans_file_list(sorted(headers)), 00230 'sources_folder': self.get_netbeans_file_list(sorted(sources)), 00231 'options': self.options, 00232 'c_std': self.get_netbeans_c_std(c_std), 00233 'cpp_std': self.get_netbeans_cpp_std(cpp_std), 00234 'linker_script': self.ld_script, 00235 'linker_libs': sys_libs, 00236 'pp_cmd': preproc, 00237 'cc_cmd': self.toolchain.cc[0], 00238 'cppc_cmd': self.toolchain.cppc[0], 00239 'asm_cmd': self.toolchain.asm[0], 00240 'ld_cmd': self.toolchain.ld[0], 00241 'elf2bin_cmd': self.toolchain.elf2bin 00242 } 00243 return jinja_ctx 00244 00245 def generate(self): 00246 """Generate Makefile, configurations.xml & project.xml Netbeans project file 00247 """ 00248 jinja_ctx = self.create_jinja_ctx() 00249 00250 if not exists(join(self.export_dir, 'nbproject')): 00251 makedirs(join(self.export_dir, 'nbproject')) 00252 00253 self.gen_file('nb/configurations.tmpl', jinja_ctx, 'nbproject/configurations.xml') 00254 self.gen_file('nb/project.tmpl', jinja_ctx, 'nbproject/project.xml') 00255 self.gen_file_nonoverwrite('nb/mbedignore.tmpl', jinja_ctx, 00256 '.mbedignore') 00257 self.gen_file('nb/Makefile.tmpl', jinja_ctx, 'Makefile') 00258 00259 print('Done. Import the \'{0}\' project in Netbeans.'.format(self.project_name)) 00260 00261 @staticmethod 00262 def clean(_): 00263 shutil.rmtree("nbproject") 00264 remove("Makefile") 00265 00266 # ------------------------------------------------------------------------- 00267 00268 @staticmethod 00269 def filter_dot(str_in): 00270 """ 00271 Remove the './' prefix, if present. 00272 This function assumes that resources.win_to_unix() 00273 replaced all windows backslashes with slashes. 00274 """ 00275 if str_in is None: 00276 return None 00277 if str_in[:2] == './': 00278 return str_in[2:] 00279 return str_in 00280 00281 # ------------------------------------------------------------------------- 00282 00283 @staticmethod 00284 def get_all_profiles(): 00285 tools_path = dirname(dirname(dirname(__file__))) 00286 file_names = [join(tools_path, "profiles", fn) for fn in os.listdir( 00287 join(tools_path, "profiles")) if fn.endswith(".json")] 00288 00289 profiles = {} 00290 00291 for fn in file_names: 00292 content = load(open(fn)) 00293 profile_name = basename(fn).replace(".json", "") 00294 profiles[profile_name] = content 00295 00296 return profiles 00297 00298 @staticmethod 00299 def get_netbeans_file_list(file_list): 00300 cur_dir = '' 00301 prev_dir = '' 00302 output = [] 00303 folder_count = 1 00304 dir_depth = 0 00305 for item in file_list: 00306 cur_dir = os.path.dirname(item) 00307 dir_temp = os.path.normpath(cur_dir) 00308 prev_dir_temp = os.path.normpath(prev_dir) 00309 dir_list = dir_temp.split(os.sep) 00310 prev_dir_list = prev_dir_temp.split(os.sep) 00311 dir_depth = len(dir_list) 00312 00313 # Current File is in Directory: Compare the given dir with previous Dir 00314 if cur_dir and prev_dir != cur_dir: 00315 # evaluate all matched items (from current and previous list) 00316 matched = [] 00317 # Compare the Element in Previous Dir with the Elements in Current Dir 00318 # and add the equal Elements to the match-List 00319 for elem_prev_dir, elem_cur_dir in zip(prev_dir_list, dir_list): 00320 if elem_prev_dir == elem_cur_dir: 00321 matched.append(elem_cur_dir) 00322 00323 # calculate difference between matched and length 00324 diff = dir_depth - len(matched) 00325 00326 # if previous dir was not root 00327 if prev_dir != '': 00328 # if the elements count is not equal we calculate the difference 00329 if len(dir_list) != len(prev_dir_list): 00330 dir_depth_prev = len(prev_dir_list) 00331 delta = dir_depth_prev - len(matched) 00332 00333 for i in range(dir_depth_prev - delta, dir_depth_prev): 00334 output.append('</logicalFolder>') 00335 00336 # if the elements count is equal, we subtract the matched length from the total length 00337 else: 00338 for i in range(len(matched), len(dir_list)): 00339 output.append('</logicalFolder>') 00340 00341 for i in range(dir_depth - diff, dir_depth): 00342 output.append('<logicalFolder name="f' + str(folder_count) + '" displayName="' + str( 00343 dir_list[i]) + '" projectFiles="true">') 00344 folder_count += 1 00345 00346 # Current File is in root 00347 else: 00348 # Close Tag if we are in root and the previous dir wasn't 00349 if cur_dir == '' and prev_dir != '': 00350 for i in range(0, len(prev_dir_list)): 00351 output.append('</logicalFolder>') 00352 00353 # Save the Current Dir 00354 prev_dir = cur_dir 00355 output.append('<itemPath>' + str(item) + '</itemPath>') 00356 00357 if cur_dir != '': 00358 # close all open tags 00359 output.append('</logicalFolder>' * dir_depth) 00360 00361 return output 00362 00363 @staticmethod 00364 def get_netbeans_c_std(c_std): 00365 c_std_netbeans = 0 00366 if '89' in c_std: 00367 c_std_netbeans = 2 00368 elif '99' in c_std: 00369 c_std_netbeans = 3 00370 elif '11' in c_std: 00371 c_std_netbeans = 10 00372 return c_std_netbeans 00373 00374 @staticmethod 00375 def get_netbeans_cpp_std(cpp_std): 00376 cpp_std_netbeans = 0 00377 if '98' in cpp_std: 00378 cpp_std_netbeans = 4 00379 elif '11' in cpp_std: 00380 cpp_std_netbeans = 8 00381 elif '14' in cpp_std: 00382 cpp_std_netbeans = 11 00383 return cpp_std_netbeans
Generated on Tue Jul 12 2022 12:43:27 by
