SConscript revision 11718:09f8fda798bc
16313Sgblack@eecs.umich.edu# -*- mode:python -*- 214128Sgiacomo.travaglini@arm.com 37093Sgblack@eecs.umich.edu# Copyright (c) 2004-2005 The Regents of The University of Michigan 47093Sgblack@eecs.umich.edu# All rights reserved. 57093Sgblack@eecs.umich.edu# 67093Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 77093Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are 87093Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright 97093Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 107093Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 117093Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 127093Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution; 137093Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its 146313Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from 156313Sgblack@eecs.umich.edu# this software without specific prior written permission. 166313Sgblack@eecs.umich.edu# 176313Sgblack@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 186313Sgblack@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 196313Sgblack@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 206313Sgblack@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 216313Sgblack@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 226313Sgblack@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 236313Sgblack@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 246313Sgblack@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 256313Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 266313Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 276313Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286313Sgblack@eecs.umich.edu# 296313Sgblack@eecs.umich.edu# Authors: Nathan Binkert 306313Sgblack@eecs.umich.edu 316313Sgblack@eecs.umich.eduimport array 326313Sgblack@eecs.umich.eduimport bisect 336313Sgblack@eecs.umich.eduimport imp 346313Sgblack@eecs.umich.eduimport marshal 356313Sgblack@eecs.umich.eduimport os 366313Sgblack@eecs.umich.eduimport re 376313Sgblack@eecs.umich.eduimport sys 386313Sgblack@eecs.umich.eduimport zlib 396313Sgblack@eecs.umich.edu 406313Sgblack@eecs.umich.edufrom os.path import basename, dirname, exists, isdir, isfile, join as joinpath 416313Sgblack@eecs.umich.edu 426313Sgblack@eecs.umich.eduimport SCons 436313Sgblack@eecs.umich.edu 447404SAli.Saidi@ARM.com# This file defines how to build a particular configuration of gem5 456313Sgblack@eecs.umich.edu# based on variable settings in the 'env' build environment. 4610461SAndreas.Sandberg@ARM.com 4712479SCurtis.Dunham@arm.comImport('*') 486333Sgblack@eecs.umich.edu 4910037SARM gem5 Developers# Children need to see the environment 507404SAli.Saidi@ARM.comExport('env') 516313Sgblack@eecs.umich.edu 5212109SRekai.GonzalezAlberquilla@arm.combuild_env = [(opt, env[opt]) for opt in export_vars] 538232Snate@binkert.org 5412109SRekai.GonzalezAlberquilla@arm.comfrom m5.util import code_formatter, compareVersions 559384SAndreas.Sandberg@arm.com 5611165SRekai.GonzalezAlberquilla@arm.com######################################################################## 576313Sgblack@eecs.umich.edu# Code for adding source files of various types 589384SAndreas.Sandberg@arm.com# 5910461SAndreas.Sandberg@ARM.com# When specifying a source file of some type, a set of guards can be 606333Sgblack@eecs.umich.edu# specified for that file. When get() is used to find the files, if 616313Sgblack@eecs.umich.edu# get specifies a set of filters, only files that match those filters 626313Sgblack@eecs.umich.edu# will be accepted (unspecified filters on files are assumed to be 636313Sgblack@eecs.umich.edu# false). Current filters are: 646313Sgblack@eecs.umich.edu# main -- specifies the gem5 main() function 656313Sgblack@eecs.umich.edu# skip_lib -- do not put this file into the gem5 library 669384SAndreas.Sandberg@arm.com# skip_no_python -- do not put this file into a no_python library 676313Sgblack@eecs.umich.edu# as it embeds compiled Python 686313Sgblack@eecs.umich.edu# <unittest> -- unit tests use filters based on the unit test name 6910037SARM gem5 Developers# 7010037SARM gem5 Developers# A parent can now be specified for a source file and default filter 7110037SARM gem5 Developers# values will be retrieved recursively from parents (children override 7211165SRekai.GonzalezAlberquilla@arm.com# parents). 7311165SRekai.GonzalezAlberquilla@arm.com# 7412109SRekai.GonzalezAlberquilla@arm.comclass SourceMeta(type): 7511165SRekai.GonzalezAlberquilla@arm.com '''Meta class for source files that keeps track of all files of a 7610461SAndreas.Sandberg@ARM.com particular type and has a get function for finding all functions 7710461SAndreas.Sandberg@ARM.com of a certain type that match a set of guards''' 7810461SAndreas.Sandberg@ARM.com def __init__(cls, name, bases, dict): 7910461SAndreas.Sandberg@ARM.com super(SourceMeta, cls).__init__(name, bases, dict) 8010461SAndreas.Sandberg@ARM.com cls.all = [] 8110461SAndreas.Sandberg@ARM.com 8210844Sandreas.sandberg@arm.com def get(cls, **guards): 8310844Sandreas.sandberg@arm.com '''Find all files that match the specified guards. If a source 8410844Sandreas.sandberg@arm.com file does not specify a flag, the default is False''' 8513531Sjairo.balart@metempsy.com for src in cls.all: 8613531Sjairo.balart@metempsy.com for flag,value in guards.iteritems(): 8713531Sjairo.balart@metempsy.com # if the flag is found and has a different value, skip 8810037SARM gem5 Developers # this file 8911771SCurtis.Dunham@arm.com if src.all_guards.get(flag, False) != value: 9010037SARM gem5 Developers break 9110037SARM gem5 Developers else: 9210037SARM gem5 Developers yield src 9313173Sgiacomo.travaglini@arm.com 9410037SARM gem5 Developersclass SourceFile(object): 9513531Sjairo.balart@metempsy.com '''Base object that encapsulates the notion of a source file. 9613114Sgiacomo.travaglini@arm.com This includes, the source node, target node, various manipulations 9713759Sgiacomo.gabrielli@arm.com of those. A source file also specifies a set of guards which 9814133Sjordi.vaquero@metempsy.com describing which builds the source file applies to. A parent can 9914128Sgiacomo.travaglini@arm.com also be specified to get default guards from''' 10013759Sgiacomo.gabrielli@arm.com __metaclass__ = SourceMeta 10113759Sgiacomo.gabrielli@arm.com def __init__(self, source, parent=None, **guards): 10213759Sgiacomo.gabrielli@arm.com self.guards = guards 10310037SARM gem5 Developers self.parent = parent 10412714Sgiacomo.travaglini@arm.com 10512714Sgiacomo.travaglini@arm.com tnode = source 10612714Sgiacomo.travaglini@arm.com if not isinstance(source, SCons.Node.FS.File): 10712714Sgiacomo.travaglini@arm.com tnode = File(source) 10812714Sgiacomo.travaglini@arm.com 10912714Sgiacomo.travaglini@arm.com self.tnode = tnode 11014000Sgiacomo.travaglini@arm.com self.snode = tnode.srcnode() 11114000Sgiacomo.travaglini@arm.com 11212478SCurtis.Dunham@arm.com for base in type(self).__mro__: 11310037SARM gem5 Developers if issubclass(base, SourceFile): 11412477SCurtis.Dunham@arm.com base.all.append(self) 11512477SCurtis.Dunham@arm.com 11612478SCurtis.Dunham@arm.com @property 11712478SCurtis.Dunham@arm.com def filename(self): 11812478SCurtis.Dunham@arm.com return str(self.tnode) 11912478SCurtis.Dunham@arm.com 12012478SCurtis.Dunham@arm.com @property 12112478SCurtis.Dunham@arm.com def dirname(self): 12212478SCurtis.Dunham@arm.com return dirname(self.filename) 12312478SCurtis.Dunham@arm.com 12412478SCurtis.Dunham@arm.com @property 12512478SCurtis.Dunham@arm.com def basename(self): 12612478SCurtis.Dunham@arm.com return basename(self.filename) 12712478SCurtis.Dunham@arm.com 12812478SCurtis.Dunham@arm.com @property 12912478SCurtis.Dunham@arm.com def extname(self): 13012478SCurtis.Dunham@arm.com index = self.basename.rfind('.') 13112478SCurtis.Dunham@arm.com if index <= 0: 13210037SARM gem5 Developers # dot files aren't extensions 13310037SARM gem5 Developers return self.basename, None 13412477SCurtis.Dunham@arm.com 13512479SCurtis.Dunham@arm.com return self.basename[:index], self.basename[index+1:] 13612477SCurtis.Dunham@arm.com 13712477SCurtis.Dunham@arm.com @property 13812477SCurtis.Dunham@arm.com def all_guards(self): 13912479SCurtis.Dunham@arm.com '''find all guards for this object getting default values 14012477SCurtis.Dunham@arm.com recursively from its parents''' 14112477SCurtis.Dunham@arm.com guards = {} 14212477SCurtis.Dunham@arm.com if self.parent: 14312477SCurtis.Dunham@arm.com guards.update(self.parent.guards) 14412477SCurtis.Dunham@arm.com guards.update(self.guards) 14512477SCurtis.Dunham@arm.com return guards 14612477SCurtis.Dunham@arm.com 14712478SCurtis.Dunham@arm.com def __lt__(self, other): return self.filename < other.filename 14812478SCurtis.Dunham@arm.com def __le__(self, other): return self.filename <= other.filename 14912478SCurtis.Dunham@arm.com def __gt__(self, other): return self.filename > other.filename 15012478SCurtis.Dunham@arm.com def __ge__(self, other): return self.filename >= other.filename 15112478SCurtis.Dunham@arm.com def __eq__(self, other): return self.filename == other.filename 15212478SCurtis.Dunham@arm.com def __ne__(self, other): return self.filename != other.filename 15312478SCurtis.Dunham@arm.com 15412478SCurtis.Dunham@arm.com @staticmethod 15512478SCurtis.Dunham@arm.com def done(): 15612478SCurtis.Dunham@arm.com def disabled(cls, name, *ignored): 15712478SCurtis.Dunham@arm.com raise RuntimeError("Additional SourceFile '%s'" % name,\ 15812478SCurtis.Dunham@arm.com "declared, but targets deps are already fixed.") 15912478SCurtis.Dunham@arm.com SourceFile.__init__ = disabled 16012478SCurtis.Dunham@arm.com 16112478SCurtis.Dunham@arm.com 16212478SCurtis.Dunham@arm.comclass Source(SourceFile): 16312479SCurtis.Dunham@arm.com '''Add a c/c++ source file to the build''' 16412479SCurtis.Dunham@arm.com def __init__(self, source, Werror=True, swig=False, **guards): 16512479SCurtis.Dunham@arm.com '''specify the source file, and any guards''' 16612479SCurtis.Dunham@arm.com super(Source, self).__init__(source, **guards) 16712479SCurtis.Dunham@arm.com 16812479SCurtis.Dunham@arm.com self.Werror = Werror 16912479SCurtis.Dunham@arm.com self.swig = swig 17012479SCurtis.Dunham@arm.com 17112479SCurtis.Dunham@arm.comclass PySource(SourceFile): 17212479SCurtis.Dunham@arm.com '''Add a python source file to the named package''' 17312479SCurtis.Dunham@arm.com invalid_sym_char = re.compile('[^A-z0-9_]') 17412479SCurtis.Dunham@arm.com modules = {} 17512479SCurtis.Dunham@arm.com tnodes = {} 17612479SCurtis.Dunham@arm.com symnames = {} 17712479SCurtis.Dunham@arm.com 17812479SCurtis.Dunham@arm.com def __init__(self, package, source, **guards): 17912479SCurtis.Dunham@arm.com '''specify the python package, the source file, and any guards''' 18012479SCurtis.Dunham@arm.com super(PySource, self).__init__(source, **guards) 18112479SCurtis.Dunham@arm.com 18212479SCurtis.Dunham@arm.com modname,ext = self.extname 18312479SCurtis.Dunham@arm.com assert ext == 'py' 18412479SCurtis.Dunham@arm.com 18512479SCurtis.Dunham@arm.com if package: 18614242Sgiacomo.travaglini@arm.com path = package.split('.') 18714242Sgiacomo.travaglini@arm.com else: 18814242Sgiacomo.travaglini@arm.com path = [] 18914242Sgiacomo.travaglini@arm.com 19012479SCurtis.Dunham@arm.com modpath = path[:] 19112479SCurtis.Dunham@arm.com if modname != '__init__': 19212479SCurtis.Dunham@arm.com modpath += [ modname ] 19312479SCurtis.Dunham@arm.com modpath = '.'.join(modpath) 19412479SCurtis.Dunham@arm.com 19512479SCurtis.Dunham@arm.com arcpath = path + [ self.basename ] 19612479SCurtis.Dunham@arm.com abspath = self.snode.abspath 19712479SCurtis.Dunham@arm.com if not exists(abspath): 19812479SCurtis.Dunham@arm.com abspath = self.tnode.abspath 19912479SCurtis.Dunham@arm.com 20012479SCurtis.Dunham@arm.com self.package = package 20112479SCurtis.Dunham@arm.com self.modname = modname 20212479SCurtis.Dunham@arm.com self.modpath = modpath 20312479SCurtis.Dunham@arm.com self.arcname = joinpath(*arcpath) 20412479SCurtis.Dunham@arm.com self.abspath = abspath 20512479SCurtis.Dunham@arm.com self.compiled = File(self.filename + 'c') 20612479SCurtis.Dunham@arm.com self.cpp = File(self.filename + '.cc') 20712479SCurtis.Dunham@arm.com self.symname = PySource.invalid_sym_char.sub('_', modpath) 20812479SCurtis.Dunham@arm.com 20912479SCurtis.Dunham@arm.com PySource.modules[modpath] = self 21012479SCurtis.Dunham@arm.com PySource.tnodes[self.tnode] = self 21112479SCurtis.Dunham@arm.com PySource.symnames[self.symname] = self 21212479SCurtis.Dunham@arm.com 21312479SCurtis.Dunham@arm.comclass SimObject(PySource): 21412479SCurtis.Dunham@arm.com '''Add a SimObject python file as a python source object and add 21512479SCurtis.Dunham@arm.com it to a list of sim object modules''' 21612479SCurtis.Dunham@arm.com 21712479SCurtis.Dunham@arm.com fixed = False 21812479SCurtis.Dunham@arm.com modnames = [] 21912479SCurtis.Dunham@arm.com 22012479SCurtis.Dunham@arm.com def __init__(self, source, **guards): 22112479SCurtis.Dunham@arm.com '''Specify the source file and any guards (automatically in 22212479SCurtis.Dunham@arm.com the m5.objects package)''' 22312479SCurtis.Dunham@arm.com super(SimObject, self).__init__('m5.objects', source, **guards) 22412479SCurtis.Dunham@arm.com if self.fixed: 22512668Sgiacomo.travaglini@arm.com raise AttributeError, "Too late to call SimObject now." 22612668Sgiacomo.travaglini@arm.com 22712668Sgiacomo.travaglini@arm.com bisect.insort_right(SimObject.modnames, self.modname) 22812668Sgiacomo.travaglini@arm.com 22912668Sgiacomo.travaglini@arm.comclass SwigSource(SourceFile): 23012479SCurtis.Dunham@arm.com '''Add a swig file to build''' 23112479SCurtis.Dunham@arm.com 23212479SCurtis.Dunham@arm.com def __init__(self, package, source, **guards): 23312479SCurtis.Dunham@arm.com '''Specify the python package, the source file, and any guards''' 23412479SCurtis.Dunham@arm.com super(SwigSource, self).__init__(source, skip_no_python=True, **guards) 23512479SCurtis.Dunham@arm.com 23612479SCurtis.Dunham@arm.com modname,ext = self.extname 23712479SCurtis.Dunham@arm.com assert ext == 'i' 23812479SCurtis.Dunham@arm.com 23912479SCurtis.Dunham@arm.com self.package = package 24012479SCurtis.Dunham@arm.com self.module = modname 24112479SCurtis.Dunham@arm.com cc_file = joinpath(self.dirname, modname + '_wrap.cc') 24212479SCurtis.Dunham@arm.com py_file = joinpath(self.dirname, modname + '.py') 24312668Sgiacomo.travaglini@arm.com 24412668Sgiacomo.travaglini@arm.com self.cc_source = Source(cc_file, swig=True, parent=self, **guards) 24512668Sgiacomo.travaglini@arm.com self.py_source = PySource(package, py_file, parent=self, **guards) 24612668Sgiacomo.travaglini@arm.com 24712668Sgiacomo.travaglini@arm.comclass ProtoBuf(SourceFile): 24813395Sgiacomo.travaglini@arm.com '''Add a Protocol Buffer to build''' 24913395Sgiacomo.travaglini@arm.com 25013395Sgiacomo.travaglini@arm.com def __init__(self, source, **guards): 25113395Sgiacomo.travaglini@arm.com '''Specify the source file, and any guards''' 25213395Sgiacomo.travaglini@arm.com super(ProtoBuf, self).__init__(source, **guards) 25312479SCurtis.Dunham@arm.com 25412479SCurtis.Dunham@arm.com # Get the file name and the extension 25512479SCurtis.Dunham@arm.com modname,ext = self.extname 25612479SCurtis.Dunham@arm.com assert ext == 'proto' 25712479SCurtis.Dunham@arm.com 25812479SCurtis.Dunham@arm.com # Currently, we stick to generating the C++ headers, so we 25912479SCurtis.Dunham@arm.com # only need to track the source and header. 26012479SCurtis.Dunham@arm.com self.cc_file = File(modname + '.pb.cc') 26112479SCurtis.Dunham@arm.com self.hh_file = File(modname + '.pb.h') 26212479SCurtis.Dunham@arm.com 26312479SCurtis.Dunham@arm.comclass UnitTest(object): 26412479SCurtis.Dunham@arm.com '''Create a UnitTest''' 26512479SCurtis.Dunham@arm.com 26612479SCurtis.Dunham@arm.com all = [] 26712479SCurtis.Dunham@arm.com def __init__(self, target, *sources, **kwargs): 26812479SCurtis.Dunham@arm.com '''Specify the target name and any sources. Sources that are 26912479SCurtis.Dunham@arm.com not SourceFiles are evalued with Source(). All files are 27012479SCurtis.Dunham@arm.com guarded with a guard of the same name as the UnitTest 27112479SCurtis.Dunham@arm.com target.''' 27212479SCurtis.Dunham@arm.com 27312479SCurtis.Dunham@arm.com srcs = [] 27412479SCurtis.Dunham@arm.com for src in sources: 27512479SCurtis.Dunham@arm.com if not isinstance(src, SourceFile): 27612479SCurtis.Dunham@arm.com src = Source(src, skip_lib=True) 27712479SCurtis.Dunham@arm.com src.guards[target] = True 27812479SCurtis.Dunham@arm.com srcs.append(src) 27912479SCurtis.Dunham@arm.com 28012479SCurtis.Dunham@arm.com self.sources = srcs 28112479SCurtis.Dunham@arm.com self.target = target 28212479SCurtis.Dunham@arm.com self.main = kwargs.get('main', False) 28312479SCurtis.Dunham@arm.com UnitTest.all.append(self) 28412479SCurtis.Dunham@arm.com 28512479SCurtis.Dunham@arm.com# Children should have access 28612479SCurtis.Dunham@arm.comExport('Source') 28712479SCurtis.Dunham@arm.comExport('PySource') 28812479SCurtis.Dunham@arm.comExport('SimObject') 28912479SCurtis.Dunham@arm.comExport('SwigSource') 29012479SCurtis.Dunham@arm.comExport('ProtoBuf') 29112479SCurtis.Dunham@arm.comExport('UnitTest') 29212479SCurtis.Dunham@arm.com 29312479SCurtis.Dunham@arm.com######################################################################## 29412479SCurtis.Dunham@arm.com# 29512479SCurtis.Dunham@arm.com# Debug Flags 29612479SCurtis.Dunham@arm.com# 29712479SCurtis.Dunham@arm.comdebug_flags = {} 29812479SCurtis.Dunham@arm.comdef DebugFlag(name, desc=None): 29912479SCurtis.Dunham@arm.com if name in debug_flags: 30012479SCurtis.Dunham@arm.com raise AttributeError, "Flag %s already specified" % name 30112479SCurtis.Dunham@arm.com debug_flags[name] = (name, (), desc) 30212479SCurtis.Dunham@arm.com 30312479SCurtis.Dunham@arm.comdef CompoundFlag(name, flags, desc=None): 30412479SCurtis.Dunham@arm.com if name in debug_flags: 30512479SCurtis.Dunham@arm.com raise AttributeError, "Flag %s already specified" % name 30612479SCurtis.Dunham@arm.com 30712479SCurtis.Dunham@arm.com compound = tuple(flags) 30812479SCurtis.Dunham@arm.com debug_flags[name] = (name, compound, desc) 30912479SCurtis.Dunham@arm.com 31012479SCurtis.Dunham@arm.comExport('DebugFlag') 31112479SCurtis.Dunham@arm.comExport('CompoundFlag') 31212479SCurtis.Dunham@arm.com 31312479SCurtis.Dunham@arm.com######################################################################## 31412479SCurtis.Dunham@arm.com# 31512479SCurtis.Dunham@arm.com# Set some compiler variables 31612479SCurtis.Dunham@arm.com# 31712479SCurtis.Dunham@arm.com 31812479SCurtis.Dunham@arm.com# Include file paths are rooted in this directory. SCons will 31912479SCurtis.Dunham@arm.com# automatically expand '.' to refer to both the source directory and 32012479SCurtis.Dunham@arm.com# the corresponding build directory to pick up generated include 32112479SCurtis.Dunham@arm.com# files. 32212479SCurtis.Dunham@arm.comenv.Append(CPPPATH=Dir('.')) 32312479SCurtis.Dunham@arm.com 32412479SCurtis.Dunham@arm.comfor extra_dir in extras_dir_list: 32512479SCurtis.Dunham@arm.com env.Append(CPPPATH=Dir(extra_dir)) 32612479SCurtis.Dunham@arm.com 32712479SCurtis.Dunham@arm.com# Workaround for bug in SCons version > 0.97d20071212 32812479SCurtis.Dunham@arm.com# Scons bug id: 2006 gem5 Bug id: 308 32912479SCurtis.Dunham@arm.comfor root, dirs, files in os.walk(base_dir, topdown=True): 33012479SCurtis.Dunham@arm.com Dir(root[len(base_dir) + 1:]) 33112479SCurtis.Dunham@arm.com 33212479SCurtis.Dunham@arm.com######################################################################## 33312479SCurtis.Dunham@arm.com# 33412479SCurtis.Dunham@arm.com# Walk the tree and execute all SConscripts in subdirectories 33512479SCurtis.Dunham@arm.com# 33612479SCurtis.Dunham@arm.com 33712479SCurtis.Dunham@arm.comhere = Dir('.').srcnode().abspath 33812479SCurtis.Dunham@arm.comfor root, dirs, files in os.walk(base_dir, topdown=True): 33912479SCurtis.Dunham@arm.com if root == here: 34012479SCurtis.Dunham@arm.com # we don't want to recurse back into this SConscript 34112479SCurtis.Dunham@arm.com continue 34212479SCurtis.Dunham@arm.com 34312479SCurtis.Dunham@arm.com if 'SConscript' in files: 34412479SCurtis.Dunham@arm.com build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:]) 34512479SCurtis.Dunham@arm.com SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) 34612479SCurtis.Dunham@arm.com 34712479SCurtis.Dunham@arm.comfor extra_dir in extras_dir_list: 34812479SCurtis.Dunham@arm.com prefix_len = len(dirname(extra_dir)) + 1 34912479SCurtis.Dunham@arm.com 35012479SCurtis.Dunham@arm.com # Also add the corresponding build directory to pick up generated 35112479SCurtis.Dunham@arm.com # include files. 35212479SCurtis.Dunham@arm.com env.Append(CPPPATH=Dir(joinpath(env['BUILDDIR'], extra_dir[prefix_len:]))) 35312479SCurtis.Dunham@arm.com 35412479SCurtis.Dunham@arm.com for root, dirs, files in os.walk(extra_dir, topdown=True): 35512479SCurtis.Dunham@arm.com # if build lives in the extras directory, don't walk down it 35612479SCurtis.Dunham@arm.com if 'build' in dirs: 35712479SCurtis.Dunham@arm.com dirs.remove('build') 35812479SCurtis.Dunham@arm.com 35912479SCurtis.Dunham@arm.com if 'SConscript' in files: 36012479SCurtis.Dunham@arm.com build_dir = joinpath(env['BUILDDIR'], root[prefix_len:]) 36112479SCurtis.Dunham@arm.com SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) 36212479SCurtis.Dunham@arm.com 36312479SCurtis.Dunham@arm.comfor opt in export_vars: 36412479SCurtis.Dunham@arm.com env.ConfigFile(opt) 36512479SCurtis.Dunham@arm.com 36612479SCurtis.Dunham@arm.comdef makeTheISA(source, target, env): 36712479SCurtis.Dunham@arm.com isas = [ src.get_contents() for src in source ] 36810037SARM gem5 Developers target_isa = env['TARGET_ISA'] 36910037SARM gem5 Developers def define(isa): 37012477SCurtis.Dunham@arm.com return isa.upper() + '_ISA' 37112479SCurtis.Dunham@arm.com 37212479SCurtis.Dunham@arm.com def namespace(isa): 37312477SCurtis.Dunham@arm.com return isa[0].upper() + isa[1:].lower() + 'ISA' 37410037SARM gem5 Developers 37512477SCurtis.Dunham@arm.com 37610037SARM gem5 Developers code = code_formatter() 37713581Sgabeblack@google.com code('''\ 3786718Sgblack@eecs.umich.edu#ifndef __CONFIG_THE_ISA_HH__ 3796718Sgblack@eecs.umich.edu#define __CONFIG_THE_ISA_HH__ 3806718Sgblack@eecs.umich.edu 3816718Sgblack@eecs.umich.edu''') 3826718Sgblack@eecs.umich.edu 38310037SARM gem5 Developers # create defines for the preprocessing and compile-time determination 38410037SARM gem5 Developers for i,isa in enumerate(isas): 38510037SARM gem5 Developers code('#define $0 $1', define(isa), i + 1) 38610037SARM gem5 Developers code() 38710037SARM gem5 Developers 38810037SARM gem5 Developers # create an enum for any run-time determination of the ISA, we 38910037SARM gem5 Developers # reuse the same name as the namespaces 39010037SARM gem5 Developers code('enum class Arch {') 39110037SARM gem5 Developers for i,isa in enumerate(isas): 39210037SARM gem5 Developers if i + 1 == len(isas): 39310037SARM gem5 Developers code(' $0 = $1', namespace(isa), define(isa)) 39410037SARM gem5 Developers else: 39510037SARM gem5 Developers code(' $0 = $1,', namespace(isa), define(isa)) 39610037SARM gem5 Developers code('};') 39710037SARM gem5 Developers 39810037SARM gem5 Developers code(''' 39910037SARM gem5 Developers 40010037SARM gem5 Developers#define THE_ISA ${{define(target_isa)}} 40110037SARM gem5 Developers#define TheISA ${{namespace(target_isa)}} 40210037SARM gem5 Developers#define THE_ISA_STR "${{target_isa}}" 40310037SARM gem5 Developers 40410037SARM gem5 Developers#endif // __CONFIG_THE_ISA_HH__''') 40510037SARM gem5 Developers 40610037SARM gem5 Developers code.write(str(target[0])) 40710037SARM gem5 Developers 40810037SARM gem5 Developersenv.Command('config/the_isa.hh', map(Value, all_isa_list), 40910037SARM gem5 Developers MakeAction(makeTheISA, Transform("CFG ISA", 0))) 41010037SARM gem5 Developers 41110037SARM gem5 Developersdef makeTheGPUISA(source, target, env): 41210037SARM gem5 Developers isas = [ src.get_contents() for src in source ] 41310037SARM gem5 Developers target_gpu_isa = env['TARGET_GPU_ISA'] 41410037SARM gem5 Developers def define(isa): 4156718Sgblack@eecs.umich.edu return isa.upper() + '_ISA' 4166718Sgblack@eecs.umich.edu 4176313Sgblack@eecs.umich.edu def namespace(isa): 41810844Sandreas.sandberg@arm.com return isa[0].upper() + isa[1:].lower() + 'ISA' 41913531Sjairo.balart@metempsy.com 42010037SARM gem5 Developers 42110037SARM gem5 Developers code = code_formatter() 42210037SARM gem5 Developers code('''\ 42310037SARM gem5 Developers#ifndef __CONFIG_THE_GPU_ISA_HH__ 42410037SARM gem5 Developers#define __CONFIG_THE_GPU_ISA_HH__ 42510037SARM gem5 Developers 42610037SARM gem5 Developers''') 42710037SARM gem5 Developers 42810037SARM gem5 Developers # create defines for the preprocessing and compile-time determination 42910037SARM gem5 Developers for i,isa in enumerate(isas): 43010037SARM gem5 Developers code('#define $0 $1', define(isa), i + 1) 43110037SARM gem5 Developers code() 43210037SARM gem5 Developers 4336313Sgblack@eecs.umich.edu # create an enum for any run-time determination of the ISA, we 4347427Sgblack@eecs.umich.edu # reuse the same name as the namespaces 43513114Sgiacomo.travaglini@arm.com code('enum class GPUArch {') 43613114Sgiacomo.travaglini@arm.com for i,isa in enumerate(isas): 43713393Sgiacomo.travaglini@arm.com if i + 1 == len(isas): 43810037SARM gem5 Developers code(' $0 = $1', namespace(isa), define(isa)) 43913114Sgiacomo.travaglini@arm.com else: 44013114Sgiacomo.travaglini@arm.com code(' $0 = $1,', namespace(isa), define(isa)) 4416313Sgblack@eecs.umich.edu code('};') 44213114Sgiacomo.travaglini@arm.com 44313581Sgabeblack@google.com code(''' 44413581Sgabeblack@google.com 44513582Sgabeblack@google.com#define THE_GPU_ISA ${{define(target_gpu_isa)}} 44613582Sgabeblack@google.com#define TheGpuISA ${{namespace(target_gpu_isa)}} 4476313Sgblack@eecs.umich.edu#define THE_GPU_ISA_STR "${{target_gpu_isa}}" 44812106SRekai.GonzalezAlberquilla@arm.com 44912106SRekai.GonzalezAlberquilla@arm.com#endif // __CONFIG_THE_GPU_ISA_HH__''') 45012106SRekai.GonzalezAlberquilla@arm.com 45112106SRekai.GonzalezAlberquilla@arm.com code.write(str(target[0])) 45212106SRekai.GonzalezAlberquilla@arm.com 45312106SRekai.GonzalezAlberquilla@arm.comenv.Command('config/the_gpu_isa.hh', map(Value, all_gpu_isa_list), 45412106SRekai.GonzalezAlberquilla@arm.com MakeAction(makeTheGPUISA, Transform("CFG ISA", 0))) 45512106SRekai.GonzalezAlberquilla@arm.com 45612109SRekai.GonzalezAlberquilla@arm.com######################################################################## 45712109SRekai.GonzalezAlberquilla@arm.com# 45812109SRekai.GonzalezAlberquilla@arm.com# Prevent any SimObjects from being added after this point, they 45913545Sgiacomo.travaglini@arm.com# should all have been added in the SConscripts above 46013545Sgiacomo.travaglini@arm.com# 46113610Sgiacomo.gabrielli@arm.comSimObject.fixed = True 46213610Sgiacomo.gabrielli@arm.com 46313610Sgiacomo.gabrielli@arm.comclass DictImporter(object): 46412106SRekai.GonzalezAlberquilla@arm.com '''This importer takes a dictionary of arbitrary module names that 46512106SRekai.GonzalezAlberquilla@arm.com map to arbitrary filenames.''' 46612106SRekai.GonzalezAlberquilla@arm.com def __init__(self, modules): 46712106SRekai.GonzalezAlberquilla@arm.com self.modules = modules 46812106SRekai.GonzalezAlberquilla@arm.com self.installed = set() 46912106SRekai.GonzalezAlberquilla@arm.com 47012106SRekai.GonzalezAlberquilla@arm.com def __del__(self): 47112106SRekai.GonzalezAlberquilla@arm.com self.unload() 4726313Sgblack@eecs.umich.edu 47310035Sandreas.hansson@arm.com def unload(self): 4746313Sgblack@eecs.umich.edu import sys 4756718Sgblack@eecs.umich.edu for module in self.installed: 4766718Sgblack@eecs.umich.edu del sys.modules[module] 4776718Sgblack@eecs.umich.edu self.installed = set() 4786726Sgblack@eecs.umich.edu 4796726Sgblack@eecs.umich.edu def find_module(self, fullname, path): 48010037SARM gem5 Developers if fullname == 'm5.defines': 48110037SARM gem5 Developers return self 48210037SARM gem5 Developers 48310037SARM gem5 Developers if fullname == 'm5.objects': 48410037SARM gem5 Developers return self 48510037SARM gem5 Developers 48610037SARM gem5 Developers if fullname.startswith('m5.internal'): 48710037SARM gem5 Developers return None 48810037SARM gem5 Developers 48911574SCurtis.Dunham@arm.com source = self.modules.get(fullname, None) 49011574SCurtis.Dunham@arm.com if source is not None and fullname.startswith('m5.objects'): 49110037SARM gem5 Developers return self 49210037SARM gem5 Developers 49310037SARM gem5 Developers return None 49410037SARM gem5 Developers 49510037SARM gem5 Developers def load_module(self, fullname): 49610037SARM gem5 Developers mod = imp.new_module(fullname) 49713020Sshunhsingou@google.com sys.modules[fullname] = mod 49810037SARM gem5 Developers self.installed.add(fullname) 4996718Sgblack@eecs.umich.edu 50010037SARM gem5 Developers mod.__loader__ = self 5016718Sgblack@eecs.umich.edu if fullname == 'm5.objects': 5026313Sgblack@eecs.umich.edu mod.__path__ = fullname.split('.') 5036313Sgblack@eecs.umich.edu return mod 5046313Sgblack@eecs.umich.edu 50510035Sandreas.hansson@arm.com if fullname == 'm5.defines': 5066313Sgblack@eecs.umich.edu mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env) 50710338SCurtis.Dunham@arm.com return mod 5086313Sgblack@eecs.umich.edu 5096313Sgblack@eecs.umich.edu source = self.modules[fullname] 5106313Sgblack@eecs.umich.edu if source.modname == '__init__': 5119920Syasuko.eckert@amd.com mod.__path__ = source.modpath 51212109SRekai.GonzalezAlberquilla@arm.com mod.__file__ = source.abspath 51312109SRekai.GonzalezAlberquilla@arm.com 51412109SRekai.GonzalezAlberquilla@arm.com exec file(source.abspath, 'r') in mod.__dict__ 51512109SRekai.GonzalezAlberquilla@arm.com 51612109SRekai.GonzalezAlberquilla@arm.com return mod 51712109SRekai.GonzalezAlberquilla@arm.com 51812109SRekai.GonzalezAlberquilla@arm.comimport m5.SimObject 51912109SRekai.GonzalezAlberquilla@arm.comimport m5.params 52012109SRekai.GonzalezAlberquilla@arm.comfrom m5.util import code_formatter 52112109SRekai.GonzalezAlberquilla@arm.com 52212109SRekai.GonzalezAlberquilla@arm.comm5.SimObject.clear() 52312109SRekai.GonzalezAlberquilla@arm.comm5.params.clear() 52412109SRekai.GonzalezAlberquilla@arm.com 52512109SRekai.GonzalezAlberquilla@arm.com# install the python importer so we can grab stuff from the source 52613610Sgiacomo.gabrielli@arm.com# tree itself. We can't have SimObjects added after this point or 52713610Sgiacomo.gabrielli@arm.com# else we won't know about them for the rest of the stuff. 52813610Sgiacomo.gabrielli@arm.comimporter = DictImporter(PySource.modules) 52913610Sgiacomo.gabrielli@arm.comsys.meta_path[0:0] = [ importer ] 53013610Sgiacomo.gabrielli@arm.com 53113610Sgiacomo.gabrielli@arm.com# import all sim objects so we can populate the all_objects list 53213610Sgiacomo.gabrielli@arm.com# make sure that we're working with a list, then let's sort it 53310035Sandreas.hansson@arm.comfor modname in SimObject.modnames: 5349920Syasuko.eckert@amd.com exec('from m5.objects import %s' % modname) 53510338SCurtis.Dunham@arm.com 5369920Syasuko.eckert@amd.com# we need to unload all of the currently imported modules so that they 5379920Syasuko.eckert@amd.com# will be re-imported the next time the sconscript is run 5389920Syasuko.eckert@amd.comimporter.unload() 5397614Sminkyu.jeong@arm.comsys.meta_path.remove(importer) 54010035Sandreas.hansson@arm.com 5417614Sminkyu.jeong@arm.comsim_objects = m5.SimObject.allClasses 54210338SCurtis.Dunham@arm.comall_enums = m5.params.allEnums 54310037SARM gem5 Developers 54410037SARM gem5 Developersif m5.SimObject.noCxxHeader: 5457614Sminkyu.jeong@arm.com print >> sys.stderr, \ 5467614Sminkyu.jeong@arm.com "warning: At least one SimObject lacks a header specification. " \ 5477614Sminkyu.jeong@arm.com "This can cause unexpected results in the generated SWIG " \ 54810037SARM gem5 Developers "wrappers." 54910037SARM gem5 Developers 55010037SARM gem5 Developers# Find param types that need to be explicitly wrapped with swig. 55110037SARM gem5 Developers# These will be recognized because the ParamDesc will have a 55210037SARM gem5 Developers# swig_decl() method. Most param types are based on types that don't 55310037SARM gem5 Developers# need this, either because they're based on native types (like Int) 55410037SARM gem5 Developers# or because they're SimObjects (which get swigged independently). 55510037SARM gem5 Developers# For now the only things handled here are VectorParam types. 55610037SARM gem5 Developersparams_to_swig = {} 55710037SARM gem5 Developersfor name,obj in sorted(sim_objects.iteritems()): 55810037SARM gem5 Developers for param in obj._params.local.values(): 55910037SARM gem5 Developers # load the ptype attribute now because it depends on the 56010037SARM gem5 Developers # current version of SimObject.allClasses, but when scons 56110037SARM gem5 Developers # actually uses the value, all versions of 56210037SARM gem5 Developers # SimObject.allClasses will have been loaded 56310037SARM gem5 Developers param.ptype 5647614Sminkyu.jeong@arm.com 5657614Sminkyu.jeong@arm.com if not hasattr(param, 'swig_decl'): 56610037SARM gem5 Developers continue 5677614Sminkyu.jeong@arm.com pname = param.ptype_str 5687614Sminkyu.jeong@arm.com if pname not in params_to_swig: 56910037SARM gem5 Developers params_to_swig[pname] = param 5707614Sminkyu.jeong@arm.com 5717614Sminkyu.jeong@arm.com######################################################################## 57210037SARM gem5 Developers# 5737614Sminkyu.jeong@arm.com# calculate extra dependencies 5747614Sminkyu.jeong@arm.com# 57510037SARM gem5 Developersmodule_depends = ["m5", "m5.SimObject", "m5.params"] 5767614Sminkyu.jeong@arm.comdepends = [ PySource.modules[dep].snode for dep in module_depends ] 5777614Sminkyu.jeong@arm.comdepends.sort(key = lambda x: x.name) 57810037SARM gem5 Developers 5797614Sminkyu.jeong@arm.com######################################################################## 5807614Sminkyu.jeong@arm.com# 58110037SARM gem5 Developers# Commands for the basic automatically generated python files 58210037SARM gem5 Developers# 58310037SARM gem5 Developers 58410037SARM gem5 Developers# Generate Python file containing a dict specifying the current 5857614Sminkyu.jeong@arm.com# buildEnv flags. 5867614Sminkyu.jeong@arm.comdef makeDefinesPyFile(target, source, env): 58710037SARM gem5 Developers build_env = source[0].get_contents() 5887614Sminkyu.jeong@arm.com 5897614Sminkyu.jeong@arm.com code = code_formatter() 5907614Sminkyu.jeong@arm.com code(""" 5917614Sminkyu.jeong@arm.comimport m5.internal 59210037SARM gem5 Developersimport m5.util 5937614Sminkyu.jeong@arm.com 5947614Sminkyu.jeong@arm.combuildEnv = m5.util.SmartDict($build_env) 59510037SARM gem5 Developers 59610037SARM gem5 DeveloperscompileDate = m5.internal.core.compileDate 59710037SARM gem5 Developers_globals = globals() 59810037SARM gem5 Developersfor key,val in m5.internal.core.__dict__.iteritems(): 59910037SARM gem5 Developers if key.startswith('flag_'): 60010037SARM gem5 Developers flag = key[5:] 60110037SARM gem5 Developers _globals[flag] = val 60210037SARM gem5 Developersdel _globals 60310037SARM gem5 Developers""") 60410037SARM gem5 Developers code.write(target[0].abspath) 60510037SARM gem5 Developers 60610037SARM gem5 Developersdefines_info = Value(build_env) 60710037SARM gem5 Developers# Generate a file with all of the compile options in it 60810037SARM gem5 Developersenv.Command('python/m5/defines.py', defines_info, 60910037SARM gem5 Developers MakeAction(makeDefinesPyFile, Transform("DEFINES", 0))) 61010037SARM gem5 DevelopersPySource('m5', 'python/m5/defines.py') 61110037SARM gem5 Developers 61210037SARM gem5 Developers# Generate python file containing info about the M5 source code 61310037SARM gem5 Developersdef makeInfoPyFile(target, source, env): 61410037SARM gem5 Developers code = code_formatter() 61510037SARM gem5 Developers for src in source: 61610037SARM gem5 Developers data = ''.join(file(src.srcnode().abspath, 'r').xreadlines()) 61710037SARM gem5 Developers code('$src = ${{repr(data)}}') 61810037SARM gem5 Developers code.write(str(target[0])) 61910037SARM gem5 Developers 62010037SARM gem5 Developers# Generate a file that wraps the basic top level files 62110037SARM gem5 Developersenv.Command('python/m5/info.py', 62210037SARM gem5 Developers [ '#/COPYING', '#/LICENSE', '#/README', ], 62310037SARM gem5 Developers MakeAction(makeInfoPyFile, Transform("INFO"))) 62410037SARM gem5 DevelopersPySource('m5', 'python/m5/info.py') 62510037SARM gem5 Developers 62610037SARM gem5 Developers######################################################################## 62710037SARM gem5 Developers# 62810037SARM gem5 Developers# Create all of the SimObject param headers and enum headers 62910037SARM gem5 Developers# 63010037SARM gem5 Developers 63110037SARM gem5 Developersdef createSimObjectParamStruct(target, source, env): 63210037SARM gem5 Developers assert len(target) == 1 and len(source) == 1 63310037SARM gem5 Developers 63410037SARM gem5 Developers name = str(source[0].get_contents()) 63510037SARM gem5 Developers obj = sim_objects[name] 63610037SARM gem5 Developers 63710037SARM gem5 Developers code = code_formatter() 63810037SARM gem5 Developers obj.cxx_param_decl(code) 63910037SARM gem5 Developers code.write(target[0].abspath) 64010037SARM gem5 Developers 64110037SARM gem5 Developersdef createSimObjectCxxConfig(is_header): 64210037SARM gem5 Developers def body(target, source, env): 64310037SARM gem5 Developers assert len(target) == 1 and len(source) == 1 64410037SARM gem5 Developers 64511771SCurtis.Dunham@arm.com name = str(source[0].get_contents()) 64610037SARM gem5 Developers obj = sim_objects[name] 64710037SARM gem5 Developers 64810037SARM gem5 Developers code = code_formatter() 64914242Sgiacomo.travaglini@arm.com obj.cxx_config_param_file(code, is_header) 65014242Sgiacomo.travaglini@arm.com code.write(target[0].abspath) 65114242Sgiacomo.travaglini@arm.com return body 65214242Sgiacomo.travaglini@arm.com 65310037SARM gem5 Developersdef createParamSwigWrapper(target, source, env): 6547614Sminkyu.jeong@arm.com assert len(target) == 1 and len(source) == 1 65510037SARM gem5 Developers 6567614Sminkyu.jeong@arm.com name = str(source[0].get_contents()) 6577614Sminkyu.jeong@arm.com param = params_to_swig[name] 65814242Sgiacomo.travaglini@arm.com 65914242Sgiacomo.travaglini@arm.com code = code_formatter() 66014242Sgiacomo.travaglini@arm.com param.swig_decl(code) 66114242Sgiacomo.travaglini@arm.com code.write(target[0].abspath) 66214242Sgiacomo.travaglini@arm.com 66314242Sgiacomo.travaglini@arm.comdef createEnumStrings(target, source, env): 66414242Sgiacomo.travaglini@arm.com assert len(target) == 1 and len(source) == 1 66514242Sgiacomo.travaglini@arm.com 66614242Sgiacomo.travaglini@arm.com name = str(source[0].get_contents()) 66714242Sgiacomo.travaglini@arm.com obj = all_enums[name] 66811771SCurtis.Dunham@arm.com 66911771SCurtis.Dunham@arm.com code = code_formatter() 67011771SCurtis.Dunham@arm.com obj.cxx_def(code) 67111771SCurtis.Dunham@arm.com code.write(target[0].abspath) 67211771SCurtis.Dunham@arm.com 67311771SCurtis.Dunham@arm.comdef createEnumDecls(target, source, env): 67411771SCurtis.Dunham@arm.com assert len(target) == 1 and len(source) == 1 67511771SCurtis.Dunham@arm.com 67611771SCurtis.Dunham@arm.com name = str(source[0].get_contents()) 67711771SCurtis.Dunham@arm.com obj = all_enums[name] 67811771SCurtis.Dunham@arm.com 67911771SCurtis.Dunham@arm.com code = code_formatter() 68011771SCurtis.Dunham@arm.com obj.cxx_decl(code) 68111771SCurtis.Dunham@arm.com code.write(target[0].abspath) 68211771SCurtis.Dunham@arm.com 68311771SCurtis.Dunham@arm.comdef createEnumSwigWrapper(target, source, env): 68411771SCurtis.Dunham@arm.com assert len(target) == 1 and len(source) == 1 68511771SCurtis.Dunham@arm.com 68611771SCurtis.Dunham@arm.com name = str(source[0].get_contents()) 68711771SCurtis.Dunham@arm.com obj = all_enums[name] 68811771SCurtis.Dunham@arm.com 68913759Sgiacomo.gabrielli@arm.com code = code_formatter() 69013759Sgiacomo.gabrielli@arm.com obj.swig_decl(code) 69113759Sgiacomo.gabrielli@arm.com code.write(target[0].abspath) 69213759Sgiacomo.gabrielli@arm.com 69313759Sgiacomo.gabrielli@arm.comdef createSimObjectSwigWrapper(target, source, env): 69413759Sgiacomo.gabrielli@arm.com name = source[0].get_contents() 69513759Sgiacomo.gabrielli@arm.com obj = sim_objects[name] 69610905Sandreas.sandberg@arm.com 6977733SAli.Saidi@ARM.com code = code_formatter() 6987733SAli.Saidi@ARM.com obj.swig_decl(code) 69912529Sgiacomo.travaglini@arm.com code.write(target[0].abspath) 70010037SARM gem5 Developers 70111771SCurtis.Dunham@arm.com# dummy target for generated code 70210037SARM gem5 Developers# we start out with all the Source files so they get copied to build/*/ also. 70310037SARM gem5 DevelopersSWIG = env.Dummy('swig', [s.tnode for s in Source.get()]) 70410037SARM gem5 Developers 70510037SARM gem5 Developers# Generate all of the SimObject param C++ struct header files 70613114Sgiacomo.travaglini@arm.comparams_hh_files = [] 70713759Sgiacomo.gabrielli@arm.comfor name,simobj in sorted(sim_objects.iteritems()): 70813759Sgiacomo.gabrielli@arm.com py_source = PySource.modules[simobj.__module__] 70914133Sjordi.vaquero@metempsy.com extra_deps = [ py_source.tnode ] 71014128Sgiacomo.travaglini@arm.com 7117733SAli.Saidi@ARM.com hh_file = File('params/%s.hh' % name) 71210905Sandreas.sandberg@arm.com params_hh_files.append(hh_file) 7137733SAli.Saidi@ARM.com env.Command(hh_file, Value(name), 7147733SAli.Saidi@ARM.com MakeAction(createSimObjectParamStruct, Transform("SO PARAM"))) 71512529Sgiacomo.travaglini@arm.com env.Depends(hh_file, depends + extra_deps) 7167733SAli.Saidi@ARM.com env.Depends(SWIG, hh_file) 7177733SAli.Saidi@ARM.com 71810037SARM gem5 Developers# C++ parameter description files 71911771SCurtis.Dunham@arm.comif GetOption('with_cxx_config'): 72010037SARM gem5 Developers for name,simobj in sorted(sim_objects.iteritems()): 72110037SARM gem5 Developers py_source = PySource.modules[simobj.__module__] 72210037SARM gem5 Developers extra_deps = [ py_source.tnode ] 72310037SARM gem5 Developers 72413114Sgiacomo.travaglini@arm.com cxx_config_hh_file = File('cxx_config/%s.hh' % name) 72513759Sgiacomo.gabrielli@arm.com cxx_config_cc_file = File('cxx_config/%s.cc' % name) 72613759Sgiacomo.gabrielli@arm.com env.Command(cxx_config_hh_file, Value(name), 72714133Sjordi.vaquero@metempsy.com MakeAction(createSimObjectCxxConfig(True), 72814128Sgiacomo.travaglini@arm.com Transform("CXXCPRHH"))) 7297733SAli.Saidi@ARM.com env.Command(cxx_config_cc_file, Value(name), 7306313Sgblack@eecs.umich.edu MakeAction(createSimObjectCxxConfig(False), 73112972Sandreas.sandberg@arm.com Transform("CXXCPRCC"))) 7329461Snilay@cs.wisc.edu env.Depends(cxx_config_hh_file, depends + extra_deps + 73311165SRekai.GonzalezAlberquilla@arm.com [File('params/%s.hh' % name), File('sim/cxx_config.hh')]) 73411165SRekai.GonzalezAlberquilla@arm.com env.Depends(cxx_config_cc_file, depends + extra_deps + 73514000Sgiacomo.travaglini@arm.com [cxx_config_hh_file]) 73614000Sgiacomo.travaglini@arm.com Source(cxx_config_cc_file) 73714000Sgiacomo.travaglini@arm.com 73814000Sgiacomo.travaglini@arm.com cxx_config_init_cc_file = File('cxx_config/init.cc') 73914000Sgiacomo.travaglini@arm.com 74014000Sgiacomo.travaglini@arm.com def createCxxConfigInitCC(target, source, env): 74114000Sgiacomo.travaglini@arm.com assert len(target) == 1 and len(source) == 1 74214000Sgiacomo.travaglini@arm.com 74314000Sgiacomo.travaglini@arm.com code = code_formatter() 74414000Sgiacomo.travaglini@arm.com 74512109SRekai.GonzalezAlberquilla@arm.com for name,simobj in sorted(sim_objects.iteritems()): 74612109SRekai.GonzalezAlberquilla@arm.com if not hasattr(simobj, 'abstract') or not simobj.abstract: 74712109SRekai.GonzalezAlberquilla@arm.com code('#include "cxx_config/${name}.hh"') 74812109SRekai.GonzalezAlberquilla@arm.com code() 74912109SRekai.GonzalezAlberquilla@arm.com code('void cxxConfigInit()') 75012109SRekai.GonzalezAlberquilla@arm.com code('{') 7519553Sandreas.hansson@arm.com code.indent() 7529553Sandreas.hansson@arm.com for name,simobj in sorted(sim_objects.iteritems()): 7539553Sandreas.hansson@arm.com not_abstract = not hasattr(simobj, 'abstract') or \ 7549384SAndreas.Sandberg@arm.com not simobj.abstract 7557400SAli.Saidi@ARM.com if not_abstract and 'type' in simobj.__dict__: 7569384SAndreas.Sandberg@arm.com code('cxx_config_directory["${name}"] = ' 7579384SAndreas.Sandberg@arm.com '${name}CxxConfigParams::makeDirectoryEntry();') 7589384SAndreas.Sandberg@arm.com code.dedent() 7596313Sgblack@eecs.umich.edu code('}') 7606313Sgblack@eecs.umich.edu code.write(target[0].abspath) 7616313Sgblack@eecs.umich.edu 76212109SRekai.GonzalezAlberquilla@arm.com py_source = PySource.modules[simobj.__module__] 76313601Sgiacomo.travaglini@arm.com extra_deps = [ py_source.tnode ] 76412109SRekai.GonzalezAlberquilla@arm.com env.Command(cxx_config_init_cc_file, Value(name), 76513601Sgiacomo.travaglini@arm.com MakeAction(createCxxConfigInitCC, Transform("CXXCINIT"))) 76613601Sgiacomo.travaglini@arm.com cxx_param_hh_files = ["cxx_config/%s.hh" % simobj 76712109SRekai.GonzalezAlberquilla@arm.com for name,simobj in sorted(sim_objects.iteritems()) 76812109SRekai.GonzalezAlberquilla@arm.com if not hasattr(simobj, 'abstract') or not simobj.abstract] 76912109SRekai.GonzalezAlberquilla@arm.com Depends(cxx_config_init_cc_file, cxx_param_hh_files + 77013601Sgiacomo.travaglini@arm.com [File('sim/cxx_config.hh')]) 77113601Sgiacomo.travaglini@arm.com Source(cxx_config_init_cc_file) 77213601Sgiacomo.travaglini@arm.com 77312109SRekai.GonzalezAlberquilla@arm.com# Generate any needed param SWIG wrapper files 77413601Sgiacomo.travaglini@arm.comparams_i_files = [] 77513601Sgiacomo.travaglini@arm.comfor name,param in sorted(params_to_swig.iteritems()): 77613601Sgiacomo.travaglini@arm.com i_file = File('python/m5/internal/%s.i' % (param.swig_module_name())) 77713601Sgiacomo.travaglini@arm.com params_i_files.append(i_file) 77813601Sgiacomo.travaglini@arm.com env.Command(i_file, Value(name), 77913601Sgiacomo.travaglini@arm.com MakeAction(createParamSwigWrapper, Transform("SW PARAM"))) 78013601Sgiacomo.travaglini@arm.com env.Depends(i_file, depends) 78113601Sgiacomo.travaglini@arm.com env.Depends(SWIG, i_file) 78213601Sgiacomo.travaglini@arm.com SwigSource('m5.internal', i_file) 78313601Sgiacomo.travaglini@arm.com 78413601Sgiacomo.travaglini@arm.com# Generate all enum header files 78512109SRekai.GonzalezAlberquilla@arm.comfor name,enum in sorted(all_enums.iteritems()): 78612109SRekai.GonzalezAlberquilla@arm.com py_source = PySource.modules[enum.__module__] 78712109SRekai.GonzalezAlberquilla@arm.com extra_deps = [ py_source.tnode ] 7886313Sgblack@eecs.umich.edu 789 cc_file = File('enums/%s.cc' % name) 790 env.Command(cc_file, Value(name), 791 MakeAction(createEnumStrings, Transform("ENUM STR"))) 792 env.Depends(cc_file, depends + extra_deps) 793 env.Depends(SWIG, cc_file) 794 Source(cc_file) 795 796 hh_file = File('enums/%s.hh' % name) 797 env.Command(hh_file, Value(name), 798 MakeAction(createEnumDecls, Transform("ENUMDECL"))) 799 env.Depends(hh_file, depends + extra_deps) 800 env.Depends(SWIG, hh_file) 801 802 i_file = File('python/m5/internal/enum_%s.i' % name) 803 env.Command(i_file, Value(name), 804 MakeAction(createEnumSwigWrapper, Transform("ENUMSWIG"))) 805 env.Depends(i_file, depends + extra_deps) 806 env.Depends(SWIG, i_file) 807 SwigSource('m5.internal', i_file) 808 809# Generate SimObject SWIG wrapper files 810for name,simobj in sorted(sim_objects.iteritems()): 811 py_source = PySource.modules[simobj.__module__] 812 extra_deps = [ py_source.tnode ] 813 i_file = File('python/m5/internal/param_%s.i' % name) 814 env.Command(i_file, Value(name), 815 MakeAction(createSimObjectSwigWrapper, Transform("SO SWIG"))) 816 env.Depends(i_file, depends + extra_deps) 817 SwigSource('m5.internal', i_file) 818 819# Generate the main swig init file 820def makeEmbeddedSwigInit(package): 821 def body(target, source, env): 822 assert len(target) == 1 and len(source) == 1 823 824 code = code_formatter() 825 module = source[0].get_contents() 826 # Provide the full context so that the swig-generated call to 827 # Py_InitModule ends up placing the embedded module in the 828 # right package. 829 context = str(package) + "._" + str(module) 830 code('''\ 831 #include "sim/init.hh" 832 833 extern "C" { 834 void init_${module}(); 835 } 836 837 EmbeddedSwig embed_swig_${module}(init_${module}, "${context}"); 838 ''') 839 code.write(str(target[0])) 840 return body 841 842# Build all swig modules 843for swig in SwigSource.all: 844 env.Command([swig.cc_source.tnode, swig.py_source.tnode], swig.tnode, 845 MakeAction('$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} ' 846 '-o ${TARGETS[0]} $SOURCES', Transform("SWIG"))) 847 cc_file = str(swig.tnode) 848 init_file = '%s/%s_init.cc' % (dirname(cc_file), basename(cc_file)) 849 env.Command(init_file, Value(swig.module), 850 MakeAction(makeEmbeddedSwigInit(swig.package), 851 Transform("EMBED SW"))) 852 env.Depends(SWIG, init_file) 853 Source(init_file, **swig.guards) 854 855# Build all protocol buffers if we have got protoc and protobuf available 856if env['HAVE_PROTOBUF']: 857 for proto in ProtoBuf.all: 858 # Use both the source and header as the target, and the .proto 859 # file as the source. When executing the protoc compiler, also 860 # specify the proto_path to avoid having the generated files 861 # include the path. 862 env.Command([proto.cc_file, proto.hh_file], proto.tnode, 863 MakeAction('$PROTOC --cpp_out ${TARGET.dir} ' 864 '--proto_path ${SOURCE.dir} $SOURCE', 865 Transform("PROTOC"))) 866 867 env.Depends(SWIG, [proto.cc_file, proto.hh_file]) 868 # Add the C++ source file 869 Source(proto.cc_file, **proto.guards) 870elif ProtoBuf.all: 871 print 'Got protobuf to build, but lacks support!' 872 Exit(1) 873 874# 875# Handle debug flags 876# 877def makeDebugFlagCC(target, source, env): 878 assert(len(target) == 1 and len(source) == 1) 879 880 code = code_formatter() 881 882 # delay definition of CompoundFlags until after all the definition 883 # of all constituent SimpleFlags 884 comp_code = code_formatter() 885 886 # file header 887 code(''' 888/* 889 * DO NOT EDIT THIS FILE! Automatically generated by SCons. 890 */ 891 892#include "base/debug.hh" 893 894namespace Debug { 895 896''') 897 898 for name, flag in sorted(source[0].read().iteritems()): 899 n, compound, desc = flag 900 assert n == name 901 902 if not compound: 903 code('SimpleFlag $name("$name", "$desc");') 904 else: 905 comp_code('CompoundFlag $name("$name", "$desc",') 906 comp_code.indent() 907 last = len(compound) - 1 908 for i,flag in enumerate(compound): 909 if i != last: 910 comp_code('&$flag,') 911 else: 912 comp_code('&$flag);') 913 comp_code.dedent() 914 915 code.append(comp_code) 916 code() 917 code('} // namespace Debug') 918 919 code.write(str(target[0])) 920 921def makeDebugFlagHH(target, source, env): 922 assert(len(target) == 1 and len(source) == 1) 923 924 val = eval(source[0].get_contents()) 925 name, compound, desc = val 926 927 code = code_formatter() 928 929 # file header boilerplate 930 code('''\ 931/* 932 * DO NOT EDIT THIS FILE! Automatically generated by SCons. 933 */ 934 935#ifndef __DEBUG_${name}_HH__ 936#define __DEBUG_${name}_HH__ 937 938namespace Debug { 939''') 940 941 if compound: 942 code('class CompoundFlag;') 943 code('class SimpleFlag;') 944 945 if compound: 946 code('extern CompoundFlag $name;') 947 for flag in compound: 948 code('extern SimpleFlag $flag;') 949 else: 950 code('extern SimpleFlag $name;') 951 952 code(''' 953} 954 955#endif // __DEBUG_${name}_HH__ 956''') 957 958 code.write(str(target[0])) 959 960for name,flag in sorted(debug_flags.iteritems()): 961 n, compound, desc = flag 962 assert n == name 963 964 hh_file = 'debug/%s.hh' % name 965 env.Command(hh_file, Value(flag), 966 MakeAction(makeDebugFlagHH, Transform("TRACING", 0))) 967 env.Depends(SWIG, hh_file) 968 969env.Command('debug/flags.cc', Value(debug_flags), 970 MakeAction(makeDebugFlagCC, Transform("TRACING", 0))) 971env.Depends(SWIG, 'debug/flags.cc') 972Source('debug/flags.cc') 973 974# version tags 975tags = \ 976env.Command('sim/tags.cc', None, 977 MakeAction('util/cpt_upgrader.py --get-cc-file > $TARGET', 978 Transform("VER TAGS"))) 979env.AlwaysBuild(tags) 980 981# Embed python files. All .py files that have been indicated by a 982# PySource() call in a SConscript need to be embedded into the M5 983# library. To do that, we compile the file to byte code, marshal the 984# byte code, compress it, and then generate a c++ file that 985# inserts the result into an array. 986def embedPyFile(target, source, env): 987 def c_str(string): 988 if string is None: 989 return "0" 990 return '"%s"' % string 991 992 '''Action function to compile a .py into a code object, marshal 993 it, compress it, and stick it into an asm file so the code appears 994 as just bytes with a label in the data section''' 995 996 src = file(str(source[0]), 'r').read() 997 998 pysource = PySource.tnodes[source[0]] 999 compiled = compile(src, pysource.abspath, 'exec') 1000 marshalled = marshal.dumps(compiled) 1001 compressed = zlib.compress(marshalled) 1002 data = compressed 1003 sym = pysource.symname 1004 1005 code = code_formatter() 1006 code('''\ 1007#include "sim/init.hh" 1008 1009namespace { 1010 1011const uint8_t data_${sym}[] = { 1012''') 1013 code.indent() 1014 step = 16 1015 for i in xrange(0, len(data), step): 1016 x = array.array('B', data[i:i+step]) 1017 code(''.join('%d,' % d for d in x)) 1018 code.dedent() 1019 1020 code('''}; 1021 1022EmbeddedPython embedded_${sym}( 1023 ${{c_str(pysource.arcname)}}, 1024 ${{c_str(pysource.abspath)}}, 1025 ${{c_str(pysource.modpath)}}, 1026 data_${sym}, 1027 ${{len(data)}}, 1028 ${{len(marshalled)}}); 1029 1030} // anonymous namespace 1031''') 1032 code.write(str(target[0])) 1033 1034for source in PySource.all: 1035 env.Command(source.cpp, source.tnode, 1036 MakeAction(embedPyFile, Transform("EMBED PY"))) 1037 env.Depends(SWIG, source.cpp) 1038 Source(source.cpp, skip_no_python=True) 1039 1040######################################################################## 1041# 1042# Define binaries. Each different build type (debug, opt, etc.) gets 1043# a slightly different build environment. 1044# 1045 1046# List of constructed environments to pass back to SConstruct 1047date_source = Source('base/date.cc', skip_lib=True) 1048 1049# Capture this directory for the closure makeEnv, otherwise when it is 1050# called, it won't know what directory it should use. 1051variant_dir = Dir('.').path 1052def variant(*path): 1053 return os.path.join(variant_dir, *path) 1054def variantd(*path): 1055 return variant(*path)+'/' 1056 1057# Function to create a new build environment as clone of current 1058# environment 'env' with modified object suffix and optional stripped 1059# binary. Additional keyword arguments are appended to corresponding 1060# build environment vars. 1061def makeEnv(env, label, objsfx, strip = False, **kwargs): 1062 # SCons doesn't know to append a library suffix when there is a '.' in the 1063 # name. Use '_' instead. 1064 libname = variant('gem5_' + label) 1065 exename = variant('gem5.' + label) 1066 secondary_exename = variant('m5.' + label) 1067 1068 new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's') 1069 new_env.Label = label 1070 new_env.Append(**kwargs) 1071 1072 swig_env = new_env.Clone() 1073 1074 # Both gcc and clang have issues with unused labels and values in 1075 # the SWIG generated code 1076 swig_env.Append(CCFLAGS=['-Wno-unused-label', '-Wno-unused-value']) 1077 1078 if env['GCC']: 1079 # Depending on the SWIG version, we also need to supress 1080 # warnings about uninitialized variables and missing field 1081 # initializers. 1082 swig_env.Append(CCFLAGS=['-Wno-uninitialized', 1083 '-Wno-missing-field-initializers', 1084 '-Wno-unused-but-set-variable', 1085 '-Wno-maybe-uninitialized', 1086 '-Wno-type-limits']) 1087 1088 1089 # The address sanitizer is available for gcc >= 4.8 1090 if GetOption('with_asan'): 1091 if GetOption('with_ubsan') and \ 1092 compareVersions(env['GCC_VERSION'], '4.9') >= 0: 1093 new_env.Append(CCFLAGS=['-fsanitize=address,undefined', 1094 '-fno-omit-frame-pointer']) 1095 new_env.Append(LINKFLAGS='-fsanitize=address,undefined') 1096 else: 1097 new_env.Append(CCFLAGS=['-fsanitize=address', 1098 '-fno-omit-frame-pointer']) 1099 new_env.Append(LINKFLAGS='-fsanitize=address') 1100 # Only gcc >= 4.9 supports UBSan, so check both the version 1101 # and the command-line option before adding the compiler and 1102 # linker flags. 1103 elif GetOption('with_ubsan') and \ 1104 compareVersions(env['GCC_VERSION'], '4.9') >= 0: 1105 new_env.Append(CCFLAGS='-fsanitize=undefined') 1106 new_env.Append(LINKFLAGS='-fsanitize=undefined') 1107 1108 1109 if env['CLANG']: 1110 swig_env.Append(CCFLAGS=['-Wno-sometimes-uninitialized', 1111 '-Wno-deprecated-register', 1112 '-Wno-tautological-compare']) 1113 1114 # We require clang >= 3.1, so there is no need to check any 1115 # versions here. 1116 if GetOption('with_ubsan'): 1117 if GetOption('with_asan'): 1118 new_env.Append(CCFLAGS=['-fsanitize=address,undefined', 1119 '-fno-omit-frame-pointer']) 1120 new_env.Append(LINKFLAGS='-fsanitize=address,undefined') 1121 else: 1122 new_env.Append(CCFLAGS='-fsanitize=undefined') 1123 new_env.Append(LINKFLAGS='-fsanitize=undefined') 1124 1125 elif GetOption('with_asan'): 1126 new_env.Append(CCFLAGS=['-fsanitize=address', 1127 '-fno-omit-frame-pointer']) 1128 new_env.Append(LINKFLAGS='-fsanitize=address') 1129 1130 werror_env = new_env.Clone() 1131 # Treat warnings as errors but white list some warnings that we 1132 # want to allow (e.g., deprecation warnings). 1133 werror_env.Append(CCFLAGS=['-Werror', 1134 '-Wno-error=deprecated-declarations', 1135 '-Wno-error=deprecated', 1136 ]) 1137 1138 def make_obj(source, static, extra_deps = None): 1139 '''This function adds the specified source to the correct 1140 build environment, and returns the corresponding SCons Object 1141 nodes''' 1142 1143 if source.swig: 1144 env = swig_env 1145 elif source.Werror: 1146 env = werror_env 1147 else: 1148 env = new_env 1149 1150 if static: 1151 obj = env.StaticObject(source.tnode) 1152 else: 1153 obj = env.SharedObject(source.tnode) 1154 1155 if extra_deps: 1156 env.Depends(obj, extra_deps) 1157 1158 return obj 1159 1160 lib_guards = {'main': False, 'skip_lib': False} 1161 1162 # Without Python, leave out all SWIG and Python content from the 1163 # library builds. The option doesn't affect gem5 built as a program 1164 if GetOption('without_python'): 1165 lib_guards['skip_no_python'] = False 1166 1167 static_objs = [ make_obj(s, True) for s in Source.get(**lib_guards) ] 1168 shared_objs = [ make_obj(s, False) for s in Source.get(**lib_guards) ] 1169 1170 static_date = make_obj(date_source, static=True, extra_deps=static_objs) 1171 static_objs.append(static_date) 1172 1173 shared_date = make_obj(date_source, static=False, extra_deps=shared_objs) 1174 shared_objs.append(shared_date) 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 # Now link a stub with main() and the static library. 1182 main_objs = [ make_obj(s, True) for s in Source.get(main=True) ] 1183 1184 for test in UnitTest.all: 1185 flags = { test.target : True } 1186 test_sources = Source.get(**flags) 1187 test_objs = [ make_obj(s, static=True) for s in test_sources ] 1188 if test.main: 1189 test_objs += main_objs 1190 path = variant('unittest/%s.%s' % (test.target, label)) 1191 new_env.Program(path, test_objs + static_objs) 1192 1193 progname = exename 1194 if strip: 1195 progname += '.unstripped' 1196 1197 targets = new_env.Program(progname, main_objs + static_objs) 1198 1199 if strip: 1200 if sys.platform == 'sunos5': 1201 cmd = 'cp $SOURCE $TARGET; strip $TARGET' 1202 else: 1203 cmd = 'strip $SOURCE -o $TARGET' 1204 targets = new_env.Command(exename, progname, 1205 MakeAction(cmd, Transform("STRIP"))) 1206 1207 new_env.Command(secondary_exename, exename, 1208 MakeAction('ln $SOURCE $TARGET', Transform("HARDLINK"))) 1209 1210 new_env.M5Binary = targets[0] 1211 return new_env 1212 1213# Start out with the compiler flags common to all compilers, 1214# i.e. they all use -g for opt and -g -pg for prof 1215ccflags = {'debug' : [], 'opt' : ['-g'], 'fast' : [], 'prof' : ['-g', '-pg'], 1216 'perf' : ['-g']} 1217 1218# Start out with the linker flags common to all linkers, i.e. -pg for 1219# prof, and -lprofiler for perf. The -lprofile flag is surrounded by 1220# no-as-needed and as-needed as the binutils linker is too clever and 1221# simply doesn't link to the library otherwise. 1222ldflags = {'debug' : [], 'opt' : [], 'fast' : [], 'prof' : ['-pg'], 1223 'perf' : ['-Wl,--no-as-needed', '-lprofiler', '-Wl,--as-needed']} 1224 1225# For Link Time Optimization, the optimisation flags used to compile 1226# individual files are decoupled from those used at link time 1227# (i.e. you can compile with -O3 and perform LTO with -O0), so we need 1228# to also update the linker flags based on the target. 1229if env['GCC']: 1230 if sys.platform == 'sunos5': 1231 ccflags['debug'] += ['-gstabs+'] 1232 else: 1233 ccflags['debug'] += ['-ggdb3'] 1234 ldflags['debug'] += ['-O0'] 1235 # opt, fast, prof and perf all share the same cc flags, also add 1236 # the optimization to the ldflags as LTO defers the optimization 1237 # to link time 1238 for target in ['opt', 'fast', 'prof', 'perf']: 1239 ccflags[target] += ['-O3'] 1240 ldflags[target] += ['-O3'] 1241 1242 ccflags['fast'] += env['LTO_CCFLAGS'] 1243 ldflags['fast'] += env['LTO_LDFLAGS'] 1244elif env['CLANG']: 1245 ccflags['debug'] += ['-g', '-O0'] 1246 # opt, fast, prof and perf all share the same cc flags 1247 for target in ['opt', 'fast', 'prof', 'perf']: 1248 ccflags[target] += ['-O3'] 1249else: 1250 print 'Unknown compiler, please fix compiler options' 1251 Exit(1) 1252 1253 1254# To speed things up, we only instantiate the build environments we 1255# need. We try to identify the needed environment for each target; if 1256# we can't, we fall back on instantiating all the environments just to 1257# be safe. 1258target_types = ['debug', 'opt', 'fast', 'prof', 'perf'] 1259obj2target = {'do': 'debug', 'o': 'opt', 'fo': 'fast', 'po': 'prof', 1260 'gpo' : 'perf'} 1261 1262def identifyTarget(t): 1263 ext = t.split('.')[-1] 1264 if ext in target_types: 1265 return ext 1266 if obj2target.has_key(ext): 1267 return obj2target[ext] 1268 match = re.search(r'/tests/([^/]+)/', t) 1269 if match and match.group(1) in target_types: 1270 return match.group(1) 1271 return 'all' 1272 1273needed_envs = [identifyTarget(target) for target in BUILD_TARGETS] 1274if 'all' in needed_envs: 1275 needed_envs += target_types 1276 1277def makeEnvirons(target, source, env): 1278 # cause any later Source() calls to be fatal, as a diagnostic. 1279 Source.done() 1280 1281 envList = [] 1282 1283 # Debug binary 1284 if 'debug' in needed_envs: 1285 envList.append( 1286 makeEnv(env, 'debug', '.do', 1287 CCFLAGS = Split(ccflags['debug']), 1288 CPPDEFINES = ['DEBUG', 'TRACING_ON=1'], 1289 LINKFLAGS = Split(ldflags['debug']))) 1290 1291 # Optimized binary 1292 if 'opt' in needed_envs: 1293 envList.append( 1294 makeEnv(env, 'opt', '.o', 1295 CCFLAGS = Split(ccflags['opt']), 1296 CPPDEFINES = ['TRACING_ON=1'], 1297 LINKFLAGS = Split(ldflags['opt']))) 1298 1299 # "Fast" binary 1300 if 'fast' in needed_envs: 1301 envList.append( 1302 makeEnv(env, 'fast', '.fo', strip = True, 1303 CCFLAGS = Split(ccflags['fast']), 1304 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1305 LINKFLAGS = Split(ldflags['fast']))) 1306 1307 # Profiled binary using gprof 1308 if 'prof' in needed_envs: 1309 envList.append( 1310 makeEnv(env, 'prof', '.po', 1311 CCFLAGS = Split(ccflags['prof']), 1312 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1313 LINKFLAGS = Split(ldflags['prof']))) 1314 1315 # Profiled binary using google-pprof 1316 if 'perf' in needed_envs: 1317 envList.append( 1318 makeEnv(env, 'perf', '.gpo', 1319 CCFLAGS = Split(ccflags['perf']), 1320 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1321 LINKFLAGS = Split(ldflags['perf']))) 1322 1323 # Set up the regression tests for each build. 1324 for e in envList: 1325 SConscript(os.path.join(env.root.abspath, 'tests', 'SConscript'), 1326 variant_dir = variantd('tests', e.Label), 1327 exports = { 'env' : e }, duplicate = False) 1328 1329# The MakeEnvirons Builder defers the full dependency collection until 1330# after processing the ISA definition (due to dynamically generated 1331# source files). Add this dependency to all targets so they will wait 1332# until the environments are completely set up. Otherwise, a second 1333# process (e.g. -j2 or higher) will try to compile the requested target, 1334# not know how, and fail. 1335env.Append(BUILDERS = {'MakeEnvirons' : 1336 Builder(action=MakeAction(makeEnvirons, 1337 Transform("ENVIRONS", 1)))}) 1338 1339isa_target = env['PHONY_BASE'] + '-deps' 1340environs = env['PHONY_BASE'] + '-environs' 1341env.Depends('#all-deps', isa_target) 1342env.Depends('#all-environs', environs) 1343env.ScanISA(isa_target, File('arch/%s/generated/inc.d' % env['TARGET_ISA'])) 1344envSetup = env.MakeEnvirons(environs, isa_target) 1345 1346# make sure no -deps targets occur before all ISAs are complete 1347env.Depends(isa_target, '#all-isas') 1348# likewise for -environs targets and all the -deps targets 1349env.Depends(environs, '#all-deps') 1350