Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
__init__.py
00001 """ 00002 mbed SDK 00003 Copyright (c) 2011-2017 ARM Limited 00004 00005 Licensed under the Apache License, Version 2.0 (the "License"); 00006 you may not use this file except in compliance with the License. 00007 You may obtain a copy of the License at 00008 00009 http://www.apache.org/licenses/LICENSE-2.0 00010 00011 Unless required by applicable law or agreed to in writing, software 00012 distributed under the License is distributed on an "AS IS" BASIS, 00013 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 See the License for the specific language governing permissions and 00015 limitations under the License. 00016 00017 Title: GNU ARM Eclipse (http://gnuarmeclipse.github.io) exporter. 00018 00019 Description: Creates a managed build project that can be imported by 00020 the GNU ARM Eclipse plug-ins. 00021 00022 Author: Liviu Ionescu <ilg@livius.net> 00023 """ 00024 00025 import os 00026 import copy 00027 import tempfile 00028 import shutil 00029 import copy 00030 00031 from subprocess import call, Popen, PIPE 00032 from os.path import splitext, basename, relpath, dirname, exists, join, dirname 00033 from random import randint 00034 from json import load 00035 00036 from tools.export.exporters import Exporter, apply_supported_whitelist 00037 from tools.options import list_profiles 00038 from tools.targets import TARGET_MAP 00039 from tools.utils import NotSupportedException 00040 from tools.build_api import prepare_toolchain 00041 00042 # ============================================================================= 00043 00044 00045 class UID : 00046 """ 00047 Helper class, used to generate unique ids required by .cproject symbols. 00048 """ 00049 @property 00050 def id(self): 00051 return "%0.9u" % randint(0, 999999999) 00052 00053 # Global UID generator instance. 00054 # Passed to the template engine, and referred as {{u.id}}. 00055 # Each invocation generates a new number. 00056 u = UID() 00057 00058 # ============================================================================= 00059 00060 00061 POST_BINARY_WHITELIST = set([ 00062 "TEENSY3_1Code.binary_hook", 00063 "MCU_NRF51Code.binary_hook", 00064 "LPCTargetCode.lpc_patch", 00065 "LPC4088Code.binary_hook" 00066 ]) 00067 00068 class GNUARMEclipse(Exporter ): 00069 NAME = 'GNU ARM Eclipse' 00070 TOOLCHAIN = 'GCC_ARM' 00071 00072 @classmethod 00073 def is_target_supported(cls, target_name): 00074 target = TARGET_MAP[target_name] 00075 return apply_supported_whitelist( 00076 cls.TOOLCHAIN, POST_BINARY_WHITELIST, target) 00077 00078 # override 00079 @property 00080 def flags(self): 00081 """Returns a dictionary of toolchain flags. 00082 Keys of the dictionary are: 00083 cxx_flags - c++ flags 00084 c_flags - c flags 00085 ld_flags - linker flags 00086 asm_flags - assembler flags 00087 common_flags - common options 00088 00089 The difference from the parent function is that it does not 00090 add macro definitions, since they are passed separately. 00091 """ 00092 00093 config_header = self.toolchain.get_config_header() 00094 flags = {key + "_flags": copy.deepcopy(value) for key, value 00095 in self.toolchain.flags.iteritems()} 00096 if config_header: 00097 config_header = relpath(config_header, 00098 self.resources.file_basepath[config_header]) 00099 flags['c_flags'] += self.toolchain.get_config_option(config_header) 00100 flags['cxx_flags'] += self.toolchain.get_config_option( 00101 config_header) 00102 return flags 00103 00104 def toolchain_flags(self, toolchain): 00105 """Returns a dictionary of toolchain flags. 00106 Keys of the dictionary are: 00107 cxx_flags - c++ flags 00108 c_flags - c flags 00109 ld_flags - linker flags 00110 asm_flags - assembler flags 00111 common_flags - common options 00112 00113 The difference from the above is that it takes a parameter. 00114 """ 00115 00116 # Note: use the config options from the currently selected toolchain. 00117 config_header = self.toolchain.get_config_header() 00118 00119 flags = {key + "_flags": copy.deepcopy(value) for key, value 00120 in toolchain.flags.iteritems()} 00121 if config_header: 00122 config_header = relpath(config_header, 00123 self.resources.file_basepath[config_header]) 00124 header_options = self.toolchain.get_config_option(config_header) 00125 flags['c_flags'] += header_options 00126 flags['cxx_flags'] += header_options 00127 return flags 00128 00129 def validate_resources(self): 00130 if not self.resources.linker_script: 00131 raise NotSupportedException("No linker script found.") 00132 00133 def create_jinja_ctx(self): 00134 00135 self.validate_resources() 00136 00137 self.resources.win_to_unix() 00138 00139 # TODO: use some logger to display additional info if verbose 00140 00141 libraries = [] 00142 # print 'libraries' 00143 # print self.resources.libraries 00144 for lib in self.resources.libraries: 00145 l, _ = splitext(basename(lib)) 00146 libraries.append(l[3:]) 00147 00148 self.system_libraries = [ 00149 'stdc++', 'supc++', 'm', 'c', 'gcc', 'nosys' 00150 ] 00151 00152 # Read in all profiles, we'll extract compiler options. 00153 profiles = self.get_all_profiles() 00154 00155 profile_ids = [s.lower() for s in profiles] 00156 profile_ids.sort() 00157 00158 # TODO: get the list from existing .cproject 00159 build_folders = [s.capitalize() for s in profile_ids] 00160 build_folders.append('BUILD') 00161 # print build_folders 00162 00163 objects = [self.filter_dot(s) for s in self.resources.objects] 00164 for bf in build_folders: 00165 objects = [o for o in objects if not o.startswith(bf + '/')] 00166 # print 'objects' 00167 # print objects 00168 00169 self.compute_exclusions() 00170 00171 self.include_path = [ 00172 self.filter_dot(s) for s in self.resources.inc_dirs] 00173 print 'Include folders: {0}'.format(len(self.include_path)) 00174 00175 self.as_defines = self.toolchain.get_symbols(True) 00176 self.c_defines = self.toolchain.get_symbols() 00177 self.cpp_defines = self.c_defines 00178 print 'Symbols: {0}'.format(len(self.c_defines)) 00179 00180 self.ld_script = self.filter_dot( 00181 self.resources.linker_script) 00182 print 'Linker script: {0}'.format(self.ld_script) 00183 00184 self.options = {} 00185 for id in profile_ids: 00186 00187 # There are 4 categories of options, a category common too 00188 # all tools and a specific category for each of the tools. 00189 opts = {} 00190 opts['common'] = {} 00191 opts['as'] = {} 00192 opts['c'] = {} 00193 opts['cpp'] = {} 00194 opts['ld'] = {} 00195 00196 opts['id'] = id 00197 opts['name'] = opts['id'].capitalize() 00198 00199 print 00200 print 'Build configuration: {0}'.format(opts['name']) 00201 00202 profile = profiles[id] 00203 00204 # A small hack, do not bother with src_path again, 00205 # pass an empty string to avoid crashing. 00206 src_paths = [''] 00207 target_name = self.toolchain.target.name 00208 toolchain = prepare_toolchain( 00209 src_paths, "", target_name, self.TOOLCHAIN, build_profile=[profile]) 00210 00211 # Hack to fill in build_dir 00212 toolchain.build_dir = self.toolchain.build_dir 00213 00214 flags = self.toolchain_flags(toolchain) 00215 00216 print 'Common flags:', ' '.join(flags['common_flags']) 00217 print 'C++ flags:', ' '.join(flags['cxx_flags']) 00218 print 'C flags:', ' '.join(flags['c_flags']) 00219 print 'ASM flags:', ' '.join(flags['asm_flags']) 00220 print 'Linker flags:', ' '.join(flags['ld_flags']) 00221 00222 # Most GNU ARM Eclipse options have a parent, 00223 # either debug or release. 00224 if '-O0' in flags['common_flags'] or '-Og' in flags['common_flags']: 00225 opts['parent_id'] = 'debug' 00226 else: 00227 opts['parent_id'] = 'release' 00228 00229 self.process_options(opts, flags) 00230 00231 opts['as']['defines'] = self.as_defines 00232 opts['c']['defines'] = self.c_defines 00233 opts['cpp']['defines'] = self.cpp_defines 00234 00235 opts['common']['include_paths'] = self.include_path 00236 opts['common']['excluded_folders'] = '|'.join( 00237 self.excluded_folders) 00238 00239 opts['ld']['library_paths'] = [ 00240 self.filter_dot(s) for s in self.resources.lib_dirs] 00241 00242 opts['ld']['object_files'] = objects 00243 opts['ld']['user_libraries'] = libraries 00244 opts['ld']['system_libraries'] = self.system_libraries 00245 opts['ld']['script'] = join(id.capitalize(), 00246 "linker-script-%s.ld" % id) 00247 opts['cpp_cmd'] = '"{}"'.format(toolchain.preproc[0]) + " " + " ".join(toolchain.preproc[1:]) 00248 00249 # Unique IDs used in multiple places. 00250 # Those used only once are implemented with {{u.id}}. 00251 uid = {} 00252 uid['config'] = u.id 00253 uid['tool_c_compiler'] = u.id 00254 uid['tool_c_compiler_input'] = u.id 00255 uid['tool_cpp_compiler'] = u.id 00256 uid['tool_cpp_compiler_input'] = u.id 00257 00258 opts['uid'] = uid 00259 00260 self.options[id] = opts 00261 00262 jinja_ctx = { 00263 'name': self.project_name, 00264 'ld_script': self.ld_script, 00265 00266 # Compiler & linker command line options 00267 'options': self.options, 00268 00269 # Must be an object with an `id` property, which 00270 # will be called repeatedly, to generate multiple UIDs. 00271 'u': u, 00272 } 00273 return jinja_ctx 00274 00275 # override 00276 def generate(self): 00277 """ 00278 Generate the .project and .cproject files. 00279 """ 00280 jinja_ctx = self.create_jinja_ctx() 00281 00282 print 00283 print 'Create a GNU ARM Eclipse C++ managed project' 00284 print 'Project name: {0}'.format(self.project_name) 00285 print 'Target: {0}'.format(self.toolchain.target.name) 00286 print 'Toolchain: {0}'.format(self.TOOLCHAIN) 00287 00288 self.gen_file('gnuarmeclipse/.project.tmpl', jinja_ctx, 00289 '.project', trim_blocks=True, lstrip_blocks=True) 00290 self.gen_file('gnuarmeclipse/.cproject.tmpl', jinja_ctx, 00291 '.cproject', trim_blocks=True, lstrip_blocks=True) 00292 self.gen_file('gnuarmeclipse/makefile.targets.tmpl', jinja_ctx, 00293 'makefile.targets', trim_blocks=True, lstrip_blocks=True) 00294 self.gen_file('gnuarmeclipse/mbedignore.tmpl', jinja_ctx, '.mbedignore') 00295 00296 print 00297 print 'Done. Import the \'{0}\' project in Eclipse.'.format(self.project_name) 00298 00299 # override 00300 @staticmethod 00301 def build(project_name, log_name="build_log.txt", cleanup=True): 00302 """ 00303 Headless build an Eclipse project. 00304 00305 The following steps are performed: 00306 - a temporary workspace is created, 00307 - the project is imported, 00308 - a clean build of all configurations is performed and 00309 - the temporary workspace is removed. 00310 00311 The build results are in the Debug & Release folders. 00312 00313 All executables (eclipse & toolchain) must be in the PATH. 00314 00315 The general method to start a headless Eclipse build is: 00316 00317 $ eclipse \ 00318 --launcher.suppressErrors \ 00319 -nosplash \ 00320 -application org.eclipse.cdt.managedbuilder.core.headlessbuild \ 00321 -data /path/to/workspace \ 00322 -import /path/to/project \ 00323 -cleanBuild "project[/configuration] | all" 00324 """ 00325 00326 # TODO: possibly use the log file. 00327 00328 # Create a temporary folder for the workspace. 00329 tmp_folder = tempfile.mkdtemp() 00330 00331 cmd = [ 00332 'eclipse', 00333 '--launcher.suppressErrors', 00334 '-nosplash', 00335 '-application org.eclipse.cdt.managedbuilder.core.headlessbuild', 00336 '-data', tmp_folder, 00337 '-import', os.getcwd(), 00338 '-cleanBuild', project_name 00339 ] 00340 00341 p = Popen(' '.join(cmd), shell=True, stdout=PIPE, stderr=PIPE) 00342 out, err = p.communicate() 00343 ret_code = p.returncode 00344 stdout_string = "=" * 10 + "STDOUT" + "=" * 10 + "\n" 00345 err_string = "=" * 10 + "STDERR" + "=" * 10 + "\n" 00346 err_string += err 00347 00348 ret_string = "SUCCESS\n" 00349 if ret_code != 0: 00350 ret_string += "FAILURE\n" 00351 00352 print "%s\n%s\n%s\n%s" % (stdout_string, out, err_string, ret_string) 00353 00354 if log_name: 00355 # Write the output to the log file 00356 with open(log_name, 'w+') as f: 00357 f.write(stdout_string) 00358 f.write(out) 00359 f.write(err_string) 00360 f.write(ret_string) 00361 00362 # Cleanup the exported and built files 00363 if cleanup: 00364 if exists(log_name): 00365 os.remove(log_name) 00366 os.remove('.project') 00367 os.remove('.cproject') 00368 if exists('Debug'): 00369 shutil.rmtree('Debug') 00370 if exists('Release'): 00371 shutil.rmtree('Release') 00372 if exists('makefile.targets'): 00373 os.remove('makefile.targets') 00374 00375 # Always remove the temporary folder. 00376 if exists(tmp_folder): 00377 shutil.rmtree(tmp_folder) 00378 00379 if ret_code == 0: 00380 # Return Success 00381 return 0 00382 00383 # Seems like something went wrong. 00384 return -1 00385 00386 # ------------------------------------------------------------------------- 00387 00388 @staticmethod 00389 def get_all_profiles(): 00390 tools_path = dirname(dirname(dirname(__file__))) 00391 file_names = [join(tools_path, "profiles", fn) for fn in os.listdir( 00392 join(tools_path, "profiles")) if fn.endswith(".json")] 00393 00394 # print file_names 00395 00396 profile_names = [basename(fn).replace(".json", "") 00397 for fn in file_names] 00398 # print profile_names 00399 00400 profiles = {} 00401 00402 for fn in file_names: 00403 content = load(open(fn)) 00404 profile_name = basename(fn).replace(".json", "") 00405 profiles[profile_name] = content 00406 00407 return profiles 00408 00409 # ------------------------------------------------------------------------- 00410 # Process source files/folders exclusions. 00411 00412 def compute_exclusions(self): 00413 """ 00414 With the project root as the only source folder known to CDT, 00415 based on the list of source files, compute the folders to not 00416 be included in the build. 00417 00418 The steps are: 00419 - get the list of source folders, as dirname(source_file) 00420 - compute the top folders (subfolders of the project folder) 00421 - iterate all subfolders and add them to a tree, with all 00422 nodes markes as 'not used' 00423 - iterate the source folders and mark them as 'used' in the 00424 tree, including all intermediate nodes 00425 - recurse the tree and collect all unused folders; descend 00426 the hierarchy only for used nodes 00427 """ 00428 source_folders = [self.filter_dot(s) for s in set(dirname( 00429 src) for src in self.resources.c_sources + self.resources.cpp_sources + self.resources.s_sources)] 00430 00431 self.excluded_folders = set(self.resources.ignored_dirs) - set(self.resources.inc_dirs) 00432 print 'Source folders: {0}, with {1} exclusions'.format(len(source_folders), len(self.excluded_folders)) 00433 00434 00435 # ------------------------------------------------------------------------- 00436 00437 @staticmethod 00438 def filter_dot(str): 00439 """ 00440 Remove the './' prefix, if present. 00441 This function assumes that resources.win_to_unix() 00442 replaced all windows backslashes with slashes. 00443 """ 00444 if str == None: 00445 return None 00446 if str[:2] == './': 00447 return str[2:] 00448 return str 00449 00450 # ------------------------------------------------------------------------- 00451 00452 def dump_tree(self, nodes, depth=0): 00453 for k in nodes.keys(): 00454 node = nodes[k] 00455 parent_name = node['parent'][ 00456 'name'] if 'parent' in node.keys() else '' 00457 print ' ' * depth, node['name'], node['is_used'], parent_name 00458 if len(node['children'].keys()) != 0: 00459 self.dump_tree(node['children'], depth + 1) 00460 00461 def dump_paths(self, nodes, depth=0): 00462 for k in nodes.keys(): 00463 node = nodes[k] 00464 parts = [] 00465 while True: 00466 parts.insert(0, node['name']) 00467 if 'parent' not in node: 00468 break 00469 node = node['parent'] 00470 path = '/'.join(parts) 00471 print path, nodes[k]['is_used'] 00472 self.dump_paths(nodes[k]['children'], depth + 1) 00473 00474 # ------------------------------------------------------------------------- 00475 00476 def process_options(self, opts, flags_in): 00477 """ 00478 CDT managed projects store lots of build options in separate 00479 variables, with separate IDs in the .cproject file. 00480 When the CDT build is started, all these options are brought 00481 together to compose the compiler and linker command lines. 00482 00483 Here the process is reversed, from the compiler and linker 00484 command lines, the options are identified and various flags are 00485 set to control the template generation process. 00486 00487 Once identified, the options are removed from the command lines. 00488 00489 The options that were not identified are options that do not 00490 have CDT equivalents and will be passed in the 'Other options' 00491 categories. 00492 00493 Although this process does not have a very complicated logic, 00494 given the large number of explicit configuration options 00495 used by the GNU ARM Eclipse managed build plug-in, it is tedious... 00496 """ 00497 00498 # Make a copy of the flags, to be one by one removed after processing. 00499 flags = copy.deepcopy(flags_in) 00500 00501 if False: 00502 print 00503 print 'common_flags', flags['common_flags'] 00504 print 'asm_flags', flags['asm_flags'] 00505 print 'c_flags', flags['c_flags'] 00506 print 'cxx_flags', flags['cxx_flags'] 00507 print 'ld_flags', flags['ld_flags'] 00508 00509 # Initialise the 'last resort' options where all unrecognised 00510 # options will be collected. 00511 opts['as']['other'] = '' 00512 opts['c']['other'] = '' 00513 opts['cpp']['other'] = '' 00514 opts['ld']['other'] = '' 00515 00516 MCPUS = { 00517 'Cortex-M0': {'mcpu': 'cortex-m0', 'fpu_unit': None}, 00518 'Cortex-M0+': {'mcpu': 'cortex-m0plus', 'fpu_unit': None}, 00519 'Cortex-M1': {'mcpu': 'cortex-m1', 'fpu_unit': None}, 00520 'Cortex-M3': {'mcpu': 'cortex-m3', 'fpu_unit': None}, 00521 'Cortex-M4': {'mcpu': 'cortex-m4', 'fpu_unit': None}, 00522 'Cortex-M4F': {'mcpu': 'cortex-m4', 'fpu_unit': 'fpv4spd16'}, 00523 'Cortex-M7': {'mcpu': 'cortex-m7', 'fpu_unit': None}, 00524 'Cortex-M7F': {'mcpu': 'cortex-m7', 'fpu_unit': 'fpv4spd16'}, 00525 'Cortex-M7FD': {'mcpu': 'cortex-m7', 'fpu_unit': 'fpv5d16'}, 00526 'Cortex-A9': {'mcpu': 'cortex-a9', 'fpu_unit': 'vfpv3'} 00527 } 00528 00529 # Remove options that are supplied by CDT 00530 self.remove_option(flags['common_flags'], '-c') 00531 self.remove_option(flags['common_flags'], '-MMD') 00532 00533 # As 'plan B', get the CPU from the target definition. 00534 core = self.toolchain.target.core 00535 00536 opts['common']['arm.target.family'] = None 00537 00538 # cortex-m0, cortex-m0-small-multiply, cortex-m0plus, 00539 # cortex-m0plus-small-multiply, cortex-m1, cortex-m1-small-multiply, 00540 # cortex-m3, cortex-m4, cortex-m7. 00541 str = self.find_options(flags['common_flags'], '-mcpu=') 00542 if str != None: 00543 opts['common']['arm.target.family'] = str[len('-mcpu='):] 00544 self.remove_option(flags['common_flags'], str) 00545 self.remove_option(flags['ld_flags'], str) 00546 else: 00547 if core not in MCPUS: 00548 raise NotSupportedException( 00549 'Target core {0} not supported.'.format(core)) 00550 opts['common']['arm.target.family'] = MCPUS[core]['mcpu'] 00551 00552 opts['common']['arm.target.arch'] = 'none' 00553 str = self.find_options(flags['common_flags'], '-march=') 00554 arch = str[len('-march='):] 00555 archs = {'armv6-m': 'armv6-m', 'armv7-m': 'armv7-m', 'armv7-a': 'armv7-a'} 00556 if arch in archs: 00557 opts['common']['arm.target.arch'] = archs[arch] 00558 self.remove_option(flags['common_flags'], str) 00559 00560 opts['common']['arm.target.instructionset'] = 'thumb' 00561 if '-mthumb' in flags['common_flags']: 00562 self.remove_option(flags['common_flags'], '-mthumb') 00563 self.remove_option(flags['ld_flags'], '-mthumb') 00564 elif '-marm' in flags['common_flags']: 00565 opts['common']['arm.target.instructionset'] = 'arm' 00566 self.remove_option(flags['common_flags'], '-marm') 00567 self.remove_option(flags['ld_flags'], '-marm') 00568 00569 opts['common']['arm.target.thumbinterwork'] = False 00570 if '-mthumb-interwork' in flags['common_flags']: 00571 opts['common']['arm.target.thumbinterwork'] = True 00572 self.remove_option(flags['common_flags'], '-mthumb-interwork') 00573 00574 opts['common']['arm.target.endianness'] = None 00575 if '-mlittle-endian' in flags['common_flags']: 00576 opts['common']['arm.target.endianness'] = 'little' 00577 self.remove_option(flags['common_flags'], '-mlittle-endian') 00578 elif '-mbig-endian' in flags['common_flags']: 00579 opts['common']['arm.target.endianness'] = 'big' 00580 self.remove_option(flags['common_flags'], '-mbig-endian') 00581 00582 opts['common']['arm.target.fpu.unit'] = None 00583 # default, fpv4spd16, fpv5d16, fpv5spd16 00584 str = self.find_options(flags['common_flags'], '-mfpu=') 00585 if str != None: 00586 fpu = str[len('-mfpu='):] 00587 fpus = { 00588 'fpv4-sp-d16': 'fpv4spd16', 00589 'fpv5-d16': 'fpv5d16', 00590 'fpv5-sp-d16': 'fpv5spd16' 00591 } 00592 if fpu in fpus: 00593 opts['common']['arm.target.fpu.unit'] = fpus[fpu] 00594 00595 self.remove_option(flags['common_flags'], str) 00596 self.remove_option(flags['ld_flags'], str) 00597 if opts['common']['arm.target.fpu.unit'] == None: 00598 if core not in MCPUS: 00599 raise NotSupportedException( 00600 'Target core {0} not supported.'.format(core)) 00601 if MCPUS[core]['fpu_unit']: 00602 opts['common'][ 00603 'arm.target.fpu.unit'] = MCPUS[core]['fpu_unit'] 00604 00605 # soft, softfp, hard. 00606 str = self.find_options(flags['common_flags'], '-mfloat-abi=') 00607 if str != None: 00608 opts['common']['arm.target.fpu.abi'] = str[ 00609 len('-mfloat-abi='):] 00610 self.remove_option(flags['common_flags'], str) 00611 self.remove_option(flags['ld_flags'], str) 00612 00613 opts['common']['arm.target.unalignedaccess'] = None 00614 if '-munaligned-access' in flags['common_flags']: 00615 opts['common']['arm.target.unalignedaccess'] = 'enabled' 00616 self.remove_option(flags['common_flags'], '-munaligned-access') 00617 elif '-mno-unaligned-access' in flags['common_flags']: 00618 opts['common']['arm.target.unalignedaccess'] = 'disabled' 00619 self.remove_option(flags['common_flags'], '-mno-unaligned-access') 00620 00621 # Default optimisation level for Release. 00622 opts['common']['optimization.level'] = '-Os' 00623 00624 # If the project defines an optimisation level, it is used 00625 # only for the Release configuration, the Debug one used '-Og'. 00626 str = self.find_options(flags['common_flags'], '-O') 00627 if str != None: 00628 levels = { 00629 '-O0': 'none', '-O1': 'optimize', '-O2': 'more', 00630 '-O3': 'most', '-Os': 'size', '-Og': 'debug' 00631 } 00632 if str in levels: 00633 opts['common']['optimization.level'] = levels[str] 00634 self.remove_option(flags['common_flags'], str) 00635 00636 include_files = [] 00637 for all_flags in [flags['common_flags'], flags['c_flags'], flags['cxx_flags']]: 00638 while '-include' in all_flags: 00639 ix = all_flags.index('-include') 00640 str = all_flags[ix + 1] 00641 if str not in include_files: 00642 include_files.append(str) 00643 self.remove_option(all_flags, '-include') 00644 self.remove_option(all_flags, str) 00645 00646 opts['common']['include_files'] = include_files 00647 00648 if '-ansi' in flags['c_flags']: 00649 opts['c']['compiler.std'] = '-ansi' 00650 self.remove_option(flags['c_flags'], str) 00651 else: 00652 str = self.find_options(flags['c_flags'], '-std') 00653 std = str[len('-std='):] 00654 c_std = { 00655 'c90': 'c90', 'c89': 'c90', 'gnu90': 'gnu90', 'gnu89': 'gnu90', 00656 'c99': 'c99', 'c9x': 'c99', 'gnu99': 'gnu99', 'gnu9x': 'gnu98', 00657 'c11': 'c11', 'c1x': 'c11', 'gnu11': 'gnu11', 'gnu1x': 'gnu11' 00658 } 00659 if std in c_std: 00660 opts['c']['compiler.std'] = c_std[std] 00661 self.remove_option(flags['c_flags'], str) 00662 00663 if '-ansi' in flags['cxx_flags']: 00664 opts['cpp']['compiler.std'] = '-ansi' 00665 self.remove_option(flags['cxx_flags'], str) 00666 else: 00667 str = self.find_options(flags['cxx_flags'], '-std') 00668 std = str[len('-std='):] 00669 cpp_std = { 00670 'c++98': 'cpp98', 'c++03': 'cpp98', 00671 'gnu++98': 'gnucpp98', 'gnu++03': 'gnucpp98', 00672 'c++0x': 'cpp0x', 'gnu++0x': 'gnucpp0x', 00673 'c++11': 'cpp11', 'gnu++11': 'gnucpp11', 00674 'c++1y': 'cpp1y', 'gnu++1y': 'gnucpp1y', 00675 'c++14': 'cpp14', 'gnu++14': 'gnucpp14', 00676 'c++1z': 'cpp1z', 'gnu++1z': 'gnucpp1z', 00677 } 00678 if std in cpp_std: 00679 opts['cpp']['compiler.std'] = cpp_std[std] 00680 self.remove_option(flags['cxx_flags'], str) 00681 00682 # Common optimisation options. 00683 optimization_options = { 00684 '-fmessage-length=0': 'optimization.messagelength', 00685 '-fsigned-char': 'optimization.signedchar', 00686 '-ffunction-sections': 'optimization.functionsections', 00687 '-fdata-sections': 'optimization.datasections', 00688 '-fno-common': 'optimization.nocommon', 00689 '-fno-inline-functions': 'optimization.noinlinefunctions', 00690 '-ffreestanding': 'optimization.freestanding', 00691 '-fno-builtin': 'optimization.nobuiltin', 00692 '-fsingle-precision-constant': 'optimization.spconstant', 00693 '-fPIC': 'optimization.PIC', 00694 '-fno-move-loop-invariants': 'optimization.nomoveloopinvariants', 00695 } 00696 00697 for option in optimization_options: 00698 opts['common'][optimization_options[option]] = False 00699 if option in flags['common_flags']: 00700 opts['common'][optimization_options[option]] = True 00701 self.remove_option(flags['common_flags'], option) 00702 00703 # Common warning options. 00704 warning_options = { 00705 '-fsyntax-only': 'warnings.syntaxonly', 00706 '-pedantic': 'warnings.pedantic', 00707 '-pedantic-errors': 'warnings.pedanticerrors', 00708 '-w': 'warnings.nowarn', 00709 '-Wunused': 'warnings.unused', 00710 '-Wuninitialized': 'warnings.uninitialized', 00711 '-Wall': 'warnings.allwarn', 00712 '-Wextra': 'warnings.extrawarn', 00713 '-Wmissing-declarations': 'warnings.missingdeclaration', 00714 '-Wconversion': 'warnings.conversion', 00715 '-Wpointer-arith': 'warnings.pointerarith', 00716 '-Wpadded': 'warnings.padded', 00717 '-Wshadow': 'warnings.shadow', 00718 '-Wlogical-op': 'warnings.logicalop', 00719 '-Waggregate-return': 'warnings.agreggatereturn', 00720 '-Wfloat-equal': 'warnings.floatequal', 00721 '-Werror': 'warnings.toerrors', 00722 } 00723 00724 for option in warning_options: 00725 opts['common'][warning_options[option]] = False 00726 if option in flags['common_flags']: 00727 opts['common'][warning_options[option]] = True 00728 self.remove_option(flags['common_flags'], option) 00729 00730 # Common debug options. 00731 debug_levels = { 00732 '-g': 'default', 00733 '-g1': 'minimal', 00734 '-g3': 'max', 00735 } 00736 opts['common']['debugging.level'] = 'none' 00737 for option in debug_levels: 00738 if option in flags['common_flags']: 00739 opts['common'][ 00740 'debugging.level'] = debug_levels[option] 00741 self.remove_option(flags['common_flags'], option) 00742 00743 debug_formats = { 00744 '-ggdb': 'gdb', 00745 '-gstabs': 'stabs', 00746 '-gstabs+': 'stabsplus', 00747 '-gdwarf-2': 'dwarf2', 00748 '-gdwarf-3': 'dwarf3', 00749 '-gdwarf-4': 'dwarf4', 00750 '-gdwarf-5': 'dwarf5', 00751 } 00752 00753 opts['common']['debugging.format'] = '' 00754 for option in debug_levels: 00755 if option in flags['common_flags']: 00756 opts['common'][ 00757 'debugging.format'] = debug_formats[option] 00758 self.remove_option(flags['common_flags'], option) 00759 00760 opts['common']['debugging.prof'] = False 00761 if '-p' in flags['common_flags']: 00762 opts['common']['debugging.prof'] = True 00763 self.remove_option(flags['common_flags'], '-p') 00764 00765 opts['common']['debugging.gprof'] = False 00766 if '-pg' in flags['common_flags']: 00767 opts['common']['debugging.gprof'] = True 00768 self.remove_option(flags['common_flags'], '-gp') 00769 00770 # Assembler options. 00771 opts['as']['usepreprocessor'] = False 00772 while '-x' in flags['asm_flags']: 00773 ix = flags['asm_flags'].index('-x') 00774 str = flags['asm_flags'][ix + 1] 00775 00776 if str == 'assembler-with-cpp': 00777 opts['as']['usepreprocessor'] = True 00778 else: 00779 # Collect all other assembler options. 00780 opts['as']['other'] += ' -x ' + str 00781 00782 self.remove_option(flags['asm_flags'], '-x') 00783 self.remove_option(flags['asm_flags'], 'assembler-with-cpp') 00784 00785 opts['as']['nostdinc'] = False 00786 if '-nostdinc' in flags['asm_flags']: 00787 opts['as']['nostdinc'] = True 00788 self.remove_option(flags['asm_flags'], '-nostdinc') 00789 00790 opts['as']['verbose'] = False 00791 if '-v' in flags['asm_flags']: 00792 opts['as']['verbose'] = True 00793 self.remove_option(flags['asm_flags'], '-v') 00794 00795 # C options. 00796 opts['c']['nostdinc'] = False 00797 if '-nostdinc' in flags['c_flags']: 00798 opts['c']['nostdinc'] = True 00799 self.remove_option(flags['c_flags'], '-nostdinc') 00800 00801 opts['c']['verbose'] = False 00802 if '-v' in flags['c_flags']: 00803 opts['c']['verbose'] = True 00804 self.remove_option(flags['c_flags'], '-v') 00805 00806 warning_options = { 00807 '-Wmissing-prototypes': 'warnings.missingprototypes', 00808 '-Wstrict-prototypes': 'warnings.strictprototypes', 00809 '-Wbad-function-cast': 'warnings.badfunctioncast', 00810 } 00811 00812 for option in warning_options: 00813 opts['c'][warning_options[option]] = False 00814 if option in flags['common_flags']: 00815 opts['c'][warning_options[option]] = True 00816 self.remove_option(flags['common_flags'], option) 00817 00818 # C++ options. 00819 opts['cpp']['nostdinc'] = False 00820 if '-nostdinc' in flags['cxx_flags']: 00821 opts['cpp']['nostdinc'] = True 00822 self.remove_option(flags['cxx_flags'], '-nostdinc') 00823 00824 opts['cpp']['nostdincpp'] = False 00825 if '-nostdinc++' in flags['cxx_flags']: 00826 opts['cpp']['nostdincpp'] = True 00827 self.remove_option(flags['cxx_flags'], '-nostdinc++') 00828 00829 optimization_options = { 00830 '-fno-exceptions': 'optimization.noexceptions', 00831 '-fno-rtti': 'optimization.nortti', 00832 '-fno-use-cxa-atexit': 'optimization.nousecxaatexit', 00833 '-fno-threadsafe-statics': 'optimization.nothreadsafestatics', 00834 } 00835 00836 for option in optimization_options: 00837 opts['cpp'][optimization_options[option]] = False 00838 if option in flags['cxx_flags']: 00839 opts['cpp'][optimization_options[option]] = True 00840 self.remove_option(flags['cxx_flags'], option) 00841 if option in flags['common_flags']: 00842 opts['cpp'][optimization_options[option]] = True 00843 self.remove_option(flags['common_flags'], option) 00844 00845 warning_options = { 00846 '-Wabi': 'warnabi', 00847 '-Wctor-dtor-privacy': 'warnings.ctordtorprivacy', 00848 '-Wnoexcept': 'warnings.noexcept', 00849 '-Wnon-virtual-dtor': 'warnings.nonvirtualdtor', 00850 '-Wstrict-null-sentinel': 'warnings.strictnullsentinel', 00851 '-Wsign-promo': 'warnings.signpromo', 00852 '-Weffc++': 'warneffc', 00853 } 00854 00855 for option in warning_options: 00856 opts['cpp'][warning_options[option]] = False 00857 if option in flags['cxx_flags']: 00858 opts['cpp'][warning_options[option]] = True 00859 self.remove_option(flags['cxx_flags'], option) 00860 if option in flags['common_flags']: 00861 opts['cpp'][warning_options[option]] = True 00862 self.remove_option(flags['common_flags'], option) 00863 00864 opts['cpp']['verbose'] = False 00865 if '-v' in flags['cxx_flags']: 00866 opts['cpp']['verbose'] = True 00867 self.remove_option(flags['cxx_flags'], '-v') 00868 00869 # Linker options. 00870 linker_options = { 00871 '-nostartfiles': 'nostart', 00872 '-nodefaultlibs': 'nodeflibs', 00873 '-nostdlib': 'nostdlibs', 00874 } 00875 00876 for option in linker_options: 00877 opts['ld'][linker_options[option]] = False 00878 if option in flags['ld_flags']: 00879 opts['ld'][linker_options[option]] = True 00880 self.remove_option(flags['ld_flags'], option) 00881 00882 opts['ld']['gcsections'] = False 00883 if '-Wl,--gc-sections' in flags['ld_flags']: 00884 opts['ld']['gcsections'] = True 00885 self.remove_option(flags['ld_flags'], '-Wl,--gc-sections') 00886 00887 opts['ld']['flags'] = [] 00888 to_remove = [] 00889 for opt in flags['ld_flags']: 00890 if opt.startswith('-Wl,--wrap,'): 00891 opts['ld']['flags'].append( 00892 '--wrap=' + opt[len('-Wl,--wrap,'):]) 00893 to_remove.append(opt) 00894 for opt in to_remove: 00895 self.remove_option(flags['ld_flags'], opt) 00896 00897 # Other tool remaining options are separated by category. 00898 opts['as']['otherwarnings'] = self.find_options( 00899 flags['asm_flags'], '-W') 00900 00901 opts['c']['otherwarnings'] = self.find_options( 00902 flags['c_flags'], '-W') 00903 opts['c']['otheroptimizations'] = self.find_options(flags[ 00904 'c_flags'], '-f') 00905 00906 opts['cpp']['otherwarnings'] = self.find_options( 00907 flags['cxx_flags'], '-W') 00908 opts['cpp']['otheroptimizations'] = self.find_options( 00909 flags['cxx_flags'], '-f') 00910 00911 # Other common remaining options are separated by category. 00912 opts['common']['optimization.other'] = self.find_options( 00913 flags['common_flags'], '-f') 00914 opts['common']['warnings.other'] = self.find_options( 00915 flags['common_flags'], '-W') 00916 00917 # Remaining common flags are added to each tool. 00918 opts['as']['other'] += ' ' + \ 00919 ' '.join(flags['common_flags']) + ' ' + \ 00920 ' '.join(flags['asm_flags']) 00921 opts['c']['other'] += ' ' + \ 00922 ' '.join(flags['common_flags']) + ' ' + ' '.join(flags['c_flags']) 00923 opts['cpp']['other'] += ' ' + \ 00924 ' '.join(flags['common_flags']) + ' ' + \ 00925 ' '.join(flags['cxx_flags']) 00926 opts['ld']['other'] += ' ' + \ 00927 ' '.join(flags['common_flags']) + ' ' + ' '.join(flags['ld_flags']) 00928 00929 if len(self.system_libraries) > 0: 00930 opts['ld']['other'] += ' -Wl,--start-group ' 00931 opts['ld'][ 00932 'other'] += ' '.join('-l' + s for s in self.system_libraries) 00933 opts['ld']['other'] += ' -Wl,--end-group ' 00934 00935 # Strip all 'other' flags, since they might have leading spaces. 00936 opts['as']['other'] = opts['as']['other'].strip() 00937 opts['c']['other'] = opts['c']['other'].strip() 00938 opts['cpp']['other'] = opts['cpp']['other'].strip() 00939 opts['ld']['other'] = opts['ld']['other'].strip() 00940 00941 if False: 00942 print 00943 print opts 00944 00945 print 00946 print 'common_flags', flags['common_flags'] 00947 print 'asm_flags', flags['asm_flags'] 00948 print 'c_flags', flags['c_flags'] 00949 print 'cxx_flags', flags['cxx_flags'] 00950 print 'ld_flags', flags['ld_flags'] 00951 00952 @staticmethod 00953 def find_options(lst, option): 00954 tmp = [str for str in lst if str.startswith(option)] 00955 if len(tmp) > 0: 00956 return tmp[0] 00957 else: 00958 return None 00959 00960 @staticmethod 00961 def find_options(lst, prefix): 00962 other = '' 00963 opts = [str for str in lst if str.startswith(prefix)] 00964 if len(opts) > 0: 00965 for opt in opts: 00966 other += ' ' + opt 00967 GNUARMEclipse.remove_option(lst, opt) 00968 return other.strip() 00969 00970 @staticmethod 00971 def remove_option(lst, option): 00972 if option in lst: 00973 lst.remove(option) 00974 00975 # =============================================================================
Generated on Sun Jul 17 2022 08:25:18 by 1.7.2