Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers __init__.py Source File

__init__.py

00001 """
00002 mbed SDK
00003 Copyright (c) 2011-2016 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: MCUXpresso exporter.
00018 
00019 Description: Creates a managed build project that can be imported by
00020 the MCUXpresso IDE from NXP
00021 
00022 Based on GNU ARM Eclipse Exporter from Liviu Ionescu <ilg@livius.net>
00023 modified for MCUXpresso by Johannes Stratmann <jojos62@online.de>
00024 """
00025 
00026 import copy
00027 import tempfile
00028 import shutil
00029 
00030 from subprocess import Popen, PIPE
00031 from os import getcwd, remove
00032 from os.path import splitext, basename, exists
00033 from random import randint
00034 
00035 from tools.export.gnuarmeclipse import GNUARMEclipse, UID
00036 from tools.export.exporters import apply_supported_whitelist
00037 from tools.targets import TARGET_MAP
00038 from tools.utils import NotSupportedException
00039 from tools.build_api import prepare_toolchain
00040 
00041 
00042 # =============================================================================
00043 
00044 
00045 POST_BINARY_WHITELIST = set([
00046     "TEENSY3_1Code.binary_hook",
00047     "MCU_NRF51Code.binary_hook",
00048     "LPCTargetCode.lpc_patch",
00049     "LPC4088Code.binary_hook"
00050 ])
00051 
00052 class MCUXpresso(GNUARMEclipse):
00053     NAME = 'MCUXpresso'
00054     TOOLCHAIN = 'GCC_ARM'
00055 
00056     MBED_CONFIG_HEADER_SUPPORTED = True
00057 
00058     @classmethod
00059     def is_target_supported(cls, target_name):
00060         # targes suppoerted when .cproject templatefile exists
00061         if exists(cls.TEMPLATE_DIR + '/mcuxpresso/' + target_name + '_cproject.tmpl'):
00062             target = TARGET_MAP[target_name]
00063             return apply_supported_whitelist(
00064                 cls.TOOLCHAIN, POST_BINARY_WHITELIST, target)
00065         else:
00066             return False
00067 
00068     # override
00069     def generate(self):
00070         """
00071         Generate the .project and .cproject files.
00072         """
00073         if not self.resources.linker_script:
00074             raise NotSupportedException("No linker script found.")
00075 
00076         print
00077         print 'Create a GNU ARM Eclipse C++ managed project'
00078         print 'Project name: {0}'.format(self.project_name)
00079         print 'Target: {0}'.format(self.toolchain.target.name)
00080         print 'Toolchain: {0}'.format(self.TOOLCHAIN)
00081 
00082         self.resources.win_to_unix()
00083 
00084         # TODO: use some logger to display additional info if verbose
00085 
00086         self.libraries = []
00087         # print 'libraries'
00088         # print self.resources.libraries
00089         for lib in self.resources.libraries:
00090             l, _ = splitext(basename(lib))
00091             self.libraries.append(l[3:])
00092 
00093         self.system_libraries = [
00094             'stdc++', 'supc++', 'm', 'c', 'gcc', 'nosys'
00095         ]
00096 
00097         # Read in all profiles, we'll extract compiler options.
00098         profiles = self.get_all_profiles()
00099 
00100         profile_ids = [s.lower() for s in profiles]
00101         profile_ids.sort()
00102 
00103         # TODO: get the list from existing .cproject
00104         build_folders = [s.capitalize() for s in profile_ids]
00105         build_folders.append('BUILD')
00106         # print build_folders
00107 
00108         objects = [self.filter_dot(s) for s in self.resources.objects]
00109         for bf in build_folders:
00110             objects = [o for o in objects if not o.startswith(bf + '/')]
00111         # print 'objects'
00112         # print objects
00113 
00114         self.compute_exclusions()
00115 
00116         self.include_path = [
00117             self.filter_dot(s) for s in self.resources.inc_dirs]
00118         print 'Include folders: {0}'.format(len(self.include_path))
00119 
00120         self.as_defines = self.toolchain.get_symbols(True)
00121         self.c_defines = self.toolchain.get_symbols()
00122         self.cpp_defines = self.c_defines
00123         print 'Symbols: {0}'.format(len(self.c_defines))
00124 
00125         self.ld_script = self.filter_dot(
00126             self.resources.linker_script)
00127         print 'Linker script: {0}'.format(self.ld_script)
00128 
00129         self.options = {}
00130         profile_ids.remove('develop')
00131         for id in profile_ids:
00132 
00133             # There are 4 categories of options, a category common too
00134             # all tools and a specific category for each of the tools.
00135             opts = {}
00136             opts['common'] = {}
00137             opts['as'] = {}
00138             opts['c'] = {}
00139             opts['cpp'] = {}
00140             opts['ld'] = {}
00141 
00142             opts['id'] = id
00143             opts['name'] = opts['id'].capitalize()
00144 
00145             print
00146             print 'Build configuration: {0}'.format(opts['name'])
00147 
00148             profile = profiles[id]
00149 
00150             # A small hack, do not bother with src_path again,
00151             # pass an empty string to avoid crashing.
00152             src_paths = ['']
00153             target_name = self.toolchain.target.name
00154             toolchain = prepare_toolchain(
00155                 src_paths, "", target_name, self.TOOLCHAIN, build_profile=[profile])
00156 
00157             # Hack to fill in build_dir
00158             toolchain.build_dir = self.toolchain.build_dir
00159 
00160             flags = self.toolchain_flags(toolchain)
00161 
00162             print 'Common flags:', ' '.join(flags['common_flags'])
00163             print 'C++ flags:', ' '.join(flags['cxx_flags'])
00164             print 'C flags:', ' '.join(flags['c_flags'])
00165             print 'ASM flags:', ' '.join(flags['asm_flags'])
00166             print 'Linker flags:', ' '.join(flags['ld_flags'])
00167 
00168             # Most GNU ARM Eclipse options have a parent,
00169             # either debug or release.
00170             if '-O0' in flags['common_flags'] or '-Og' in flags['common_flags']:
00171                 opts['parent_id'] = 'debug'
00172             else:
00173                 opts['parent_id'] = 'release'
00174 
00175             self.process_options(opts, flags)
00176 
00177             opts['as']['defines'] = self.as_defines
00178             opts['c']['defines'] = self.c_defines
00179             opts['cpp']['defines'] = self.cpp_defines
00180 
00181             opts['common']['include_paths'] = self.include_path
00182             opts['common']['excluded_folders'] = '|'.join(
00183                 self.excluded_folders)
00184             self.excluded_folders = [item.replace("\\", "/") for item in self.excluded_folders]
00185 
00186             opts['ld']['library_paths'] = [
00187                 self.filter_dot(s) for s in self.resources.lib_dirs]
00188 
00189             opts['ld']['object_files'] = objects
00190             opts['ld']['user_libraries'] = self.libraries
00191             opts['ld']['system_libraries'] = self.system_libraries
00192             opts['ld']['script'] = "linker-script-%s.ld" % id
00193             opts['cpp_cmd'] = " ".join(toolchain.preproc)
00194 
00195             # Unique IDs used in multiple places.
00196             # Those used only once are implemented with {{u.id}}.
00197             u = UID()
00198             uid = {}
00199             uid['config'] = u.id
00200             uid['tool_c_compiler'] = u.id
00201             uid['tool_c_compiler_input'] = u.id
00202             uid['tool_cpp_compiler'] = u.id
00203             uid['tool_cpp_compiler_input'] = u.id
00204 
00205             opts['uid'] = uid
00206 
00207             self.options[id] = opts
00208 
00209         jinja_ctx = {
00210             'name': self.project_name,
00211             'ld_script': self.ld_script,
00212 
00213             # Compiler & linker command line options
00214             'options': self.options,
00215 
00216             # Must be an object with an `id` property, which
00217             # will be called repeatedly, to generate multiple UIDs.
00218             'u': u,
00219         }
00220 
00221         self.gen_file('mcuxpresso/.project.tmpl', jinja_ctx,
00222                       '.project', trim_blocks=True, lstrip_blocks=True)
00223         self.gen_file('mcuxpresso/{0}_cproject.tmpl'.format(target_name), jinja_ctx,
00224                       '.cproject', trim_blocks=True, lstrip_blocks=True)
00225         self.gen_file('mcuxpresso/makefile.targets.tmpl', jinja_ctx,
00226                       'makefile.targets', trim_blocks=True, lstrip_blocks=True)
00227         self.gen_file('mcuxpresso/mbedignore.tmpl', jinja_ctx, '.mbedignore')
00228 
00229         print
00230         print 'Done. Import the \'{0}\' project in Eclipse.'.format(self.project_name)
00231 
00232     # override
00233     @staticmethod
00234     def build(project_name, log_name="build_log.txt", cleanup=True):
00235         """
00236         Headless build an Eclipse project.
00237 
00238         The following steps are performed:
00239         - a temporary workspace is created,
00240         - the project is imported,
00241         - a clean build of all configurations is performed and
00242         - the temporary workspace is removed.
00243 
00244         The build results are in the Debug & Release folders.
00245 
00246         All executables (eclipse & toolchain) must be in the PATH.
00247 
00248         The general method to start a headless Eclipse build is:
00249 
00250         $ eclipse \
00251         --launcher.suppressErrors \
00252         -nosplash \
00253         -application org.eclipse.cdt.managedbuilder.core.headlessbuild \
00254         -data /path/to/workspace \
00255         -import /path/to/project \
00256         -cleanBuild "project[/configuration] | all"
00257         """
00258 
00259         # TODO: possibly use the log file.
00260 
00261         # Create a temporary folder for the workspace.
00262         tmp_folder = tempfile.mkdtemp()
00263 
00264         cmd = [
00265             'mcuxpressoide',
00266             '--launcher.suppressErrors',
00267             '-nosplash',
00268             '-application org.eclipse.cdt.managedbuilder.core.headlessbuild',
00269             '-data', tmp_folder,
00270             '-import', getcwd(),
00271             '-cleanBuild', project_name
00272         ]
00273 
00274         p = Popen(' '.join(cmd), shell=True, stdout=PIPE, stderr=PIPE)
00275         out, err = p.communicate()
00276         ret_code = p.returncode
00277         stdout_string = "=" * 10 + "STDOUT" + "=" * 10 + "\n"
00278         err_string = "=" * 10 + "STDERR" + "=" * 10 + "\n"
00279         err_string += err
00280         success = any(l.startswith("Finished building target:") for l in out.split("\n"))
00281 
00282         if success:
00283             ret_string = "SUCCESS\n"
00284         else:
00285             ret_string = "FAILURE: build returned %s \n" % ret_code
00286 
00287         print "%s\n%s\n%s\n%s" % (stdout_string, out, err_string, ret_string)
00288 
00289         if log_name:
00290             # Write the output to the log file
00291             with open(log_name, 'w+') as f:
00292                 f.write(stdout_string)
00293                 f.write(out)
00294                 f.write(err_string)
00295                 f.write(ret_string)
00296 
00297         # Cleanup the exported and built files
00298         if cleanup:
00299             if exists(log_name):
00300                 remove(log_name)
00301             remove('.project')
00302             remove('.cproject')
00303             if exists('Debug'):
00304                 shutil.rmtree('Debug')
00305             if exists('Release'):
00306                 shutil.rmtree('Release')
00307             if exists('makefile.targets'):
00308                 remove('makefile.targets')
00309 
00310         # Always remove the temporary folder.
00311         if exists(tmp_folder):
00312             shutil.rmtree(tmp_folder)
00313 
00314         return not(success)
00315 
00316 
00317     # -------------------------------------------------------------------------
00318 
00319     def process_options(self, opts, flags_in):
00320         """
00321         CDT managed projects store lots of build options in separate
00322         variables, with separate IDs in the .cproject file.
00323         When the CDT build is started, all these options are brought
00324         together to compose the compiler and linker command lines.
00325 
00326         Here the process is reversed, from the compiler and linker
00327         command lines, the options are identified and various flags are
00328         set to control the template generation process.
00329 
00330         Once identified, the options are removed from the command lines.
00331 
00332         The options that were not identified are options that do not
00333         have CDT equivalents and will be passed in the 'Other options'
00334         categories.
00335 
00336         Although this process does not have a very complicated logic,
00337         given the large number of explicit configuration options
00338         used by the GNU ARM Eclipse managed build plug-in, it is tedious...
00339         """
00340 
00341         # Make a copy of the flags, to be one by one removed after processing.
00342         flags = copy.deepcopy(flags_in)
00343 
00344         if False:
00345             print
00346             print 'common_flags', flags['common_flags']
00347             print 'asm_flags', flags['asm_flags']
00348             print 'c_flags', flags['c_flags']
00349             print 'cxx_flags', flags['cxx_flags']
00350             print 'ld_flags', flags['ld_flags']
00351 
00352         # Initialise the 'last resort' options where all unrecognised
00353         # options will be collected.
00354         opts['as']['other'] = ''
00355         opts['c']['other'] = ''
00356         opts['cpp']['other'] = ''
00357         opts['ld']['other'] = ''
00358 
00359         MCPUS = {
00360             'Cortex-M0': {'mcpu': 'cortex-m0', 'fpu_unit': None},
00361             'Cortex-M0+': {'mcpu': 'cortex-m0plus', 'fpu_unit': None},
00362             'Cortex-M1': {'mcpu': 'cortex-m1', 'fpu_unit': None},
00363             'Cortex-M3': {'mcpu': 'cortex-m3', 'fpu_unit': None},
00364             'Cortex-M4': {'mcpu': 'cortex-m4', 'fpu_unit': None},
00365             'Cortex-M4F': {'mcpu': 'cortex-m4', 'fpu_unit': 'fpv4spd16'},
00366             'Cortex-M7': {'mcpu': 'cortex-m7', 'fpu_unit': None},
00367             'Cortex-M7F': {'mcpu': 'cortex-m7', 'fpu_unit': 'fpv4spd16'},
00368             'Cortex-M7FD': {'mcpu': 'cortex-m7', 'fpu_unit': 'fpv5d16'},
00369             'Cortex-A9': {'mcpu': 'cortex-a9', 'fpu_unit': 'vfpv3'}
00370         }
00371 
00372         MCPU_NXP = {
00373             'cortex-m7' : 'cm7',
00374             'cortex-m4' : 'cm4',
00375             'cortex-m3' : 'cm3',
00376             'cortex-m1' : 'cm1',
00377             'cortex-m0' : 'cm0',
00378             'cortex-m0.small-multiply' : 'cm0.smallmul',
00379             'cortex-m0plus' : 'cm0plus',
00380             'cortex-m0plus.small-multiply' : 'cm0plus.smallmul'
00381         }
00382 
00383         # Remove options that are supplied by CDT
00384         self.remove_option(flags['common_flags'], '-c')
00385         self.remove_option(flags['common_flags'], '-MMD')
00386 
00387         # As 'plan B', get the CPU from the target definition.
00388         core = self.toolchain.target.core
00389 
00390         opts['common']['arm.target.family'] = None
00391 
00392         # cortex-m0, cortex-m0-small-multiply, cortex-m0plus,
00393         # cortex-m0plus-small-multiply, cortex-m1, cortex-m1-small-multiply,
00394         # cortex-m3, cortex-m4, cortex-m7.
00395         str = self.find_options(flags['common_flags'], '-mcpu=')
00396         if str != None:
00397             opts['common']['arm.target.family'] = str[len('-mcpu='):]
00398             opts['common']['arm.target.family_nxp'] = MCPU_NXP[str[len('-mcpu='):]]
00399             self.remove_option(flags['common_flags'], str)
00400             self.remove_option(flags['ld_flags'], str)
00401         else:
00402             if core not in MCPUS:
00403                 raise NotSupportedException(
00404                     'Target core {0} not supported.'.format(core))
00405             opts['common']['arm.target.family'] = MCPUS[core]['mcpu']
00406 
00407         opts['common']['arm.target.arch'] = 'none'
00408         str = self.find_options(flags['common_flags'], '-march=')
00409         arch = str[len('-march='):]
00410         archs = {'armv6-m': 'armv6-m', 'armv7-m': 'armv7-m', 'armv7-a': 'armv7-a'}
00411         if arch in archs:
00412             opts['common']['arm.target.arch'] = archs[arch]
00413             self.remove_option(flags['common_flags'], str)
00414 
00415         opts['common']['arm.target.instructionset'] = 'thumb'
00416         if '-mthumb' in flags['common_flags']:
00417             self.remove_option(flags['common_flags'], '-mthumb')
00418             self.remove_option(flags['ld_flags'], '-mthumb')
00419         elif '-marm' in flags['common_flags']:
00420             opts['common']['arm.target.instructionset'] = 'arm'
00421             self.remove_option(flags['common_flags'], '-marm')
00422             self.remove_option(flags['ld_flags'], '-marm')
00423 
00424         opts['common']['arm.target.thumbinterwork'] = False
00425         if '-mthumb-interwork' in flags['common_flags']:
00426             opts['common']['arm.target.thumbinterwork'] = True
00427             self.remove_option(flags['common_flags'], '-mthumb-interwork')
00428 
00429         opts['common']['arm.target.endianness'] = None
00430         if '-mlittle-endian' in flags['common_flags']:
00431             opts['common']['arm.target.endianness'] = 'little'
00432             self.remove_option(flags['common_flags'], '-mlittle-endian')
00433         elif '-mbig-endian' in flags['common_flags']:
00434             opts['common']['arm.target.endianness'] = 'big'
00435             self.remove_option(flags['common_flags'], '-mbig-endian')
00436 
00437         opts['common']['arm.target.fpu.unit'] = None
00438         opts['common']['arm.target.fpu.unit_nxp'] = None
00439         # default, fpv4spd16, fpv5d16, fpv5spd16
00440         str = self.find_options(flags['common_flags'], '-mfpu=')
00441         if str != None:
00442             fpu = str[len('-mfpu='):]
00443             fpus = {
00444                 'fpv4-sp-d16': 'fpv4spd16',
00445                 'fpv5-d16': 'fpv5d16',
00446                 'fpv5-sp-d16': 'fpv5spd16'
00447             }
00448             fpus_nxp = {
00449                 'fpv4-sp-d16': 'fpv4',
00450                 'fpv5-d16': 'fpv5dp',
00451                 'fpv5-sp-d16': 'fpv5sp'
00452             }
00453             if fpu in fpus:
00454                 opts['common']['arm.target.fpu.unit'] = fpus[fpu]
00455                 opts['common']['arm.target.fpu.unit_nxp'] = fpus_nxp[fpu]
00456 
00457                 self.remove_option(flags['common_flags'], str)
00458                 self.remove_option(flags['ld_flags'], str)
00459         if opts['common']['arm.target.fpu.unit'] == None:
00460             if core not in MCPUS:
00461                 raise NotSupportedException(
00462                     'Target core {0} not supported.'.format(core))
00463             if MCPUS[core]['fpu_unit']:
00464                 opts['common'][
00465                     'arm.target.fpu.unit'] = MCPUS[core]['fpu_unit']
00466 
00467         # soft, softfp, hard.
00468         str = self.find_options(flags['common_flags'], '-mfloat-abi=')
00469         if str != None:
00470             opts['common']['arm.target.fpu.abi'] = str[
00471                 len('-mfloat-abi='):]
00472             self.remove_option(flags['common_flags'], str)
00473             self.remove_option(flags['ld_flags'], str)
00474             if opts['common']['arm.target.fpu.abi'] == 'hard':
00475                 opts['common']['arm.target.fpu.unit_nxp'] += '.hard'
00476 
00477         # Default optimisation level for Release.
00478         opts['common']['optimization.level'] = '-Os'
00479 
00480         # If the project defines an optimisation level, it is used
00481         # only for the Release configuration, the Debug one used '-Og'.
00482         str = self.find_options(flags['common_flags'], '-O')
00483         if str != None:
00484             levels = {
00485                 '-O0': 'none', '-O1': 'optimize', '-O2': 'more',
00486                 '-O3': 'most', '-Os': 'size', '-Og': 'debug'
00487             }
00488             if str in levels:
00489                 opts['common']['optimization.level'] = levels[str]
00490                 self.remove_option(flags['common_flags'], str)
00491 
00492         include_files = []
00493         for all_flags in [flags['common_flags'], flags['c_flags'], flags['cxx_flags']]:
00494             while '-include' in all_flags:
00495                 ix = all_flags.index('-include')
00496                 str = all_flags[ix + 1]
00497                 if str not in include_files:
00498                     include_files.append(str)
00499                 self.remove_option(all_flags, '-include')
00500                 self.remove_option(all_flags, str)
00501 
00502         opts['common']['include_files'] = include_files
00503 
00504         if '-ansi' in flags['c_flags']:
00505             opts['c']['compiler.std'] = '-ansi'
00506             self.remove_option(flags['c_flags'], str)
00507         else:
00508             str = self.find_options(flags['c_flags'], '-std')
00509             std = str[len('-std='):]
00510             c_std = {
00511                 'c90': 'c90', 'c89': 'c90', 'gnu90': 'gnu90', 'gnu89': 'gnu90',
00512                 'c99': 'c99', 'c9x': 'c99', 'gnu99': 'gnu99', 'gnu9x': 'gnu98',
00513                 'c11': 'c11', 'c1x': 'c11', 'gnu11': 'gnu11', 'gnu1x': 'gnu11'
00514             }
00515             if std in c_std:
00516                 opts['c']['compiler.std'] = c_std[std]
00517                 self.remove_option(flags['c_flags'], str)
00518 
00519         if '-ansi' in flags['cxx_flags']:
00520             opts['cpp']['compiler.std'] = '-ansi'
00521             self.remove_option(flags['cxx_flags'], str)
00522         else:
00523             str = self.find_options(flags['cxx_flags'], '-std')
00524             std = str[len('-std='):]
00525             cpp_std = {
00526                 'c++98': 'cpp98', 'c++03': 'cpp03',
00527                 'gnu++98': 'gnupp98', 'gnu++03': 'gnupp03',
00528                 'c++0x': 'cpp03', 'gnu++0x': 'gnupp03',
00529                 'c++11': 'cpp11', 'gnu++11': 'gnupp11',
00530                 'c++1y': 'cpp11', 'gnu++1y': 'gnupp11',
00531                 'c++14': 'cpp14', 'gnu++14': 'gnupp14',
00532                 'c++1z': 'cpp1z', 'gnu++1z': 'gnupp1z',
00533             }
00534             if std in cpp_std:
00535                 opts['cpp']['compiler.std'] = cpp_std[std]
00536                 self.remove_option(flags['cxx_flags'], str)
00537 
00538         # Common optimisation options.
00539         optimization_options = {
00540             '-flto': 'optimization.lto',
00541             '--ffat-lto-objects': 'optimization.lto_objects'
00542         }
00543         for option in optimization_options:
00544             opts['common'][optimization_options[option]] = False
00545             if option in flags['common_flags']:
00546                 opts['common'][optimization_options[option]] = True
00547                 self.remove_option(flags['common_flags'], option)
00548 
00549         # Common warning options.
00550         warning_options = {
00551             '-fsyntax-only': 'warnings.syntaxonly',
00552             '-pedantic': 'warnings.pedantic',
00553             '-pedantic-errors': 'warnings.pedanticerrors',
00554             '-w': 'warnings.nowarn',
00555             '-Wall': 'warnings.allwarn',
00556             '-Wextra': 'warnings.extrawarn',
00557             '-Wconversion': 'warnings.conversion',
00558             '-Werror': 'warnings.toerrors',
00559         }
00560 
00561         for option in warning_options:
00562             opts['common'][warning_options[option]] = False
00563             if option in flags['common_flags']:
00564                 opts['common'][warning_options[option]] = True
00565                 self.remove_option(flags['common_flags'], option)
00566 
00567         # Common debug options.
00568         debug_levels = {
00569             '-g': 'default',
00570             '-g1': 'minimal',
00571             '-g3': 'max',
00572         }
00573         opts['common']['debugging.level'] = 'none'
00574         for option in debug_levels:
00575             if option in flags['common_flags']:
00576                 opts['common'][
00577                     'debugging.level'] = debug_levels[option]
00578                 self.remove_option(flags['common_flags'], option)
00579 
00580 
00581         opts['common']['debugging.prof'] = False
00582         if '-p' in flags['common_flags']:
00583             opts['common']['debugging.prof'] = True
00584             self.remove_option(flags['common_flags'], '-p')
00585 
00586         opts['common']['debugging.gprof'] = False
00587         if '-pg' in flags['common_flags']:
00588             opts['common']['debugging.gprof'] = True
00589             self.remove_option(flags['common_flags'], '-gp')
00590 
00591         # Assembler options.
00592         opts['as']['usepreprocessor'] = False
00593         while '-x' in flags['asm_flags']:
00594             ix = flags['asm_flags'].index('-x')
00595             str = flags['asm_flags'][ix + 1]
00596 
00597             if str == 'assembler-with-cpp':
00598                 opts['as']['usepreprocessor'] = True
00599             else:
00600                 # Collect all other assembler options.
00601                 opts['as']['other'] += ' -x ' + str
00602 
00603             self.remove_option(flags['asm_flags'], '-x')
00604             self.remove_option(flags['asm_flags'], 'assembler-with-cpp')
00605 
00606         opts['as']['nostdinc'] = False
00607         if '-nostdinc' in flags['asm_flags']:
00608             opts['as']['nostdinc'] = True
00609             self.remove_option(flags['asm_flags'], '-nostdinc')
00610 
00611         opts['as']['verbose'] = False
00612         if '-v' in flags['asm_flags']:
00613             opts['as']['verbose'] = True
00614             self.remove_option(flags['asm_flags'], '-v')
00615 
00616         # C options.
00617         opts['c']['nostdinc'] = False
00618         if '-nostdinc' in flags['c_flags']:
00619             opts['c']['nostdinc'] = True
00620             self.remove_option(flags['c_flags'], '-nostdinc')
00621 
00622         opts['c']['verbose'] = False
00623         if '-v' in flags['c_flags']:
00624             opts['c']['verbose'] = True
00625             self.remove_option(flags['c_flags'], '-v')
00626 
00627 
00628         # C++ options.
00629         opts['cpp']['nostdinc'] = False
00630         if '-nostdinc' in flags['cxx_flags']:
00631             opts['cpp']['nostdinc'] = True
00632             self.remove_option(flags['cxx_flags'], '-nostdinc')
00633 
00634         opts['cpp']['nostdincpp'] = False
00635         if '-nostdinc++' in flags['cxx_flags']:
00636             opts['cpp']['nostdincpp'] = True
00637             self.remove_option(flags['cxx_flags'], '-nostdinc++')
00638 
00639         optimization_options = {
00640             '-fno-exceptions': 'optimization.noexceptions',
00641             '-fno-rtti': 'optimization.nortti',
00642             '-fno-use-cxa-atexit': 'optimization.nousecxaatexit',
00643             '-fno-threadsafe-statics': 'optimization.nothreadsafestatics',
00644         }
00645 
00646         for option in optimization_options:
00647             opts['cpp'][optimization_options[option]] = False
00648             if option in flags['cxx_flags']:
00649                 opts['cpp'][optimization_options[option]] = True
00650             if option in flags['common_flags']:
00651                 opts['cpp'][optimization_options[option]] = True
00652 
00653         opts['cpp']['verbose'] = False
00654         if '-v' in flags['cxx_flags']:
00655             opts['cpp']['verbose'] = True
00656             self.remove_option(flags['cxx_flags'], '-v')
00657 
00658         # Linker options.
00659         linker_options = {
00660             '-nostartfiles': 'nostart',
00661             '-nodefaultlibs': 'nodeflibs',
00662             '-nostdlib': 'nostdlibs',
00663         }
00664 
00665         for option in linker_options:
00666             opts['ld'][linker_options[option]] = False
00667             if option in flags['ld_flags']:
00668                 opts['ld'][linker_options[option]] = True
00669                 self.remove_option(flags['ld_flags'], option)
00670 
00671         opts['ld']['gcsections'] = False
00672         if '-Wl,--gc-sections' in flags['ld_flags']:
00673             opts['ld']['gcsections'] = True
00674             self.remove_option(flags['ld_flags'], '-Wl,--gc-sections')
00675 
00676         opts['ld']['flags'] = []
00677         to_remove = []
00678         for opt in flags['ld_flags']:
00679             if opt.startswith('-Wl,--wrap,'):
00680                 opts['ld']['flags'].append(
00681                     '--wrap=' + opt[len('-Wl,--wrap,'):])
00682                 to_remove.append(opt)
00683         for opt in to_remove:
00684             self.remove_option(flags['ld_flags'], opt)
00685 
00686         # Other tool remaining options are separated by category.
00687         opts['as']['otherwarnings'] = self.find_options(
00688             flags['asm_flags'], '-W')
00689 
00690         opts['c']['otherwarnings'] = self.find_options(
00691             flags['c_flags'], '-W')
00692         opts['c']['otheroptimizations'] = self.find_options(flags[
00693             'c_flags'], '-f')
00694 
00695         opts['cpp']['otherwarnings'] = self.find_options(
00696             flags['cxx_flags'], '-W')
00697         opts['cpp']['otheroptimizations'] = self.find_options(
00698             flags['cxx_flags'], '-f')
00699 
00700         # Other common remaining options are separated by category.
00701         opts['common']['optimization.other'] = self.find_options(
00702             flags['common_flags'], '-f')
00703         opts['common']['warnings.other'] = self.find_options(
00704             flags['common_flags'], '-W')
00705 
00706         # Remaining common flags are added to each tool.
00707         opts['as']['other'] += ' ' + \
00708             ' '.join(flags['common_flags']) + ' ' + \
00709             ' '.join(flags['asm_flags'])
00710         opts['c']['other'] += ' ' + \
00711             ' '.join(flags['common_flags']) + ' ' + ' '.join(flags['c_flags'])
00712         opts['cpp']['other'] += ' ' + \
00713             ' '.join(flags['common_flags']) + ' ' + \
00714             ' '.join(flags['cxx_flags'])
00715         opts['ld']['other'] += ' ' + \
00716             ' '.join(flags['common_flags']) + ' ' + ' '.join(flags['ld_flags'])
00717 
00718         if len(self.system_libraries) > 0:
00719             opts['ld']['other'] += ' -Wl,--start-group '
00720             opts['ld'][
00721                 'other'] += ' '.join('-l' + s for s in self.system_libraries) + ' '
00722             opts['ld'][
00723                 'other'] += ' '.join('-l' + s for s in self.libraries)
00724             opts['ld']['other'] += ' -Wl,--end-group '
00725 
00726         # Strip all 'other' flags, since they might have leading spaces.
00727         opts['as']['other'] = opts['as']['other'].strip()
00728         opts['c']['other'] = opts['c']['other'].strip()
00729         opts['cpp']['other'] = opts['cpp']['other'].strip()
00730         opts['ld']['other'] = opts['ld']['other'].strip()
00731 
00732         if False:
00733             print
00734             print opts
00735 
00736             print
00737             print 'common_flags', flags['common_flags']
00738             print 'asm_flags', flags['asm_flags']
00739             print 'c_flags', flags['c_flags']
00740             print 'cxx_flags', flags['cxx_flags']
00741             print 'ld_flags', flags['ld_flags']
00742