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