class Target(TargetConfiguration, ArchSupport): """Handles the creation of runtimes for a particular target""" @property def rel_path(self): if self._parent is not None: return self._parent.rel_path + self.name + '/' else: return self.name + '/' def __init__(self): """Initialize the target The build_flags dictionnary is used to set attributes of runtime_build.gpr""" TargetConfiguration.__init__(self) ArchSupport.__init__(self) self.config_files = {} self.runtimes = {} self.rts_options = RTSProfiles(self) self.build_flags = { 'source_dirs': None, 'common_flags': [ '-fcallgraph-info=su,da', '-ffunction-sections', '-fdata-sections' ], 'asm_flags': [], 'c_flags': ['-DIN_RTS', '-Dinhibit_libc'] } readme = self.readme_file if readme: self.config_files.update({'README': readfile(readme)}) for profile in self.system_ads: # Set the scenario variable values for the base profile rts = FilesHolder() self.runtimes[profile] = rts if 'ravenscar' not in profile: rts.rts_vars = self.rts_options.zfp_scenarios(math_lib=False) elif 'full' in profile: rts.rts_vars = self.rts_options.full_scenarios(math_lib=True) else: rts.rts_vars = self.rts_options.sfp_scenarios(math_lib=False) # By default, system.ads files are searched for in # bb-runtimes/src/system. # This works fine in general, however, for custom runtimes, we may # need to change the location of this file for various reasons # so if we detect a slash in the base name, this means that we # lookup the file as any other regular source file. system_ads = self.system_ads[profile] if '/' in system_ads: rts.add_sources('arch', {'system.ads': system_ads}) else: rts.add_sources('arch', {'system.ads': 'src/system/%s' % system_ads}) rts.build_flags = copy.deepcopy(self.build_flags) rts.config_files = {} # Update the runtimes objects according to target specifications self.amend_rts(profile, rts) # Check that dependencies are met self.rts_options.check_deps(rts.rts_vars) assert len(self.runtimes) > 0, "No runtime defined" def amend_rts(self, rts_profile, rts): """to be overriden by the actual target to refine the runtime""" pass ############### # runtime.xml # ############### def dump_runtime_xml(self, rts_name, rts): " Dumps the runtime.xml file that gives the configuration to gprbuild" ret = '<?xml version="1.0" ?>\n\n' ret += '<gprconfig>\n' ret += ' <configuration>\n' ret += ' <config><![CDATA[\n' if self.loaders is not None: # Add USER loader so users can always specify their own linker # script. To ensure the USER loader is always used for this # purpose it cannot be defined by a target assert 'USER' not in self.loaders, \ "target cannot define USER loader" loaders = self.loaders + ("USER", ) ret += ' type Loaders is ("%s");\n' % '", "'.join(loaders) ret += ' Loader : Loaders := external("LOADER", "%s");\n\n' % ( loaders[0]) elif len(self.ld_scripts) == 1: # No loader defined, and a single ld script # Let's make it user-configurable ret += ' LDSCRIPT := external("LDSCRIPT",\n' ret += ' "${RUNTIME_DIR(ada)}/ld/%s");' % ( self.ld_scripts[0]['name'], ) ret += '\n\n' ret += ' package Compiler is\n' if len(self.compiler_switches) > 0: ret += ' Common_Required_Switches := ("%s");\n' % \ '", "'.join(self.compiler_switches) else: ret += ' Common_Required_Switches := ();\n' if len(self.c_switches) > 0: ret += ' C_Required_Switches := ("%s");\n' % \ '", "'.join(self.c_switches) ret += '\n' for lang in ('Ada', 'C', 'Asm', 'Asm2', 'Asm_Cpp'): w = ' ' ret += w + 'for Leading_Required_Switches ("%s") use\n' % lang w = ' ' ret += w + 'Compiler\'Leading_Required_Switches ("%s") &\n' % \ lang ret += w + 'Common_Required_Switches' if lang != 'Ada' and len(self.c_switches) > 0: ret += ' &\n' + w ret += 'C_Required_Switches' ret += ';\n' ret += ' end Compiler;\n\n' switches = [] if len(self.ld_scripts) == 1 and self.loaders is None: switches.append('"-T", LDSCRIPT') else: for val in self.ld_scripts: if val['loader'] is None: # use for all loaders switches.append('"-T", "%s"' % val['name']) for sw in self.ld_switches: if sw['loader'] is None or sw['loader'] == '': switches.append('"%s"' % sw['switch']) ret += ' package Linker is\n' indent = 6 blank = indent * ' ' ret += blank + \ 'for Required_Switches use Linker\'Required_Switches &\n' ret += blank + ' ("-Wl,-L${RUNTIME_DIR(ada)}/adalib",\n' indent = 9 blank = indent * ' ' ret += blank + '"-nostartfiles"' if rts.rts_vars['RTS_Profile'] != "ravenscar-full": ret += ', "-nolibc"' else: # libgnat depends on libc for malloc stuff # libc and libgcc depends on libgnat for syscalls and abort ret += (', "-lgnat", "-lc", "-lgcc", "-lgnat"') if len(self.ld_scripts) > 0: ret += ',\n' + blank + '"-L${RUNTIME_DIR(ada)}/ld"' if len(switches) > 0: ret += ',\n' + blank ret += (',\n' + blank).join(switches) blank = indent * ' ' ret += ') &\n' + blank + 'Compiler.Common_Required_Switches;\n' indent = 6 blank = indent * ' ' if self.loaders is not None: ret += '\n' + blank ret += 'case Loader is\n' indent += 3 blank = indent * ' ' for l in loaders: ret += blank ret += 'when "%s" =>\n' % l indent += 3 blank = indent * ' ' switches = [] for val in self.ld_scripts: if val['loader'] is None: continue if isinstance(val['loader'], basestring): if val['loader'] == l: switches.append('"-T", "%s"' % val['name']) else: if l in val['loader']: switches.append('"-T", "%s"' % val['name']) for sw in self.ld_switches: if isinstance(sw['loader'], basestring) \ and sw['loader'] == l: switches.append('"%s"' % sw['switch']) if isinstance(sw['loader'], list) \ and l in sw['loader']: switches.append('"%s"' % sw['switch']) if len(switches) > 0: ret += blank ret += \ 'for Required_Switches use Linker\'Required_Switches' ret += ' &\n' + blank + ' ' ret += '(%s);\n' % (',\n ' + blank).join(switches) indent -= 3 blank = indent * ' ' indent -= 3 blank = indent * ' ' ret += '%send case;\n' % blank ret += (' end Linker;\n' ']]>\n' ' </config>\n' ' </configuration>\n' '</gprconfig>\n') return ret
class Target(TargetConfiguration, ArchSupport): """Handles the creation of runtimes for a particular target""" def __init__(self): """Initialize the target The build_flags dictionnary is used to set attributes of runtime_build.gpr""" TargetConfiguration.__init__(self) ArchSupport.__init__(self) self.config_files = {} self.runtimes = {} self.rts_options = RTSProfiles(self) self.build_flags = { 'source_dirs': None, 'common_flags': [ '-fcallgraph-info=su,da', '-ffunction-sections', '-fdata-sections' ], 'asm_flags': [], 'c_flags': ['-DIN_RTS', '-Dinhibit_libc'] } readme = self.readme_file if readme: self.config_files.update({'README': readfile(readme)}) for profile in self.system_ads: # Set the scenario variable values for the base profile rts = FilesHolder() self.runtimes[profile] = rts if 'ravenscar' not in profile: rts.rts_vars = self.rts_options.zfp_scenarios(math_lib=False) elif 'full' in profile: rts.rts_vars = self.rts_options.full_scenarios(math_lib=True) else: rts.rts_vars = self.rts_options.sfp_scenarios(math_lib=False) # By default, system.ads files are searched for in # bb-runtimes/src/system. # This works fine in general, however, for custom runtimes, we may # need to change the location of this file for various reasons # so if we detect a slash in the base name, this means that we # lookup the file as any other regular source file. system_ads = self.system_ads[profile] if '/' in system_ads: rts.add_source_alias('gnat', 'system.ads', system_ads) else: rts.add_source_alias('gnat', 'system.ads', 'src/system/%s' % system_ads) rts.build_flags = copy.deepcopy(self.build_flags) rts.config_files = {} # Update the runtimes objects according to target specifications self.amend_rts(profile, rts) # Check that dependencies are met self.rts_options.check_deps(rts.rts_vars) assert len(self.runtimes) > 0, "No runtime defined" @property def compiler_switches(self): return [] def amend_rts(self, rts_profile, rts): """to be overriden by the actual target to refine the runtime""" pass def other_sources(self, profile): """Used to return a list of source dirs to install. The expected returned format is: { 'rts_subdir': [ <dir1>, <dir2> ] } the sources in <dir1>, <dir2> will then be installed in the runtime's subdirectory rts_subdir. """ return None def other_projects(self, profile): """List of projects to build in the runtime""" return None ############### # runtime.xml # ############### def dump_runtime_xml(self, rts_name, rts): """Dumps the runtime.xml file that gives the configuration to gprbuild """ ret = '<?xml version="1.0" ?>\n\n' ret += '<gprconfig>\n' ret += ' <configuration>\n' ret += ' <config><![CDATA[\n' if self.loaders is not None: # Add USER loader so users can always specify their own linker # script. To ensure the USER loader is always used for this # purpose it cannot be defined by a target assert 'USER' not in self.loaders, \ "target cannot define USER loader" loaders = list(self.loaders) + ['USER'] else: assert len(self.ld_scripts) <= 1, ( "target configuration error: no loader specified and several" " ld scripts are defined") if len(self.ld_scripts) == 1: loaders = ['DEFAULT', 'USER'] self.ld_scripts[0].add_loader('DEFAULT') else: loaders = ['USER'] ret += ' type Loaders is ("%s");\n' % '", "'.join(loaders) ret += ' Loader : Loaders := external("LOADER", "%s");\n\n' % \ loaders[0] ret += ' package Compiler is\n' if len(self.compiler_switches) > 0: ret += ' Common_Required_Switches := ("%s");\n' % \ '", "'.join(self.compiler_switches) else: ret += ' Common_Required_Switches := ();\n' if len(self.c_switches) > 0: ret += ' C_Required_Switches := ("%s");\n' % \ '", "'.join(self.c_switches) ret += '\n' for lang in ('Ada', 'C', 'Asm', 'Asm2', 'Asm_Cpp'): w = ' ' ret += w + 'for Leading_Required_Switches ("%s") use\n' % lang w = ' ' ret += w + 'Compiler\'Leading_Required_Switches ("%s") &\n' % \ lang ret += w + 'Common_Required_Switches' if lang != 'Ada' and len(self.c_switches) > 0: ret += ' &\n' + w ret += 'C_Required_Switches' ret += ';\n' ret += ' end Compiler;\n\n' switches = [] for sw in self.ld_switches: if sw['loader'] is None or sw['loader'] == '': switches.append('"%s"' % sw['switch']) ret += ' package Linker is\n' indent = 6 blank = indent * ' ' ret += blank + \ 'for Required_Switches use Linker\'Required_Switches &\n' ret += blank + ' ("-Wl,-L${RUNTIME_DIR(Ada)}/adalib",\n' indent = 9 blank = indent * ' ' ret += blank + '"-nostartfiles"' if rts.rts_vars['RTS_Profile'] != "ravenscar-full": ret += ', "-nolibc"' else: # in the ravenscar-full case, the runtime depends on # functionalities from newlib, such as memory allocation. ret += ', "-lc", "-lgnat"' # Add the user script path first, so that they have precedence ret += ',\n' + blank + '"-L${RUNTIME_DIR(ada)}/ld_user"' # And then our own script(s), if any if len(self.ld_scripts) > 0: ret += ',\n' + blank + '"-L${RUNTIME_DIR(ada)}/ld"' if len(switches) > 0: ret += ',\n' + blank ret += (',\n' + blank).join(switches) blank = indent * ' ' ret += ') &\n' + blank + 'Compiler.Common_Required_Switches;\n' indent = 6 blank = indent * ' ' if loaders is not None: ret += '\n' + blank ret += 'case Loader is\n' indent += 3 blank = indent * ' ' for loader in loaders: ret += blank ret += 'when "%s" =>\n' % loader if loader == 'USER': continue indent += 3 blank = indent * ' ' switches = [] for val in self.ld_scripts: if val.loaders is None or loader in val.loaders: switches.append('"-T", "%s"' % val.name) for sw in self.ld_switches: if is_string(sw['loader']) \ and sw['loader'] == loader: switches.append('"%s"' % sw['switch']) if isinstance(sw['loader'], list) \ and loader in sw['loader']: switches.append('"%s"' % sw['switch']) if len(switches) > 0: ret += blank ret += \ 'for Required_Switches use Linker\'Required_Switches' ret += ' &\n' + blank + ' ' ret += '(%s);\n' % (',\n ' + blank).join(switches) indent -= 3 blank = indent * ' ' indent -= 3 blank = indent * ' ' ret += '%send case;\n' % blank ret += (' end Linker;\n' ']]>\n' ' </config>\n' ' </configuration>\n' '</gprconfig>\n') return ret