SConscript revision 12797:fc61ae2a54bd
14519Sgblack@eecs.umich.edu# -*- mode:python -*- 24519Sgblack@eecs.umich.edu 34519Sgblack@eecs.umich.edu# Copyright (c) 2004-2005 The Regents of The University of Michigan 44519Sgblack@eecs.umich.edu# All rights reserved. 54519Sgblack@eecs.umich.edu# 64519Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 74519Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are 84519Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright 94519Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 104519Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 114519Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 124519Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution; 134519Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its 144519Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from 154519Sgblack@eecs.umich.edu# this software without specific prior written permission. 164519Sgblack@eecs.umich.edu# 174519Sgblack@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 184519Sgblack@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 194519Sgblack@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 204519Sgblack@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 214519Sgblack@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 224519Sgblack@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 234519Sgblack@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 244519Sgblack@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 254519Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 264519Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 274519Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 284519Sgblack@eecs.umich.edu# 294519Sgblack@eecs.umich.edu# Authors: Nathan Binkert 304519Sgblack@eecs.umich.edu 314519Sgblack@eecs.umich.edufrom __future__ import print_function 324519Sgblack@eecs.umich.edu 334519Sgblack@eecs.umich.eduimport array 344519Sgblack@eecs.umich.eduimport bisect 354519Sgblack@eecs.umich.eduimport functools 364519Sgblack@eecs.umich.eduimport imp 374519Sgblack@eecs.umich.eduimport marshal 384519Sgblack@eecs.umich.eduimport os 394519Sgblack@eecs.umich.eduimport re 404519Sgblack@eecs.umich.eduimport subprocess 414519Sgblack@eecs.umich.eduimport sys 424519Sgblack@eecs.umich.eduimport zlib 434519Sgblack@eecs.umich.edu 444519Sgblack@eecs.umich.edufrom os.path import basename, dirname, exists, isdir, isfile, join as joinpath 454519Sgblack@eecs.umich.edu 464519Sgblack@eecs.umich.eduimport SCons 474519Sgblack@eecs.umich.edu 484519Sgblack@eecs.umich.edufrom gem5_scons import Transform 494519Sgblack@eecs.umich.edu 504519Sgblack@eecs.umich.edu# This file defines how to build a particular configuration of gem5 514519Sgblack@eecs.umich.edu# based on variable settings in the 'env' build environment. 524519Sgblack@eecs.umich.edu 534519Sgblack@eecs.umich.eduImport('*') 544519Sgblack@eecs.umich.edu 554519Sgblack@eecs.umich.edu# Children need to see the environment 564519Sgblack@eecs.umich.eduExport('env') 574519Sgblack@eecs.umich.edu 584519Sgblack@eecs.umich.edubuild_env = [(opt, env[opt]) for opt in export_vars] 594519Sgblack@eecs.umich.edu 604519Sgblack@eecs.umich.edufrom m5.util import code_formatter, compareVersions 614519Sgblack@eecs.umich.edu 624519Sgblack@eecs.umich.edu######################################################################## 634519Sgblack@eecs.umich.edu# Code for adding source files of various types 644519Sgblack@eecs.umich.edu# 654519Sgblack@eecs.umich.edu# When specifying a source file of some type, a set of tags can be 664519Sgblack@eecs.umich.edu# specified for that file. 674519Sgblack@eecs.umich.edu 684809Sgblack@eecs.umich.educlass SourceFilter(object): 694519Sgblack@eecs.umich.edu def __init__(self, predicate): 704519Sgblack@eecs.umich.edu self.predicate = predicate 714688Sgblack@eecs.umich.edu 724688Sgblack@eecs.umich.edu def __or__(self, other): 734688Sgblack@eecs.umich.edu return SourceFilter(lambda tags: self.predicate(tags) or 744688Sgblack@eecs.umich.edu other.predicate(tags)) 754688Sgblack@eecs.umich.edu 764688Sgblack@eecs.umich.edu def __and__(self, other): 774708Sgblack@eecs.umich.edu return SourceFilter(lambda tags: self.predicate(tags) and 784708Sgblack@eecs.umich.edu other.predicate(tags)) 794708Sgblack@eecs.umich.edu 804708Sgblack@eecs.umich.edudef with_tags_that(predicate): 814519Sgblack@eecs.umich.edu '''Return a list of sources with tags that satisfy a predicate.''' 824519Sgblack@eecs.umich.edu return SourceFilter(predicate) 834519Sgblack@eecs.umich.edu 844519Sgblack@eecs.umich.edudef with_any_tags(*tags): 854519Sgblack@eecs.umich.edu '''Return a list of sources with any of the supplied tags.''' 864519Sgblack@eecs.umich.edu return SourceFilter(lambda stags: len(set(tags) & stags) > 0) 874519Sgblack@eecs.umich.edu 884519Sgblack@eecs.umich.edudef with_all_tags(*tags): 894519Sgblack@eecs.umich.edu '''Return a list of sources with all of the supplied tags.''' 904519Sgblack@eecs.umich.edu return SourceFilter(lambda stags: set(tags) <= stags) 914519Sgblack@eecs.umich.edu 924951Sgblack@eecs.umich.edudef with_tag(tag): 934519Sgblack@eecs.umich.edu '''Return a list of sources with the supplied tag.''' 944519Sgblack@eecs.umich.edu return SourceFilter(lambda stags: tag in stags) 954519Sgblack@eecs.umich.edu 964519Sgblack@eecs.umich.edudef without_tags(*tags): 974519Sgblack@eecs.umich.edu '''Return a list of sources without any of the supplied tags.''' 984519Sgblack@eecs.umich.edu return SourceFilter(lambda stags: len(set(tags) & stags) == 0) 994688Sgblack@eecs.umich.edu 1004688Sgblack@eecs.umich.edudef without_tag(tag): 1014688Sgblack@eecs.umich.edu '''Return a list of sources with the supplied tag.''' 1024688Sgblack@eecs.umich.edu return SourceFilter(lambda stags: tag not in stags) 1034688Sgblack@eecs.umich.edu 1044688Sgblack@eecs.umich.edusource_filter_factories = { 1054708Sgblack@eecs.umich.edu 'with_tags_that': with_tags_that, 1064708Sgblack@eecs.umich.edu 'with_any_tags': with_any_tags, 1074708Sgblack@eecs.umich.edu 'with_all_tags': with_all_tags, 1084708Sgblack@eecs.umich.edu 'with_tag': with_tag, 1094519Sgblack@eecs.umich.edu 'without_tags': without_tags, 1104519Sgblack@eecs.umich.edu 'without_tag': without_tag, 1114519Sgblack@eecs.umich.edu} 1124519Sgblack@eecs.umich.edu 1134519Sgblack@eecs.umich.eduExport(source_filter_factories) 1144519Sgblack@eecs.umich.edu 1154519Sgblack@eecs.umich.educlass SourceList(list): 1164519Sgblack@eecs.umich.edu def apply_filter(self, f): 1174519Sgblack@eecs.umich.edu def match(source): 1184519Sgblack@eecs.umich.edu return f.predicate(source.tags) 1194519Sgblack@eecs.umich.edu return SourceList(filter(match, self)) 1204519Sgblack@eecs.umich.edu 1214519Sgblack@eecs.umich.edu def __getattr__(self, name): 1224519Sgblack@eecs.umich.edu func = source_filter_factories.get(name, None) 1234519Sgblack@eecs.umich.edu if not func: 1244519Sgblack@eecs.umich.edu raise AttributeError 1254519Sgblack@eecs.umich.edu 1264519Sgblack@eecs.umich.edu @functools.wraps(func) 1274519Sgblack@eecs.umich.edu def wrapper(*args, **kwargs): 1284519Sgblack@eecs.umich.edu return self.apply_filter(func(*args, **kwargs)) 1294519Sgblack@eecs.umich.edu return wrapper 1304712Sgblack@eecs.umich.edu 1314519Sgblack@eecs.umich.educlass SourceMeta(type): 1324519Sgblack@eecs.umich.edu '''Meta class for source files that keeps track of all files of a 1334519Sgblack@eecs.umich.edu particular type.''' 1344519Sgblack@eecs.umich.edu def __init__(cls, name, bases, dict): 1354712Sgblack@eecs.umich.edu super(SourceMeta, cls).__init__(name, bases, dict) 1364519Sgblack@eecs.umich.edu cls.all = SourceList() 1374519Sgblack@eecs.umich.edu 1384519Sgblack@eecs.umich.educlass SourceFile(object): 1394519Sgblack@eecs.umich.edu '''Base object that encapsulates the notion of a source file. 1404519Sgblack@eecs.umich.edu This includes, the source node, target node, various manipulations 1414519Sgblack@eecs.umich.edu of those. A source file also specifies a set of tags which 1424519Sgblack@eecs.umich.edu describing arbitrary properties of the source file.''' 1434951Sgblack@eecs.umich.edu __metaclass__ = SourceMeta 1444519Sgblack@eecs.umich.edu 1454519Sgblack@eecs.umich.edu static_objs = {} 1464519Sgblack@eecs.umich.edu shared_objs = {} 1474519Sgblack@eecs.umich.edu 1484519Sgblack@eecs.umich.edu def __init__(self, source, tags=None, add_tags=None): 1494951Sgblack@eecs.umich.edu if tags is None: 1504519Sgblack@eecs.umich.edu tags='gem5 lib' 1514519Sgblack@eecs.umich.edu if isinstance(tags, basestring): 1524951Sgblack@eecs.umich.edu tags = set([tags]) 1534712Sgblack@eecs.umich.edu if not isinstance(tags, set): 1544519Sgblack@eecs.umich.edu tags = set(tags) 1554951Sgblack@eecs.umich.edu self.tags = tags 1564519Sgblack@eecs.umich.edu 1574951Sgblack@eecs.umich.edu if add_tags: 1584712Sgblack@eecs.umich.edu if isinstance(add_tags, basestring): 1594519Sgblack@eecs.umich.edu add_tags = set([add_tags]) 1604519Sgblack@eecs.umich.edu if not isinstance(add_tags, set): 1614519Sgblack@eecs.umich.edu add_tags = set(add_tags) 1624519Sgblack@eecs.umich.edu self.tags |= add_tags 1634519Sgblack@eecs.umich.edu 1644519Sgblack@eecs.umich.edu tnode = source 1654519Sgblack@eecs.umich.edu if not isinstance(source, SCons.Node.FS.File): 1664519Sgblack@eecs.umich.edu tnode = File(source) 1674519Sgblack@eecs.umich.edu 1684519Sgblack@eecs.umich.edu self.tnode = tnode 1694519Sgblack@eecs.umich.edu self.snode = tnode.srcnode() 1704519Sgblack@eecs.umich.edu 1714519Sgblack@eecs.umich.edu for base in type(self).__mro__: 1724519Sgblack@eecs.umich.edu if issubclass(base, SourceFile): 1734519Sgblack@eecs.umich.edu base.all.append(self) 1744712Sgblack@eecs.umich.edu 1754519Sgblack@eecs.umich.edu def static(self, env): 1764581Sgblack@eecs.umich.edu key = (self.tnode, env['OBJSUFFIX']) 1774688Sgblack@eecs.umich.edu if not key in self.static_objs: 1784581Sgblack@eecs.umich.edu self.static_objs[key] = env.StaticObject(self.tnode) 1794519Sgblack@eecs.umich.edu return self.static_objs[key] 1804519Sgblack@eecs.umich.edu 1814519Sgblack@eecs.umich.edu def shared(self, env): 1824519Sgblack@eecs.umich.edu key = (self.tnode, env['OBJSUFFIX']) 1834519Sgblack@eecs.umich.edu if not key in self.shared_objs: 1844519Sgblack@eecs.umich.edu self.shared_objs[key] = env.SharedObject(self.tnode) 1854519Sgblack@eecs.umich.edu return self.shared_objs[key] 1864519Sgblack@eecs.umich.edu 1874712Sgblack@eecs.umich.edu @property 1884519Sgblack@eecs.umich.edu def filename(self): 1894581Sgblack@eecs.umich.edu return str(self.tnode) 1904688Sgblack@eecs.umich.edu 1914581Sgblack@eecs.umich.edu @property 1924519Sgblack@eecs.umich.edu def dirname(self): 1934519Sgblack@eecs.umich.edu return dirname(self.filename) 1944519Sgblack@eecs.umich.edu 1954519Sgblack@eecs.umich.edu @property 1964519Sgblack@eecs.umich.edu def basename(self): 1974519Sgblack@eecs.umich.edu return basename(self.filename) 1984519Sgblack@eecs.umich.edu 1994951Sgblack@eecs.umich.edu @property 2004519Sgblack@eecs.umich.edu def extname(self): 2014519Sgblack@eecs.umich.edu index = self.basename.rfind('.') 2024519Sgblack@eecs.umich.edu if index <= 0: 2034519Sgblack@eecs.umich.edu # dot files aren't extensions 2044951Sgblack@eecs.umich.edu return self.basename, None 2054519Sgblack@eecs.umich.edu 2064951Sgblack@eecs.umich.edu return self.basename[:index], self.basename[index+1:] 2074712Sgblack@eecs.umich.edu 2084519Sgblack@eecs.umich.edu def __lt__(self, other): return self.filename < other.filename 2094581Sgblack@eecs.umich.edu def __le__(self, other): return self.filename <= other.filename 2104688Sgblack@eecs.umich.edu def __gt__(self, other): return self.filename > other.filename 2114581Sgblack@eecs.umich.edu def __ge__(self, other): return self.filename >= other.filename 2124519Sgblack@eecs.umich.edu def __eq__(self, other): return self.filename == other.filename 2134519Sgblack@eecs.umich.edu def __ne__(self, other): return self.filename != other.filename 2144519Sgblack@eecs.umich.edu 2154519Sgblack@eecs.umich.educlass Source(SourceFile): 2164951Sgblack@eecs.umich.edu ungrouped_tag = 'No link group' 2174519Sgblack@eecs.umich.edu source_groups = set() 2184519Sgblack@eecs.umich.edu 2194951Sgblack@eecs.umich.edu _current_group_tag = ungrouped_tag 2204712Sgblack@eecs.umich.edu 2214519Sgblack@eecs.umich.edu @staticmethod 2224581Sgblack@eecs.umich.edu def link_group_tag(group): 2234688Sgblack@eecs.umich.edu return 'link group: %s' % group 2244581Sgblack@eecs.umich.edu 2254519Sgblack@eecs.umich.edu @classmethod 2264519Sgblack@eecs.umich.edu def set_group(cls, group): 2274519Sgblack@eecs.umich.edu new_tag = Source.link_group_tag(group) 2284519Sgblack@eecs.umich.edu Source._current_group_tag = new_tag 2294519Sgblack@eecs.umich.edu Source.source_groups.add(group) 2305075Sgblack@eecs.umich.edu 2315075Sgblack@eecs.umich.edu def _add_link_group_tag(self): 2325075Sgblack@eecs.umich.edu self.tags.add(Source._current_group_tag) 2335075Sgblack@eecs.umich.edu 2345075Sgblack@eecs.umich.edu '''Add a c/c++ source file to the build''' 2355075Sgblack@eecs.umich.edu def __init__(self, source, tags=None, add_tags=None): 2365075Sgblack@eecs.umich.edu '''specify the source file, and any tags''' 2375075Sgblack@eecs.umich.edu super(Source, self).__init__(source, tags, add_tags) 2385075Sgblack@eecs.umich.edu self._add_link_group_tag() 2395075Sgblack@eecs.umich.edu 2405075Sgblack@eecs.umich.educlass PySource(SourceFile): 2415075Sgblack@eecs.umich.edu '''Add a python source file to the named package''' 2425075Sgblack@eecs.umich.edu invalid_sym_char = re.compile('[^A-z0-9_]') 2435075Sgblack@eecs.umich.edu modules = {} 2445075Sgblack@eecs.umich.edu tnodes = {} 2455075Sgblack@eecs.umich.edu symnames = {} 2465075Sgblack@eecs.umich.edu 2475075Sgblack@eecs.umich.edu def __init__(self, package, source, tags=None, add_tags=None): 2485075Sgblack@eecs.umich.edu '''specify the python package, the source file, and any tags''' 2495075Sgblack@eecs.umich.edu super(PySource, self).__init__(source, tags, add_tags) 2505075Sgblack@eecs.umich.edu 2515075Sgblack@eecs.umich.edu modname,ext = self.extname 2525075Sgblack@eecs.umich.edu assert ext == 'py' 2535075Sgblack@eecs.umich.edu 2545075Sgblack@eecs.umich.edu if package: 2555075Sgblack@eecs.umich.edu path = package.split('.') 2565075Sgblack@eecs.umich.edu else: 2575075Sgblack@eecs.umich.edu path = [] 2585075Sgblack@eecs.umich.edu 2595075Sgblack@eecs.umich.edu modpath = path[:] 2605075Sgblack@eecs.umich.edu if modname != '__init__': 2615075Sgblack@eecs.umich.edu modpath += [ modname ] 2625075Sgblack@eecs.umich.edu modpath = '.'.join(modpath) 2635075Sgblack@eecs.umich.edu 2645075Sgblack@eecs.umich.edu arcpath = path + [ self.basename ] 2655075Sgblack@eecs.umich.edu abspath = self.snode.abspath 2665075Sgblack@eecs.umich.edu if not exists(abspath): 2675075Sgblack@eecs.umich.edu abspath = self.tnode.abspath 2685075Sgblack@eecs.umich.edu 2694519Sgblack@eecs.umich.edu self.package = package 2705040Sgblack@eecs.umich.edu self.modname = modname 2715040Sgblack@eecs.umich.edu self.modpath = modpath 2725040Sgblack@eecs.umich.edu self.arcname = joinpath(*arcpath) 2735040Sgblack@eecs.umich.edu self.abspath = abspath 2745040Sgblack@eecs.umich.edu self.compiled = File(self.filename + 'c') 2755040Sgblack@eecs.umich.edu self.cpp = File(self.filename + '.cc') 2765040Sgblack@eecs.umich.edu self.symname = PySource.invalid_sym_char.sub('_', modpath) 2775040Sgblack@eecs.umich.edu 2785040Sgblack@eecs.umich.edu PySource.modules[modpath] = self 2795040Sgblack@eecs.umich.edu PySource.tnodes[self.tnode] = self 2805040Sgblack@eecs.umich.edu PySource.symnames[self.symname] = self 2815040Sgblack@eecs.umich.edu 2825040Sgblack@eecs.umich.educlass SimObject(PySource): 2835040Sgblack@eecs.umich.edu '''Add a SimObject python file as a python source object and add 2845040Sgblack@eecs.umich.edu it to a list of sim object modules''' 2855040Sgblack@eecs.umich.edu 2865040Sgblack@eecs.umich.edu fixed = False 2875040Sgblack@eecs.umich.edu modnames = [] 2885040Sgblack@eecs.umich.edu 2895040Sgblack@eecs.umich.edu def __init__(self, source, tags=None, add_tags=None): 2905040Sgblack@eecs.umich.edu '''Specify the source file and any tags (automatically in 2915040Sgblack@eecs.umich.edu the m5.objects package)''' 2925040Sgblack@eecs.umich.edu super(SimObject, self).__init__('m5.objects', source, tags, add_tags) 2935040Sgblack@eecs.umich.edu if self.fixed: 2945040Sgblack@eecs.umich.edu raise AttributeError, "Too late to call SimObject now." 2955040Sgblack@eecs.umich.edu 2965040Sgblack@eecs.umich.edu bisect.insort_right(SimObject.modnames, self.modname) 2975040Sgblack@eecs.umich.edu 2985040Sgblack@eecs.umich.educlass ProtoBuf(SourceFile): 2995040Sgblack@eecs.umich.edu '''Add a Protocol Buffer to build''' 3005062Sgblack@eecs.umich.edu 3015062Sgblack@eecs.umich.edu def __init__(self, source, tags=None, add_tags=None): 3025062Sgblack@eecs.umich.edu '''Specify the source file, and any tags''' 3035062Sgblack@eecs.umich.edu super(ProtoBuf, self).__init__(source, tags, add_tags) 3045062Sgblack@eecs.umich.edu 3055062Sgblack@eecs.umich.edu # Get the file name and the extension 3065062Sgblack@eecs.umich.edu modname,ext = self.extname 3075040Sgblack@eecs.umich.edu assert ext == 'proto' 3085062Sgblack@eecs.umich.edu 3095062Sgblack@eecs.umich.edu # Currently, we stick to generating the C++ headers, so we 3105062Sgblack@eecs.umich.edu # only need to track the source and header. 3115062Sgblack@eecs.umich.edu self.cc_file = File(modname + '.pb.cc') 3125040Sgblack@eecs.umich.edu self.hh_file = File(modname + '.pb.h') 3135040Sgblack@eecs.umich.edu 3145040Sgblack@eecs.umich.edu 3155040Sgblack@eecs.umich.eduexectuable_classes = [] 3165040Sgblack@eecs.umich.educlass ExecutableMeta(type): 3175040Sgblack@eecs.umich.edu '''Meta class for Executables.''' 3185040Sgblack@eecs.umich.edu all = [] 3195040Sgblack@eecs.umich.edu 3205040Sgblack@eecs.umich.edu def __init__(cls, name, bases, d): 3215040Sgblack@eecs.umich.edu if not d.pop('abstract', False): 3225040Sgblack@eecs.umich.edu ExecutableMeta.all.append(cls) 3235040Sgblack@eecs.umich.edu super(ExecutableMeta, cls).__init__(name, bases, d) 3245040Sgblack@eecs.umich.edu 3255040Sgblack@eecs.umich.edu cls.all = [] 3265040Sgblack@eecs.umich.edu 3275040Sgblack@eecs.umich.educlass Executable(object): 3285040Sgblack@eecs.umich.edu '''Base class for creating an executable from sources.''' 3295040Sgblack@eecs.umich.edu __metaclass__ = ExecutableMeta 3305061Sgblack@eecs.umich.edu 3315040Sgblack@eecs.umich.edu abstract = True 3325040Sgblack@eecs.umich.edu 3335061Sgblack@eecs.umich.edu def __init__(self, target, *srcs_and_filts): 3345061Sgblack@eecs.umich.edu '''Specify the target name and any sources. Sources that are 3355061Sgblack@eecs.umich.edu not SourceFiles are evalued with Source().''' 3365061Sgblack@eecs.umich.edu super(Executable, self).__init__() 3375061Sgblack@eecs.umich.edu self.all.append(self) 3385061Sgblack@eecs.umich.edu self.target = target 3395061Sgblack@eecs.umich.edu 3405061Sgblack@eecs.umich.edu isFilter = lambda arg: isinstance(arg, SourceFilter) 3415040Sgblack@eecs.umich.edu self.filters = filter(isFilter, srcs_and_filts) 3425040Sgblack@eecs.umich.edu sources = filter(lambda a: not isFilter(a), srcs_and_filts) 3435040Sgblack@eecs.umich.edu 3445040Sgblack@eecs.umich.edu srcs = SourceList() 3455040Sgblack@eecs.umich.edu for src in sources: 3465040Sgblack@eecs.umich.edu if not isinstance(src, SourceFile): 3475040Sgblack@eecs.umich.edu src = Source(src, tags=[]) 3485040Sgblack@eecs.umich.edu srcs.append(src) 3495040Sgblack@eecs.umich.edu 3505040Sgblack@eecs.umich.edu self.sources = srcs 3515040Sgblack@eecs.umich.edu self.dir = Dir('.') 3525040Sgblack@eecs.umich.edu 3535040Sgblack@eecs.umich.edu def path(self, env): 3545040Sgblack@eecs.umich.edu return self.dir.File(self.target + '.' + env['EXE_SUFFIX']) 3555040Sgblack@eecs.umich.edu 3565040Sgblack@eecs.umich.edu def srcs_to_objs(self, env, sources): 3575040Sgblack@eecs.umich.edu return list([ s.static(env) for s in sources ]) 3585040Sgblack@eecs.umich.edu 3595040Sgblack@eecs.umich.edu @classmethod 3605040Sgblack@eecs.umich.edu def declare_all(cls, env): 3615040Sgblack@eecs.umich.edu return list([ instance.declare(env) for instance in cls.all ]) 3625040Sgblack@eecs.umich.edu 3635040Sgblack@eecs.umich.edu def declare(self, env, objs=None): 3645040Sgblack@eecs.umich.edu if objs is None: 3655040Sgblack@eecs.umich.edu objs = self.srcs_to_objs(env, self.sources) 3664688Sgblack@eecs.umich.edu 3675040Sgblack@eecs.umich.edu if env['STRIP_EXES']: 3684688Sgblack@eecs.umich.edu stripped = self.path(env) 3694688Sgblack@eecs.umich.edu unstripped = env.File(str(stripped) + '.unstripped') 3704688Sgblack@eecs.umich.edu if sys.platform == 'sunos5': 3714688Sgblack@eecs.umich.edu cmd = 'cp $SOURCE $TARGET; strip $TARGET' 3725040Sgblack@eecs.umich.edu else: 3734688Sgblack@eecs.umich.edu cmd = 'strip $SOURCE -o $TARGET' 3745040Sgblack@eecs.umich.edu env.Program(unstripped, objs) 3755040Sgblack@eecs.umich.edu return env.Command(stripped, unstripped, 3765040Sgblack@eecs.umich.edu MakeAction(cmd, Transform("STRIP"))) 3775040Sgblack@eecs.umich.edu else: 3785040Sgblack@eecs.umich.edu return env.Program(self.path(env), objs) 3795040Sgblack@eecs.umich.edu 3805040Sgblack@eecs.umich.educlass UnitTest(Executable): 3815040Sgblack@eecs.umich.edu '''Create a UnitTest''' 3825040Sgblack@eecs.umich.edu def __init__(self, target, *srcs_and_filts, **kwargs): 3835040Sgblack@eecs.umich.edu super(UnitTest, self).__init__(target, *srcs_and_filts) 3845040Sgblack@eecs.umich.edu 3855040Sgblack@eecs.umich.edu self.main = kwargs.get('main', False) 3865040Sgblack@eecs.umich.edu 3875040Sgblack@eecs.umich.edu def declare(self, env): 3885040Sgblack@eecs.umich.edu sources = list(self.sources) 3895040Sgblack@eecs.umich.edu for f in self.filters: 3905040Sgblack@eecs.umich.edu sources = Source.all.apply_filter(f) 3915040Sgblack@eecs.umich.edu objs = self.srcs_to_objs(env, sources) + env['STATIC_OBJS'] 3925040Sgblack@eecs.umich.edu if self.main: 3935040Sgblack@eecs.umich.edu objs += env['MAIN_OBJS'] 3945040Sgblack@eecs.umich.edu return super(UnitTest, self).declare(env, objs) 3955040Sgblack@eecs.umich.edu 3964688Sgblack@eecs.umich.educlass GTest(Executable): 3974688Sgblack@eecs.umich.edu '''Create a unit test based on the google test framework.''' 3985040Sgblack@eecs.umich.edu all = [] 3995040Sgblack@eecs.umich.edu def __init__(self, *srcs_and_filts, **kwargs): 4005040Sgblack@eecs.umich.edu super(GTest, self).__init__(*srcs_and_filts) 4015040Sgblack@eecs.umich.edu 4024688Sgblack@eecs.umich.edu self.skip_lib = kwargs.pop('skip_lib', False) 4034688Sgblack@eecs.umich.edu 4045040Sgblack@eecs.umich.edu @classmethod 4055040Sgblack@eecs.umich.edu def declare_all(cls, env): 4065040Sgblack@eecs.umich.edu env = env.Clone() 4075040Sgblack@eecs.umich.edu env.Append(LIBS=env['GTEST_LIBS']) 4085040Sgblack@eecs.umich.edu env.Append(CPPFLAGS=env['GTEST_CPPFLAGS']) 4095040Sgblack@eecs.umich.edu env['GTEST_LIB_SOURCES'] = Source.all.with_tag('gtest lib') 4104519Sgblack@eecs.umich.edu env['GTEST_OUT_DIR'] = \ 4114519Sgblack@eecs.umich.edu Dir(env['BUILDDIR']).Dir('unittests.' + env['EXE_SUFFIX']) 4125040Sgblack@eecs.umich.edu return super(GTest, cls).declare_all(env) 4134688Sgblack@eecs.umich.edu 4144701Sgblack@eecs.umich.edu def declare(self, env): 4154688Sgblack@eecs.umich.edu sources = list(self.sources) 4164688Sgblack@eecs.umich.edu if not self.skip_lib: 4174688Sgblack@eecs.umich.edu sources += env['GTEST_LIB_SOURCES'] 4184688Sgblack@eecs.umich.edu for f in self.filters: 4194688Sgblack@eecs.umich.edu sources += Source.all.apply_filter(f) 4204688Sgblack@eecs.umich.edu objs = self.srcs_to_objs(env, sources) 4214688Sgblack@eecs.umich.edu 4224519Sgblack@eecs.umich.edu binary = super(GTest, self).declare(env, objs) 4234519Sgblack@eecs.umich.edu 4245040Sgblack@eecs.umich.edu out_dir = env['GTEST_OUT_DIR'] 4255040Sgblack@eecs.umich.edu xml_file = out_dir.Dir(str(self.dir)).File(self.target + '.xml') 4265040Sgblack@eecs.umich.edu AlwaysBuild(env.Command(xml_file, binary, 4274560Sgblack@eecs.umich.edu "${SOURCES[0]} --gtest_output=xml:${TARGETS[0]}")) 4285040Sgblack@eecs.umich.edu 4294688Sgblack@eecs.umich.edu return binary 4305040Sgblack@eecs.umich.edu 4314519Sgblack@eecs.umich.educlass Gem5(Executable): 4325040Sgblack@eecs.umich.edu '''Create a gem5 executable.''' 4334519Sgblack@eecs.umich.edu 4344519Sgblack@eecs.umich.edu def __init__(self, target): 4354519Sgblack@eecs.umich.edu super(Gem5, self).__init__(target) 4364539Sgblack@eecs.umich.edu 4374519Sgblack@eecs.umich.edu def declare(self, env): 4385040Sgblack@eecs.umich.edu objs = env['MAIN_OBJS'] + env['STATIC_OBJS'] 4394688Sgblack@eecs.umich.edu return super(Gem5, self).declare(env, objs) 4405040Sgblack@eecs.umich.edu 4415040Sgblack@eecs.umich.edu 4425115Sgblack@eecs.umich.edu# Children should have access 4435040Sgblack@eecs.umich.eduExport('Source') 4445040Sgblack@eecs.umich.eduExport('PySource') 4455040Sgblack@eecs.umich.eduExport('SimObject') 4465115Sgblack@eecs.umich.eduExport('ProtoBuf') 4475040Sgblack@eecs.umich.eduExport('Executable') 4485040Sgblack@eecs.umich.eduExport('UnitTest') 4494519Sgblack@eecs.umich.eduExport('GTest') 4505040Sgblack@eecs.umich.edu 4515040Sgblack@eecs.umich.edu######################################################################## 4525040Sgblack@eecs.umich.edu# 4535040Sgblack@eecs.umich.edu# Debug Flags 4544519Sgblack@eecs.umich.edu# 4555040Sgblack@eecs.umich.edudebug_flags = {} 4565040Sgblack@eecs.umich.edudef DebugFlag(name, desc=None): 4575040Sgblack@eecs.umich.edu if name in debug_flags: 4585040Sgblack@eecs.umich.edu raise AttributeError, "Flag %s already specified" % name 4594519Sgblack@eecs.umich.edu debug_flags[name] = (name, (), desc) 4605040Sgblack@eecs.umich.edu 4615040Sgblack@eecs.umich.edudef CompoundFlag(name, flags, desc=None): 4625083Sgblack@eecs.umich.edu if name in debug_flags: 4634519Sgblack@eecs.umich.edu raise AttributeError, "Flag %s already specified" % name 4645063Sgblack@eecs.umich.edu 4655063Sgblack@eecs.umich.edu compound = tuple(flags) 4665063Sgblack@eecs.umich.edu debug_flags[name] = (name, compound, desc) 4675063Sgblack@eecs.umich.edu 4685063Sgblack@eecs.umich.eduExport('DebugFlag') 4695063Sgblack@eecs.umich.eduExport('CompoundFlag') 4705063Sgblack@eecs.umich.edu 4715063Sgblack@eecs.umich.edu######################################################################## 4725063Sgblack@eecs.umich.edu# 4735063Sgblack@eecs.umich.edu# Set some compiler variables 4745063Sgblack@eecs.umich.edu# 4755063Sgblack@eecs.umich.edu 4765040Sgblack@eecs.umich.edu# Include file paths are rooted in this directory. SCons will 4775040Sgblack@eecs.umich.edu# automatically expand '.' to refer to both the source directory and 4784595Sgblack@eecs.umich.edu# the corresponding build directory to pick up generated include 4795040Sgblack@eecs.umich.edu# files. 4805040Sgblack@eecs.umich.eduenv.Append(CPPPATH=Dir('.')) 4814595Sgblack@eecs.umich.edu 4825040Sgblack@eecs.umich.edufor extra_dir in extras_dir_list: 4835040Sgblack@eecs.umich.edu env.Append(CPPPATH=Dir(extra_dir)) 4844732Sgblack@eecs.umich.edu 4855138Sgblack@eecs.umich.edu# Workaround for bug in SCons version > 0.97d20071212 4865040Sgblack@eecs.umich.edu# Scons bug id: 2006 gem5 Bug id: 308 4875040Sgblack@eecs.umich.edufor root, dirs, files in os.walk(base_dir, topdown=True): 4885040Sgblack@eecs.umich.edu Dir(root[len(base_dir) + 1:]) 4895040Sgblack@eecs.umich.edu 4904732Sgblack@eecs.umich.edu######################################################################## 4915138Sgblack@eecs.umich.edu# 4925040Sgblack@eecs.umich.edu# Walk the tree and execute all SConscripts in subdirectories 4935040Sgblack@eecs.umich.edu# 4945040Sgblack@eecs.umich.edu 4955040Sgblack@eecs.umich.eduhere = Dir('.').srcnode().abspath 4965040Sgblack@eecs.umich.edufor root, dirs, files in os.walk(base_dir, topdown=True): 4975040Sgblack@eecs.umich.edu if root == here: 4985040Sgblack@eecs.umich.edu # we don't want to recurse back into this SConscript 4995040Sgblack@eecs.umich.edu continue 5005040Sgblack@eecs.umich.edu 5015040Sgblack@eecs.umich.edu if 'SConscript' in files: 5025040Sgblack@eecs.umich.edu build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:]) 5035065Sgblack@eecs.umich.edu Source.set_group(build_dir) 5045065Sgblack@eecs.umich.edu SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) 5055065Sgblack@eecs.umich.edu 5065065Sgblack@eecs.umich.edufor extra_dir in extras_dir_list: 5075065Sgblack@eecs.umich.edu prefix_len = len(dirname(extra_dir)) + 1 5085063Sgblack@eecs.umich.edu 5095040Sgblack@eecs.umich.edu # Also add the corresponding build directory to pick up generated 5105063Sgblack@eecs.umich.edu # include files. 5115063Sgblack@eecs.umich.edu env.Append(CPPPATH=Dir(joinpath(env['BUILDDIR'], extra_dir[prefix_len:]))) 5125063Sgblack@eecs.umich.edu 5135063Sgblack@eecs.umich.edu for root, dirs, files in os.walk(extra_dir, topdown=True): 5145063Sgblack@eecs.umich.edu # if build lives in the extras directory, don't walk down it 5155063Sgblack@eecs.umich.edu if 'build' in dirs: 5165063Sgblack@eecs.umich.edu dirs.remove('build') 5175063Sgblack@eecs.umich.edu 5185063Sgblack@eecs.umich.edu if 'SConscript' in files: 5195040Sgblack@eecs.umich.edu build_dir = joinpath(env['BUILDDIR'], root[prefix_len:]) 5205040Sgblack@eecs.umich.edu SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) 5215063Sgblack@eecs.umich.edu 5225040Sgblack@eecs.umich.edufor opt in export_vars: 5235063Sgblack@eecs.umich.edu env.ConfigFile(opt) 5244809Sgblack@eecs.umich.edu 5255063Sgblack@eecs.umich.edudef makeTheISA(source, target, env): 5265063Sgblack@eecs.umich.edu isas = [ src.get_contents() for src in source ] 5275063Sgblack@eecs.umich.edu target_isa = env['TARGET_ISA'] 5285063Sgblack@eecs.umich.edu def define(isa): 5295063Sgblack@eecs.umich.edu return isa.upper() + '_ISA' 5305063Sgblack@eecs.umich.edu 5315063Sgblack@eecs.umich.edu def namespace(isa): 5325040Sgblack@eecs.umich.edu return isa[0].upper() + isa[1:].lower() + 'ISA' 5335040Sgblack@eecs.umich.edu 5345063Sgblack@eecs.umich.edu 5355063Sgblack@eecs.umich.edu code = code_formatter() 5365040Sgblack@eecs.umich.edu code('''\ 5375063Sgblack@eecs.umich.edu#ifndef __CONFIG_THE_ISA_HH__ 5385063Sgblack@eecs.umich.edu#define __CONFIG_THE_ISA_HH__ 5395063Sgblack@eecs.umich.edu 5405063Sgblack@eecs.umich.edu''') 5415063Sgblack@eecs.umich.edu 5425063Sgblack@eecs.umich.edu # create defines for the preprocessing and compile-time determination 5435063Sgblack@eecs.umich.edu for i,isa in enumerate(isas): 5445063Sgblack@eecs.umich.edu code('#define $0 $1', define(isa), i + 1) 5455063Sgblack@eecs.umich.edu code() 5465063Sgblack@eecs.umich.edu 5475063Sgblack@eecs.umich.edu # create an enum for any run-time determination of the ISA, we 5485063Sgblack@eecs.umich.edu # reuse the same name as the namespaces 5495062Sgblack@eecs.umich.edu code('enum class Arch {') 5505075Sgblack@eecs.umich.edu for i,isa in enumerate(isas): 5515075Sgblack@eecs.umich.edu if i + 1 == len(isas): 5525040Sgblack@eecs.umich.edu code(' $0 = $1', namespace(isa), define(isa)) 5535075Sgblack@eecs.umich.edu else: 5545075Sgblack@eecs.umich.edu code(' $0 = $1,', namespace(isa), define(isa)) 5555075Sgblack@eecs.umich.edu code('};') 5565075Sgblack@eecs.umich.edu 5575075Sgblack@eecs.umich.edu code(''' 5585075Sgblack@eecs.umich.edu 5595075Sgblack@eecs.umich.edu#define THE_ISA ${{define(target_isa)}} 5605075Sgblack@eecs.umich.edu#define TheISA ${{namespace(target_isa)}} 5615075Sgblack@eecs.umich.edu#define THE_ISA_STR "${{target_isa}}" 5625075Sgblack@eecs.umich.edu 5635075Sgblack@eecs.umich.edu#endif // __CONFIG_THE_ISA_HH__''') 5645075Sgblack@eecs.umich.edu 5655075Sgblack@eecs.umich.edu code.write(str(target[0])) 5665075Sgblack@eecs.umich.edu 5675075Sgblack@eecs.umich.eduenv.Command('config/the_isa.hh', map(Value, all_isa_list), 5685040Sgblack@eecs.umich.edu MakeAction(makeTheISA, Transform("CFG ISA", 0))) 5694823Sgblack@eecs.umich.edu 5705075Sgblack@eecs.umich.edudef makeTheGPUISA(source, target, env): 5715075Sgblack@eecs.umich.edu isas = [ src.get_contents() for src in source ] 5725075Sgblack@eecs.umich.edu target_gpu_isa = env['TARGET_GPU_ISA'] 5735075Sgblack@eecs.umich.edu def define(isa): 5745075Sgblack@eecs.umich.edu return isa.upper() + '_ISA' 5755075Sgblack@eecs.umich.edu 5765075Sgblack@eecs.umich.edu def namespace(isa): 5775075Sgblack@eecs.umich.edu return isa[0].upper() + isa[1:].lower() + 'ISA' 5785075Sgblack@eecs.umich.edu 5795075Sgblack@eecs.umich.edu 5805075Sgblack@eecs.umich.edu code = code_formatter() 5815075Sgblack@eecs.umich.edu code('''\ 5825075Sgblack@eecs.umich.edu#ifndef __CONFIG_THE_GPU_ISA_HH__ 5835075Sgblack@eecs.umich.edu#define __CONFIG_THE_GPU_ISA_HH__ 5845075Sgblack@eecs.umich.edu 5855075Sgblack@eecs.umich.edu''') 5865075Sgblack@eecs.umich.edu 5875075Sgblack@eecs.umich.edu # create defines for the preprocessing and compile-time determination 5885075Sgblack@eecs.umich.edu for i,isa in enumerate(isas): 5895075Sgblack@eecs.umich.edu code('#define $0 $1', define(isa), i + 1) 5905075Sgblack@eecs.umich.edu code() 5915075Sgblack@eecs.umich.edu 5925075Sgblack@eecs.umich.edu # create an enum for any run-time determination of the ISA, we 5935075Sgblack@eecs.umich.edu # reuse the same name as the namespaces 5945075Sgblack@eecs.umich.edu code('enum class GPUArch {') 5955075Sgblack@eecs.umich.edu for i,isa in enumerate(isas): 5965075Sgblack@eecs.umich.edu if i + 1 == len(isas): 5975075Sgblack@eecs.umich.edu code(' $0 = $1', namespace(isa), define(isa)) 5985075Sgblack@eecs.umich.edu else: 5995075Sgblack@eecs.umich.edu code(' $0 = $1,', namespace(isa), define(isa)) 6005075Sgblack@eecs.umich.edu code('};') 6015075Sgblack@eecs.umich.edu 6025075Sgblack@eecs.umich.edu code(''' 6034732Sgblack@eecs.umich.edu 6045075Sgblack@eecs.umich.edu#define THE_GPU_ISA ${{define(target_gpu_isa)}} 6055075Sgblack@eecs.umich.edu#define TheGpuISA ${{namespace(target_gpu_isa)}} 6065075Sgblack@eecs.umich.edu#define THE_GPU_ISA_STR "${{target_gpu_isa}}" 6075075Sgblack@eecs.umich.edu 6085075Sgblack@eecs.umich.edu#endif // __CONFIG_THE_GPU_ISA_HH__''') 6095040Sgblack@eecs.umich.edu 6105040Sgblack@eecs.umich.edu code.write(str(target[0])) 6115040Sgblack@eecs.umich.edu 6125040Sgblack@eecs.umich.eduenv.Command('config/the_gpu_isa.hh', map(Value, all_gpu_isa_list), 6135040Sgblack@eecs.umich.edu MakeAction(makeTheGPUISA, Transform("CFG ISA", 0))) 6144732Sgblack@eecs.umich.edu 6155040Sgblack@eecs.umich.edu######################################################################## 6165076Sgblack@eecs.umich.edu# 6175040Sgblack@eecs.umich.edu# Prevent any SimObjects from being added after this point, they 6184756Sgblack@eecs.umich.edu# should all have been added in the SConscripts above 6194823Sgblack@eecs.umich.edu# 6205040Sgblack@eecs.umich.eduSimObject.fixed = True 6215076Sgblack@eecs.umich.edu 6225076Sgblack@eecs.umich.educlass DictImporter(object): 6235076Sgblack@eecs.umich.edu '''This importer takes a dictionary of arbitrary module names that 6245076Sgblack@eecs.umich.edu map to arbitrary filenames.''' 6255076Sgblack@eecs.umich.edu def __init__(self, modules): 6265076Sgblack@eecs.umich.edu self.modules = modules 6275076Sgblack@eecs.umich.edu self.installed = set() 6285076Sgblack@eecs.umich.edu 6295076Sgblack@eecs.umich.edu def __del__(self): 6305076Sgblack@eecs.umich.edu self.unload() 6315076Sgblack@eecs.umich.edu 6325076Sgblack@eecs.umich.edu def unload(self): 6335076Sgblack@eecs.umich.edu import sys 6345076Sgblack@eecs.umich.edu for module in self.installed: 6355076Sgblack@eecs.umich.edu del sys.modules[module] 6365076Sgblack@eecs.umich.edu self.installed = set() 6375076Sgblack@eecs.umich.edu 6385076Sgblack@eecs.umich.edu def find_module(self, fullname, path): 6395076Sgblack@eecs.umich.edu if fullname == 'm5.defines': 6405076Sgblack@eecs.umich.edu return self 6415076Sgblack@eecs.umich.edu 6425040Sgblack@eecs.umich.edu if fullname == 'm5.objects': 6435076Sgblack@eecs.umich.edu return self 6445040Sgblack@eecs.umich.edu 6454756Sgblack@eecs.umich.edu if fullname.startswith('_m5'): 6464732Sgblack@eecs.umich.edu return None 6474732Sgblack@eecs.umich.edu 6484732Sgblack@eecs.umich.edu source = self.modules.get(fullname, None) 6494732Sgblack@eecs.umich.edu if source is not None and fullname.startswith('m5.objects'): 6504823Sgblack@eecs.umich.edu return self 6515040Sgblack@eecs.umich.edu 6525076Sgblack@eecs.umich.edu return None 6535076Sgblack@eecs.umich.edu 6545076Sgblack@eecs.umich.edu def load_module(self, fullname): 6555076Sgblack@eecs.umich.edu mod = imp.new_module(fullname) 6565076Sgblack@eecs.umich.edu sys.modules[fullname] = mod 6575076Sgblack@eecs.umich.edu self.installed.add(fullname) 6585076Sgblack@eecs.umich.edu 6595076Sgblack@eecs.umich.edu mod.__loader__ = self 6605076Sgblack@eecs.umich.edu if fullname == 'm5.objects': 6615076Sgblack@eecs.umich.edu mod.__path__ = fullname.split('.') 6625076Sgblack@eecs.umich.edu return mod 6635076Sgblack@eecs.umich.edu 6645076Sgblack@eecs.umich.edu if fullname == 'm5.defines': 6655076Sgblack@eecs.umich.edu mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env) 6665076Sgblack@eecs.umich.edu return mod 6675076Sgblack@eecs.umich.edu 6685076Sgblack@eecs.umich.edu source = self.modules[fullname] 6695040Sgblack@eecs.umich.edu if source.modname == '__init__': 6705076Sgblack@eecs.umich.edu mod.__path__ = source.modpath 6715040Sgblack@eecs.umich.edu mod.__file__ = source.abspath 6724756Sgblack@eecs.umich.edu 6734732Sgblack@eecs.umich.edu exec file(source.abspath, 'r') in mod.__dict__ 6744732Sgblack@eecs.umich.edu 6754732Sgblack@eecs.umich.edu return mod 6764732Sgblack@eecs.umich.edu 6775032Sgblack@eecs.umich.eduimport m5.SimObject 6784823Sgblack@eecs.umich.eduimport m5.params 6795040Sgblack@eecs.umich.edufrom m5.util import code_formatter 6805076Sgblack@eecs.umich.edu 6815076Sgblack@eecs.umich.edum5.SimObject.clear() 6825076Sgblack@eecs.umich.edum5.params.clear() 6835076Sgblack@eecs.umich.edu 6845076Sgblack@eecs.umich.edu# install the python importer so we can grab stuff from the source 6855076Sgblack@eecs.umich.edu# tree itself. We can't have SimObjects added after this point or 6865076Sgblack@eecs.umich.edu# else we won't know about them for the rest of the stuff. 6875076Sgblack@eecs.umich.eduimporter = DictImporter(PySource.modules) 6885076Sgblack@eecs.umich.edusys.meta_path[0:0] = [ importer ] 6895076Sgblack@eecs.umich.edu 6905076Sgblack@eecs.umich.edu# import all sim objects so we can populate the all_objects list 6915076Sgblack@eecs.umich.edu# make sure that we're working with a list, then let's sort it 6925076Sgblack@eecs.umich.edufor modname in SimObject.modnames: 6935076Sgblack@eecs.umich.edu exec('from m5.objects import %s' % modname) 6945040Sgblack@eecs.umich.edu 6955076Sgblack@eecs.umich.edu# we need to unload all of the currently imported modules so that they 6965040Sgblack@eecs.umich.edu# will be re-imported the next time the sconscript is run 6974732Sgblack@eecs.umich.eduimporter.unload() 6984756Sgblack@eecs.umich.edusys.meta_path.remove(importer) 6994732Sgblack@eecs.umich.edu 7004732Sgblack@eecs.umich.edusim_objects = m5.SimObject.allClasses 7014823Sgblack@eecs.umich.eduall_enums = m5.params.allEnums 7024823Sgblack@eecs.umich.edu 7034732Sgblack@eecs.umich.edufor name,obj in sorted(sim_objects.iteritems()): 7044732Sgblack@eecs.umich.edu for param in obj._params.local.values(): 7054732Sgblack@eecs.umich.edu # load the ptype attribute now because it depends on the 7064732Sgblack@eecs.umich.edu # current version of SimObject.allClasses, but when scons 7075040Sgblack@eecs.umich.edu # actually uses the value, all versions of 7085076Sgblack@eecs.umich.edu # SimObject.allClasses will have been loaded 7095076Sgblack@eecs.umich.edu param.ptype 7105076Sgblack@eecs.umich.edu 7115076Sgblack@eecs.umich.edu######################################################################## 7125076Sgblack@eecs.umich.edu# 7135076Sgblack@eecs.umich.edu# calculate extra dependencies 7145076Sgblack@eecs.umich.edu# 7155076Sgblack@eecs.umich.edumodule_depends = ["m5", "m5.SimObject", "m5.params"] 7165076Sgblack@eecs.umich.edudepends = [ PySource.modules[dep].snode for dep in module_depends ] 7175076Sgblack@eecs.umich.edudepends.sort(key = lambda x: x.name) 7185076Sgblack@eecs.umich.edu 7195076Sgblack@eecs.umich.edu######################################################################## 7205076Sgblack@eecs.umich.edu# 7215076Sgblack@eecs.umich.edu# Commands for the basic automatically generated python files 7225076Sgblack@eecs.umich.edu# 7235076Sgblack@eecs.umich.edu 7245076Sgblack@eecs.umich.edu# Generate Python file containing a dict specifying the current 7255076Sgblack@eecs.umich.edu# buildEnv flags. 7265076Sgblack@eecs.umich.edudef makeDefinesPyFile(target, source, env): 7275076Sgblack@eecs.umich.edu build_env = source[0].get_contents() 7285040Sgblack@eecs.umich.edu 7295076Sgblack@eecs.umich.edu code = code_formatter() 7305040Sgblack@eecs.umich.edu code(""" 7314733Sgblack@eecs.umich.eduimport _m5.core 7324756Sgblack@eecs.umich.eduimport m5.util 7334733Sgblack@eecs.umich.edu 7344733Sgblack@eecs.umich.edubuildEnv = m5.util.SmartDict($build_env) 7354733Sgblack@eecs.umich.edu 7365138Sgblack@eecs.umich.educompileDate = _m5.core.compileDate 7374733Sgblack@eecs.umich.edu_globals = globals() 7384823Sgblack@eecs.umich.edufor key,val in _m5.core.__dict__.iteritems(): 7394823Sgblack@eecs.umich.edu if key.startswith('flag_'): 7404733Sgblack@eecs.umich.edu flag = key[5:] 7414733Sgblack@eecs.umich.edu _globals[flag] = val 7424733Sgblack@eecs.umich.edudel _globals 7434733Sgblack@eecs.umich.edu""") 7445040Sgblack@eecs.umich.edu code.write(target[0].abspath) 7455076Sgblack@eecs.umich.edu 7465076Sgblack@eecs.umich.edudefines_info = Value(build_env) 7475076Sgblack@eecs.umich.edu# Generate a file with all of the compile options in it 7485076Sgblack@eecs.umich.eduenv.Command('python/m5/defines.py', defines_info, 7495076Sgblack@eecs.umich.edu MakeAction(makeDefinesPyFile, Transform("DEFINES", 0))) 7505076Sgblack@eecs.umich.eduPySource('m5', 'python/m5/defines.py') 7515076Sgblack@eecs.umich.edu 7525076Sgblack@eecs.umich.edu# Generate python file containing info about the M5 source code 7535076Sgblack@eecs.umich.edudef makeInfoPyFile(target, source, env): 7545076Sgblack@eecs.umich.edu code = code_formatter() 7555076Sgblack@eecs.umich.edu for src in source: 7565076Sgblack@eecs.umich.edu data = ''.join(file(src.srcnode().abspath, 'r').xreadlines()) 7575076Sgblack@eecs.umich.edu code('$src = ${{repr(data)}}') 7585076Sgblack@eecs.umich.edu code.write(str(target[0])) 7595076Sgblack@eecs.umich.edu 7605076Sgblack@eecs.umich.edu# Generate a file that wraps the basic top level files 7615076Sgblack@eecs.umich.eduenv.Command('python/m5/info.py', 7625076Sgblack@eecs.umich.edu [ '#/COPYING', '#/LICENSE', '#/README', ], 7635040Sgblack@eecs.umich.edu MakeAction(makeInfoPyFile, Transform("INFO"))) 7645076Sgblack@eecs.umich.eduPySource('m5', 'python/m5/info.py') 7655040Sgblack@eecs.umich.edu 7664732Sgblack@eecs.umich.edu######################################################################## 7674756Sgblack@eecs.umich.edu# 7684732Sgblack@eecs.umich.edu# Create all of the SimObject param headers and enum headers 7694732Sgblack@eecs.umich.edu# 7704823Sgblack@eecs.umich.edu 7714732Sgblack@eecs.umich.edudef createSimObjectParamStruct(target, source, env): 7724823Sgblack@eecs.umich.edu assert len(target) == 1 and len(source) == 1 7734732Sgblack@eecs.umich.edu 7744732Sgblack@eecs.umich.edu name = source[0].get_text_contents() 7754732Sgblack@eecs.umich.edu obj = sim_objects[name] 7764732Sgblack@eecs.umich.edu 7775040Sgblack@eecs.umich.edu code = code_formatter() 7785076Sgblack@eecs.umich.edu obj.cxx_param_decl(code) 7795076Sgblack@eecs.umich.edu code.write(target[0].abspath) 7805076Sgblack@eecs.umich.edu 7815076Sgblack@eecs.umich.edudef createSimObjectCxxConfig(is_header): 7825076Sgblack@eecs.umich.edu def body(target, source, env): 7835076Sgblack@eecs.umich.edu assert len(target) == 1 and len(source) == 1 7845076Sgblack@eecs.umich.edu 7855076Sgblack@eecs.umich.edu name = str(source[0].get_contents()) 7865076Sgblack@eecs.umich.edu obj = sim_objects[name] 7875076Sgblack@eecs.umich.edu 7885076Sgblack@eecs.umich.edu code = code_formatter() 7895076Sgblack@eecs.umich.edu obj.cxx_config_param_file(code, is_header) 7905076Sgblack@eecs.umich.edu code.write(target[0].abspath) 7915076Sgblack@eecs.umich.edu return body 7925076Sgblack@eecs.umich.edu 7935076Sgblack@eecs.umich.edudef createEnumStrings(target, source, env): 7945076Sgblack@eecs.umich.edu assert len(target) == 1 and len(source) == 2 7955076Sgblack@eecs.umich.edu 7965076Sgblack@eecs.umich.edu name = source[0].get_text_contents() 7975076Sgblack@eecs.umich.edu use_python = source[1].read() 7985040Sgblack@eecs.umich.edu obj = all_enums[name] 7995076Sgblack@eecs.umich.edu 8005040Sgblack@eecs.umich.edu code = code_formatter() 8014733Sgblack@eecs.umich.edu obj.cxx_def(code) 8024756Sgblack@eecs.umich.edu if use_python: 8034733Sgblack@eecs.umich.edu obj.pybind_def(code) 8044733Sgblack@eecs.umich.edu code.write(target[0].abspath) 8054733Sgblack@eecs.umich.edu 8064823Sgblack@eecs.umich.edudef createEnumDecls(target, source, env): 8075138Sgblack@eecs.umich.edu assert len(target) == 1 and len(source) == 1 8084733Sgblack@eecs.umich.edu 8094733Sgblack@eecs.umich.edu name = source[0].get_text_contents() 8104823Sgblack@eecs.umich.edu obj = all_enums[name] 8114809Sgblack@eecs.umich.edu 8124733Sgblack@eecs.umich.edu code = code_formatter() 8134733Sgblack@eecs.umich.edu obj.cxx_decl(code) 8144733Sgblack@eecs.umich.edu code.write(target[0].abspath) 8154733Sgblack@eecs.umich.edu 8165040Sgblack@eecs.umich.edudef createSimObjectPyBindWrapper(target, source, env): 8175076Sgblack@eecs.umich.edu name = source[0].get_text_contents() 8185076Sgblack@eecs.umich.edu obj = sim_objects[name] 8195076Sgblack@eecs.umich.edu 8205076Sgblack@eecs.umich.edu code = code_formatter() 8215076Sgblack@eecs.umich.edu obj.pybind_decl(code) 8225076Sgblack@eecs.umich.edu code.write(target[0].abspath) 8235076Sgblack@eecs.umich.edu 8245076Sgblack@eecs.umich.edu# Generate all of the SimObject param C++ struct header files 8255076Sgblack@eecs.umich.eduparams_hh_files = [] 8265076Sgblack@eecs.umich.edufor name,simobj in sorted(sim_objects.iteritems()): 8275076Sgblack@eecs.umich.edu py_source = PySource.modules[simobj.__module__] 8285076Sgblack@eecs.umich.edu extra_deps = [ py_source.tnode ] 8295076Sgblack@eecs.umich.edu 8305076Sgblack@eecs.umich.edu hh_file = File('params/%s.hh' % name) 8315076Sgblack@eecs.umich.edu params_hh_files.append(hh_file) 8325076Sgblack@eecs.umich.edu env.Command(hh_file, Value(name), 8335076Sgblack@eecs.umich.edu MakeAction(createSimObjectParamStruct, Transform("SO PARAM"))) 8345076Sgblack@eecs.umich.edu env.Depends(hh_file, depends + extra_deps) 8355076Sgblack@eecs.umich.edu 8364732Sgblack@eecs.umich.edu# C++ parameter description files 8375040Sgblack@eecs.umich.eduif GetOption('with_cxx_config'): 8385157Sgblack@eecs.umich.edu for name,simobj in sorted(sim_objects.iteritems()): 8395040Sgblack@eecs.umich.edu py_source = PySource.modules[simobj.__module__] 8405040Sgblack@eecs.umich.edu extra_deps = [ py_source.tnode ] 8415040Sgblack@eecs.umich.edu 8425040Sgblack@eecs.umich.edu cxx_config_hh_file = File('cxx_config/%s.hh' % name) 8435040Sgblack@eecs.umich.edu cxx_config_cc_file = File('cxx_config/%s.cc' % name) 8445040Sgblack@eecs.umich.edu env.Command(cxx_config_hh_file, Value(name), 8455040Sgblack@eecs.umich.edu MakeAction(createSimObjectCxxConfig(True), 8465040Sgblack@eecs.umich.edu Transform("CXXCPRHH"))) 8475040Sgblack@eecs.umich.edu env.Command(cxx_config_cc_file, Value(name), 8485040Sgblack@eecs.umich.edu MakeAction(createSimObjectCxxConfig(False), 8495040Sgblack@eecs.umich.edu Transform("CXXCPRCC"))) 8505040Sgblack@eecs.umich.edu env.Depends(cxx_config_hh_file, depends + extra_deps + 8515040Sgblack@eecs.umich.edu [File('params/%s.hh' % name), File('sim/cxx_config.hh')]) 8525040Sgblack@eecs.umich.edu env.Depends(cxx_config_cc_file, depends + extra_deps + 8535040Sgblack@eecs.umich.edu [cxx_config_hh_file]) 8545040Sgblack@eecs.umich.edu Source(cxx_config_cc_file) 8555040Sgblack@eecs.umich.edu 8565116Sgblack@eecs.umich.edu cxx_config_init_cc_file = File('cxx_config/init.cc') 8574951Sgblack@eecs.umich.edu 8585011Sgblack@eecs.umich.edu def createCxxConfigInitCC(target, source, env): 8595011Sgblack@eecs.umich.edu assert len(target) == 1 and len(source) == 1 8605040Sgblack@eecs.umich.edu 8615040Sgblack@eecs.umich.edu code = code_formatter() 8625040Sgblack@eecs.umich.edu 8635040Sgblack@eecs.umich.edu for name,simobj in sorted(sim_objects.iteritems()): 8645040Sgblack@eecs.umich.edu if not hasattr(simobj, 'abstract') or not simobj.abstract: 8654732Sgblack@eecs.umich.edu code('#include "cxx_config/${name}.hh"') 8665040Sgblack@eecs.umich.edu code() 8675040Sgblack@eecs.umich.edu code('void cxxConfigInit()') 8684823Sgblack@eecs.umich.edu code('{') 8694595Sgblack@eecs.umich.edu code.indent() 8705007Sgblack@eecs.umich.edu for name,simobj in sorted(sim_objects.iteritems()): 8715007Sgblack@eecs.umich.edu not_abstract = not hasattr(simobj, 'abstract') or \ 8725007Sgblack@eecs.umich.edu not simobj.abstract 8735040Sgblack@eecs.umich.edu if not_abstract and 'type' in simobj.__dict__: 8744714Sgblack@eecs.umich.edu code('cxx_config_directory["${name}"] = ' 8755040Sgblack@eecs.umich.edu '${name}CxxConfigParams::makeDirectoryEntry();') 8765040Sgblack@eecs.umich.edu code.dedent() 8774519Sgblack@eecs.umich.edu code('}') 878 code.write(target[0].abspath) 879 880 py_source = PySource.modules[simobj.__module__] 881 extra_deps = [ py_source.tnode ] 882 env.Command(cxx_config_init_cc_file, Value(name), 883 MakeAction(createCxxConfigInitCC, Transform("CXXCINIT"))) 884 cxx_param_hh_files = ["cxx_config/%s.hh" % simobj 885 for name,simobj in sorted(sim_objects.iteritems()) 886 if not hasattr(simobj, 'abstract') or not simobj.abstract] 887 Depends(cxx_config_init_cc_file, cxx_param_hh_files + 888 [File('sim/cxx_config.hh')]) 889 Source(cxx_config_init_cc_file) 890 891# Generate all enum header files 892for name,enum in sorted(all_enums.iteritems()): 893 py_source = PySource.modules[enum.__module__] 894 extra_deps = [ py_source.tnode ] 895 896 cc_file = File('enums/%s.cc' % name) 897 env.Command(cc_file, [Value(name), Value(env['USE_PYTHON'])], 898 MakeAction(createEnumStrings, Transform("ENUM STR"))) 899 env.Depends(cc_file, depends + extra_deps) 900 Source(cc_file) 901 902 hh_file = File('enums/%s.hh' % name) 903 env.Command(hh_file, Value(name), 904 MakeAction(createEnumDecls, Transform("ENUMDECL"))) 905 env.Depends(hh_file, depends + extra_deps) 906 907# Generate SimObject Python bindings wrapper files 908if env['USE_PYTHON']: 909 for name,simobj in sorted(sim_objects.iteritems()): 910 py_source = PySource.modules[simobj.__module__] 911 extra_deps = [ py_source.tnode ] 912 cc_file = File('python/_m5/param_%s.cc' % name) 913 env.Command(cc_file, Value(name), 914 MakeAction(createSimObjectPyBindWrapper, 915 Transform("SO PyBind"))) 916 env.Depends(cc_file, depends + extra_deps) 917 Source(cc_file) 918 919# Build all protocol buffers if we have got protoc and protobuf available 920if env['HAVE_PROTOBUF']: 921 for proto in ProtoBuf.all: 922 # Use both the source and header as the target, and the .proto 923 # file as the source. When executing the protoc compiler, also 924 # specify the proto_path to avoid having the generated files 925 # include the path. 926 env.Command([proto.cc_file, proto.hh_file], proto.tnode, 927 MakeAction('$PROTOC --cpp_out ${TARGET.dir} ' 928 '--proto_path ${SOURCE.dir} $SOURCE', 929 Transform("PROTOC"))) 930 931 # Add the C++ source file 932 Source(proto.cc_file, tags=proto.tags) 933elif ProtoBuf.all: 934 print('Got protobuf to build, but lacks support!') 935 Exit(1) 936 937# 938# Handle debug flags 939# 940def makeDebugFlagCC(target, source, env): 941 assert(len(target) == 1 and len(source) == 1) 942 943 code = code_formatter() 944 945 # delay definition of CompoundFlags until after all the definition 946 # of all constituent SimpleFlags 947 comp_code = code_formatter() 948 949 # file header 950 code(''' 951/* 952 * DO NOT EDIT THIS FILE! Automatically generated by SCons. 953 */ 954 955#include "base/debug.hh" 956 957namespace Debug { 958 959''') 960 961 for name, flag in sorted(source[0].read().iteritems()): 962 n, compound, desc = flag 963 assert n == name 964 965 if not compound: 966 code('SimpleFlag $name("$name", "$desc");') 967 else: 968 comp_code('CompoundFlag $name("$name", "$desc",') 969 comp_code.indent() 970 last = len(compound) - 1 971 for i,flag in enumerate(compound): 972 if i != last: 973 comp_code('&$flag,') 974 else: 975 comp_code('&$flag);') 976 comp_code.dedent() 977 978 code.append(comp_code) 979 code() 980 code('} // namespace Debug') 981 982 code.write(str(target[0])) 983 984def makeDebugFlagHH(target, source, env): 985 assert(len(target) == 1 and len(source) == 1) 986 987 val = eval(source[0].get_contents()) 988 name, compound, desc = val 989 990 code = code_formatter() 991 992 # file header boilerplate 993 code('''\ 994/* 995 * DO NOT EDIT THIS FILE! Automatically generated by SCons. 996 */ 997 998#ifndef __DEBUG_${name}_HH__ 999#define __DEBUG_${name}_HH__ 1000 1001namespace Debug { 1002''') 1003 1004 if compound: 1005 code('class CompoundFlag;') 1006 code('class SimpleFlag;') 1007 1008 if compound: 1009 code('extern CompoundFlag $name;') 1010 for flag in compound: 1011 code('extern SimpleFlag $flag;') 1012 else: 1013 code('extern SimpleFlag $name;') 1014 1015 code(''' 1016} 1017 1018#endif // __DEBUG_${name}_HH__ 1019''') 1020 1021 code.write(str(target[0])) 1022 1023for name,flag in sorted(debug_flags.iteritems()): 1024 n, compound, desc = flag 1025 assert n == name 1026 1027 hh_file = 'debug/%s.hh' % name 1028 env.Command(hh_file, Value(flag), 1029 MakeAction(makeDebugFlagHH, Transform("TRACING", 0))) 1030 1031env.Command('debug/flags.cc', Value(debug_flags), 1032 MakeAction(makeDebugFlagCC, Transform("TRACING", 0))) 1033Source('debug/flags.cc') 1034 1035# version tags 1036tags = \ 1037env.Command('sim/tags.cc', None, 1038 MakeAction('util/cpt_upgrader.py --get-cc-file > $TARGET', 1039 Transform("VER TAGS"))) 1040env.AlwaysBuild(tags) 1041 1042# Embed python files. All .py files that have been indicated by a 1043# PySource() call in a SConscript need to be embedded into the M5 1044# library. To do that, we compile the file to byte code, marshal the 1045# byte code, compress it, and then generate a c++ file that 1046# inserts the result into an array. 1047def embedPyFile(target, source, env): 1048 def c_str(string): 1049 if string is None: 1050 return "0" 1051 return '"%s"' % string 1052 1053 '''Action function to compile a .py into a code object, marshal 1054 it, compress it, and stick it into an asm file so the code appears 1055 as just bytes with a label in the data section''' 1056 1057 src = file(str(source[0]), 'r').read() 1058 1059 pysource = PySource.tnodes[source[0]] 1060 compiled = compile(src, pysource.abspath, 'exec') 1061 marshalled = marshal.dumps(compiled) 1062 compressed = zlib.compress(marshalled) 1063 data = compressed 1064 sym = pysource.symname 1065 1066 code = code_formatter() 1067 code('''\ 1068#include "sim/init.hh" 1069 1070namespace { 1071 1072const uint8_t data_${sym}[] = { 1073''') 1074 code.indent() 1075 step = 16 1076 for i in xrange(0, len(data), step): 1077 x = array.array('B', data[i:i+step]) 1078 code(''.join('%d,' % d for d in x)) 1079 code.dedent() 1080 1081 code('''}; 1082 1083EmbeddedPython embedded_${sym}( 1084 ${{c_str(pysource.arcname)}}, 1085 ${{c_str(pysource.abspath)}}, 1086 ${{c_str(pysource.modpath)}}, 1087 data_${sym}, 1088 ${{len(data)}}, 1089 ${{len(marshalled)}}); 1090 1091} // anonymous namespace 1092''') 1093 code.write(str(target[0])) 1094 1095for source in PySource.all: 1096 env.Command(source.cpp, source.tnode, 1097 MakeAction(embedPyFile, Transform("EMBED PY"))) 1098 Source(source.cpp, tags=source.tags, add_tags='python') 1099 1100######################################################################## 1101# 1102# Define binaries. Each different build type (debug, opt, etc.) gets 1103# a slightly different build environment. 1104# 1105 1106# List of constructed environments to pass back to SConstruct 1107date_source = Source('base/date.cc', tags=[]) 1108 1109gem5_binary = Gem5('gem5') 1110 1111# Function to create a new build environment as clone of current 1112# environment 'env' with modified object suffix and optional stripped 1113# binary. Additional keyword arguments are appended to corresponding 1114# build environment vars. 1115def makeEnv(env, label, objsfx, strip=False, disable_partial=False, **kwargs): 1116 # SCons doesn't know to append a library suffix when there is a '.' in the 1117 # name. Use '_' instead. 1118 libname = 'gem5_' + label 1119 secondary_exename = 'm5.' + label 1120 1121 new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's') 1122 new_env.Label = label 1123 new_env.Append(**kwargs) 1124 1125 lib_sources = Source.all.with_tag('gem5 lib') 1126 1127 # Without Python, leave out all Python content from the library 1128 # builds. The option doesn't affect gem5 built as a program 1129 if GetOption('without_python'): 1130 lib_sources = lib_sources.without_tag('python') 1131 1132 static_objs = [] 1133 shared_objs = [] 1134 1135 for s in lib_sources.with_tag(Source.ungrouped_tag): 1136 static_objs.append(s.static(new_env)) 1137 shared_objs.append(s.shared(new_env)) 1138 1139 for group in Source.source_groups: 1140 srcs = lib_sources.with_tag(Source.link_group_tag(group)) 1141 if not srcs: 1142 continue 1143 1144 group_static = [ s.static(new_env) for s in srcs ] 1145 group_shared = [ s.shared(new_env) for s in srcs ] 1146 1147 # If partial linking is disabled, add these sources to the build 1148 # directly, and short circuit this loop. 1149 if disable_partial: 1150 static_objs.extend(group_static) 1151 shared_objs.extend(group_shared) 1152 continue 1153 1154 # Set up the static partially linked objects. 1155 file_name = new_env.subst("${OBJPREFIX}lib${OBJSUFFIX}.partial") 1156 target = File(joinpath(group, file_name)) 1157 partial = env.PartialStatic(target=target, source=group_static) 1158 static_objs.extend(partial) 1159 1160 # Set up the shared partially linked objects. 1161 file_name = new_env.subst("${SHOBJPREFIX}lib${SHOBJSUFFIX}.partial") 1162 target = File(joinpath(group, file_name)) 1163 partial = env.PartialShared(target=target, source=group_shared) 1164 shared_objs.extend(partial) 1165 1166 static_date = date_source.static(new_env) 1167 new_env.Depends(static_date, static_objs) 1168 static_objs.extend(static_date) 1169 1170 shared_date = date_source.shared(new_env) 1171 new_env.Depends(shared_date, shared_objs) 1172 shared_objs.extend(shared_date) 1173 1174 main_objs = [ s.static(new_env) for s in Source.all.with_tag('main') ] 1175 1176 # First make a library of everything but main() so other programs can 1177 # link against m5. 1178 static_lib = new_env.StaticLibrary(libname, static_objs) 1179 shared_lib = new_env.SharedLibrary(libname, shared_objs) 1180 1181 # Keep track of the object files generated so far so Executables can 1182 # include them. 1183 new_env['STATIC_OBJS'] = static_objs 1184 new_env['SHARED_OBJS'] = shared_objs 1185 new_env['MAIN_OBJS'] = main_objs 1186 1187 new_env['STATIC_LIB'] = static_lib 1188 new_env['SHARED_LIB'] = shared_lib 1189 1190 # Record some settings for building Executables. 1191 new_env['EXE_SUFFIX'] = label 1192 new_env['STRIP_EXES'] = strip 1193 1194 for cls in ExecutableMeta.all: 1195 cls.declare_all(new_env) 1196 1197 new_env.M5Binary = File(gem5_binary.path(new_env)) 1198 1199 new_env.Command(secondary_exename, new_env.M5Binary, 1200 MakeAction('ln $SOURCE $TARGET', Transform("HARDLINK"))) 1201 1202 # Set up regression tests. 1203 SConscript(os.path.join(env.root.abspath, 'tests', 'SConscript'), 1204 variant_dir=Dir('tests').Dir(new_env.Label), 1205 exports={ 'env' : new_env }, duplicate=False) 1206 1207# Start out with the compiler flags common to all compilers, 1208# i.e. they all use -g for opt and -g -pg for prof 1209ccflags = {'debug' : [], 'opt' : ['-g'], 'fast' : [], 'prof' : ['-g', '-pg'], 1210 'perf' : ['-g']} 1211 1212# Start out with the linker flags common to all linkers, i.e. -pg for 1213# prof, and -lprofiler for perf. The -lprofile flag is surrounded by 1214# no-as-needed and as-needed as the binutils linker is too clever and 1215# simply doesn't link to the library otherwise. 1216ldflags = {'debug' : [], 'opt' : [], 'fast' : [], 'prof' : ['-pg'], 1217 'perf' : ['-Wl,--no-as-needed', '-lprofiler', '-Wl,--as-needed']} 1218 1219# For Link Time Optimization, the optimisation flags used to compile 1220# individual files are decoupled from those used at link time 1221# (i.e. you can compile with -O3 and perform LTO with -O0), so we need 1222# to also update the linker flags based on the target. 1223if env['GCC']: 1224 if sys.platform == 'sunos5': 1225 ccflags['debug'] += ['-gstabs+'] 1226 else: 1227 ccflags['debug'] += ['-ggdb3'] 1228 ldflags['debug'] += ['-O0'] 1229 # opt, fast, prof and perf all share the same cc flags, also add 1230 # the optimization to the ldflags as LTO defers the optimization 1231 # to link time 1232 for target in ['opt', 'fast', 'prof', 'perf']: 1233 ccflags[target] += ['-O3'] 1234 ldflags[target] += ['-O3'] 1235 1236 ccflags['fast'] += env['LTO_CCFLAGS'] 1237 ldflags['fast'] += env['LTO_LDFLAGS'] 1238elif env['CLANG']: 1239 ccflags['debug'] += ['-g', '-O0'] 1240 # opt, fast, prof and perf all share the same cc flags 1241 for target in ['opt', 'fast', 'prof', 'perf']: 1242 ccflags[target] += ['-O3'] 1243else: 1244 print('Unknown compiler, please fix compiler options') 1245 Exit(1) 1246 1247 1248# To speed things up, we only instantiate the build environments we 1249# need. We try to identify the needed environment for each target; if 1250# we can't, we fall back on instantiating all the environments just to 1251# be safe. 1252target_types = ['debug', 'opt', 'fast', 'prof', 'perf'] 1253obj2target = {'do': 'debug', 'o': 'opt', 'fo': 'fast', 'po': 'prof', 1254 'gpo' : 'perf'} 1255 1256def identifyTarget(t): 1257 ext = t.split('.')[-1] 1258 if ext in target_types: 1259 return ext 1260 if obj2target.has_key(ext): 1261 return obj2target[ext] 1262 match = re.search(r'/tests/([^/]+)/', t) 1263 if match and match.group(1) in target_types: 1264 return match.group(1) 1265 return 'all' 1266 1267needed_envs = [identifyTarget(target) for target in BUILD_TARGETS] 1268if 'all' in needed_envs: 1269 needed_envs += target_types 1270 1271# Debug binary 1272if 'debug' in needed_envs: 1273 makeEnv(env, 'debug', '.do', 1274 CCFLAGS = Split(ccflags['debug']), 1275 CPPDEFINES = ['DEBUG', 'TRACING_ON=1'], 1276 LINKFLAGS = Split(ldflags['debug'])) 1277 1278# Optimized binary 1279if 'opt' in needed_envs: 1280 makeEnv(env, 'opt', '.o', 1281 CCFLAGS = Split(ccflags['opt']), 1282 CPPDEFINES = ['TRACING_ON=1'], 1283 LINKFLAGS = Split(ldflags['opt'])) 1284 1285# "Fast" binary 1286if 'fast' in needed_envs: 1287 disable_partial = \ 1288 env.get('BROKEN_INCREMENTAL_LTO', False) and \ 1289 GetOption('force_lto') 1290 makeEnv(env, 'fast', '.fo', strip = True, 1291 CCFLAGS = Split(ccflags['fast']), 1292 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1293 LINKFLAGS = Split(ldflags['fast']), 1294 disable_partial=disable_partial) 1295 1296# Profiled binary using gprof 1297if 'prof' in needed_envs: 1298 makeEnv(env, 'prof', '.po', 1299 CCFLAGS = Split(ccflags['prof']), 1300 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1301 LINKFLAGS = Split(ldflags['prof'])) 1302 1303# Profiled binary using google-pprof 1304if 'perf' in needed_envs: 1305 makeEnv(env, 'perf', '.gpo', 1306 CCFLAGS = Split(ccflags['perf']), 1307 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1308 LINKFLAGS = Split(ldflags['perf'])) 1309