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