SConscript revision 7816:b5003ac75977
1955SN/A# -*- mode:python -*-
2955SN/A
31762SN/A# Copyright (c) 2004-2005 The Regents of The University of Michigan
4955SN/A# All rights reserved.
5955SN/A#
6955SN/A# Redistribution and use in source and binary forms, with or without
7955SN/A# modification, are permitted provided that the following conditions are
8955SN/A# met: redistributions of source code must retain the above copyright
9955SN/A# notice, this list of conditions and the following disclaimer;
10955SN/A# redistributions in binary form must reproduce the above copyright
11955SN/A# notice, this list of conditions and the following disclaimer in the
12955SN/A# documentation and/or other materials provided with the distribution;
13955SN/A# neither the name of the copyright holders nor the names of its
14955SN/A# contributors may be used to endorse or promote products derived from
15955SN/A# this software without specific prior written permission.
16955SN/A#
17955SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18955SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19955SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20955SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21955SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22955SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23955SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24955SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25955SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26955SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27955SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282665Ssaidi@eecs.umich.edu#
292665Ssaidi@eecs.umich.edu# Authors: Nathan Binkert
30955SN/A
31955SN/Aimport array
32955SN/Aimport bisect
33955SN/Aimport imp
34955SN/Aimport marshal
352632Sstever@eecs.umich.eduimport os
362632Sstever@eecs.umich.eduimport re
372632Sstever@eecs.umich.eduimport sys
382632Sstever@eecs.umich.eduimport zlib
39955SN/A
402632Sstever@eecs.umich.edufrom os.path import basename, dirname, exists, isdir, isfile, join as joinpath
412632Sstever@eecs.umich.edu
422761Sstever@eecs.umich.eduimport SCons
432632Sstever@eecs.umich.edu
442632Sstever@eecs.umich.edu# This file defines how to build a particular configuration of M5
452632Sstever@eecs.umich.edu# based on variable settings in the 'env' build environment.
462761Sstever@eecs.umich.edu
472761Sstever@eecs.umich.eduImport('*')
482761Sstever@eecs.umich.edu
492632Sstever@eecs.umich.edu# Children need to see the environment
502632Sstever@eecs.umich.eduExport('env')
512761Sstever@eecs.umich.edu
522761Sstever@eecs.umich.edubuild_env = [(opt, env[opt]) for opt in export_vars]
532761Sstever@eecs.umich.edu
542761Sstever@eecs.umich.edufrom m5.util import code_formatter
552761Sstever@eecs.umich.edu
562632Sstever@eecs.umich.edu########################################################################
572632Sstever@eecs.umich.edu# Code for adding source files of various types
582632Sstever@eecs.umich.edu#
592632Sstever@eecs.umich.educlass SourceMeta(type):
602632Sstever@eecs.umich.edu    def __init__(cls, name, bases, dict):
612632Sstever@eecs.umich.edu        super(SourceMeta, cls).__init__(name, bases, dict)
622632Sstever@eecs.umich.edu        cls.all = []
63955SN/A        
64955SN/A    def get(cls, **kwargs):
65955SN/A        for src in cls.all:
66955SN/A            for attr,value in kwargs.iteritems():
67955SN/A                if getattr(src, attr) != value:
683918Ssaidi@eecs.umich.edu                    break
694202Sbinkertn@umich.edu            else:
703716Sstever@eecs.umich.edu                yield src
71955SN/A
722656Sstever@eecs.umich.educlass SourceFile(object):
732656Sstever@eecs.umich.edu    __metaclass__ = SourceMeta
742656Sstever@eecs.umich.edu    def __init__(self, source):
752656Sstever@eecs.umich.edu        tnode = source
762656Sstever@eecs.umich.edu        if not isinstance(source, SCons.Node.FS.File):
772656Sstever@eecs.umich.edu            tnode = File(source)
782656Sstever@eecs.umich.edu
792653Sstever@eecs.umich.edu        self.tnode = tnode
802653Sstever@eecs.umich.edu        self.snode = tnode.srcnode()
812653Sstever@eecs.umich.edu        self.filename = str(tnode)
822653Sstever@eecs.umich.edu        self.dirname = dirname(self.filename)
832653Sstever@eecs.umich.edu        self.basename = basename(self.filename)
842653Sstever@eecs.umich.edu        index = self.basename.rfind('.')
852653Sstever@eecs.umich.edu        if index <= 0:
862653Sstever@eecs.umich.edu            # dot files aren't extensions
872653Sstever@eecs.umich.edu            self.extname = self.basename, None
882653Sstever@eecs.umich.edu        else:
892653Sstever@eecs.umich.edu            self.extname = self.basename[:index], self.basename[index+1:]
901852SN/A
91955SN/A        for base in type(self).__mro__:
92955SN/A            if issubclass(base, SourceFile):
93955SN/A                base.all.append(self)
943717Sstever@eecs.umich.edu
953716Sstever@eecs.umich.edu    def __lt__(self, other): return self.filename < other.filename
96955SN/A    def __le__(self, other): return self.filename <= other.filename
971533SN/A    def __gt__(self, other): return self.filename > other.filename
983716Sstever@eecs.umich.edu    def __ge__(self, other): return self.filename >= other.filename
991533SN/A    def __eq__(self, other): return self.filename == other.filename
100955SN/A    def __ne__(self, other): return self.filename != other.filename
101955SN/A        
1022632Sstever@eecs.umich.educlass Source(SourceFile):
1032632Sstever@eecs.umich.edu    '''Add a c/c++ source file to the build'''
104955SN/A    def __init__(self, source, Werror=True, swig=False, bin_only=False,
105955SN/A                 skip_lib=False):
106955SN/A        super(Source, self).__init__(source)
107955SN/A
1082632Sstever@eecs.umich.edu        self.Werror = Werror
109955SN/A        self.swig = swig
1102632Sstever@eecs.umich.edu        self.bin_only = bin_only
1112632Sstever@eecs.umich.edu        self.skip_lib = bin_only or skip_lib
1122632Sstever@eecs.umich.edu
1132632Sstever@eecs.umich.educlass PySource(SourceFile):
1142632Sstever@eecs.umich.edu    '''Add a python source file to the named package'''
1152632Sstever@eecs.umich.edu    invalid_sym_char = re.compile('[^A-z0-9_]')
1162632Sstever@eecs.umich.edu    modules = {}
1173053Sstever@eecs.umich.edu    tnodes = {}
1183053Sstever@eecs.umich.edu    symnames = {}
1193053Sstever@eecs.umich.edu    
1203053Sstever@eecs.umich.edu    def __init__(self, package, source):
1213053Sstever@eecs.umich.edu        super(PySource, self).__init__(source)
1223053Sstever@eecs.umich.edu
1233053Sstever@eecs.umich.edu        modname,ext = self.extname
1243053Sstever@eecs.umich.edu        assert ext == 'py'
1253053Sstever@eecs.umich.edu
1263053Sstever@eecs.umich.edu        if package:
1273053Sstever@eecs.umich.edu            path = package.split('.')
1283053Sstever@eecs.umich.edu        else:
1293053Sstever@eecs.umich.edu            path = []
1303053Sstever@eecs.umich.edu
1313053Sstever@eecs.umich.edu        modpath = path[:]
1323053Sstever@eecs.umich.edu        if modname != '__init__':
1332632Sstever@eecs.umich.edu            modpath += [ modname ]
1342632Sstever@eecs.umich.edu        modpath = '.'.join(modpath)
1352632Sstever@eecs.umich.edu
1362632Sstever@eecs.umich.edu        arcpath = path + [ self.basename ]
1372632Sstever@eecs.umich.edu        abspath = self.snode.abspath
1382632Sstever@eecs.umich.edu        if not exists(abspath):
1393718Sstever@eecs.umich.edu            abspath = self.tnode.abspath
1403718Sstever@eecs.umich.edu
1413718Sstever@eecs.umich.edu        self.package = package
1423718Sstever@eecs.umich.edu        self.modname = modname
1433718Sstever@eecs.umich.edu        self.modpath = modpath
1443718Sstever@eecs.umich.edu        self.arcname = joinpath(*arcpath)
1453718Sstever@eecs.umich.edu        self.abspath = abspath
1463718Sstever@eecs.umich.edu        self.compiled = File(self.filename + 'c')
1473718Sstever@eecs.umich.edu        self.cpp = File(self.filename + '.cc')
1483718Sstever@eecs.umich.edu        self.symname = PySource.invalid_sym_char.sub('_', modpath)
1493718Sstever@eecs.umich.edu
1503718Sstever@eecs.umich.edu        PySource.modules[modpath] = self
1513718Sstever@eecs.umich.edu        PySource.tnodes[self.tnode] = self
1522634Sstever@eecs.umich.edu        PySource.symnames[self.symname] = self
1532634Sstever@eecs.umich.edu
1542632Sstever@eecs.umich.educlass SimObject(PySource):
1552638Sstever@eecs.umich.edu    '''Add a SimObject python file as a python source object and add
1562632Sstever@eecs.umich.edu    it to a list of sim object modules'''
1572632Sstever@eecs.umich.edu
1582632Sstever@eecs.umich.edu    fixed = False
1592632Sstever@eecs.umich.edu    modnames = []
1602632Sstever@eecs.umich.edu
1612632Sstever@eecs.umich.edu    def __init__(self, source):
1621858SN/A        super(SimObject, self).__init__('m5.objects', source)
1633716Sstever@eecs.umich.edu        if self.fixed:
1642638Sstever@eecs.umich.edu            raise AttributeError, "Too late to call SimObject now."
1652638Sstever@eecs.umich.edu
1662638Sstever@eecs.umich.edu        bisect.insort_right(SimObject.modnames, self.modname)
1672638Sstever@eecs.umich.edu
1682638Sstever@eecs.umich.educlass SwigSource(SourceFile):
1692638Sstever@eecs.umich.edu    '''Add a swig file to build'''
1702638Sstever@eecs.umich.edu
1713716Sstever@eecs.umich.edu    def __init__(self, package, source):
1722634Sstever@eecs.umich.edu        super(SwigSource, self).__init__(source)
1732634Sstever@eecs.umich.edu
174955SN/A        modname,ext = self.extname
175955SN/A        assert ext == 'i'
176955SN/A
177955SN/A        self.module = modname
178955SN/A        cc_file = joinpath(self.dirname, modname + '_wrap.cc')
179955SN/A        py_file = joinpath(self.dirname, modname + '.py')
180955SN/A
181955SN/A        self.cc_source = Source(cc_file, swig=True)
1821858SN/A        self.py_source = PySource(package, py_file)
1831858SN/A
1842632Sstever@eecs.umich.eduunit_tests = []
185955SN/Adef UnitTest(target, sources):
1863643Ssaidi@eecs.umich.edu    if not isinstance(sources, (list, tuple)):
1873643Ssaidi@eecs.umich.edu        sources = [ sources ]
1883643Ssaidi@eecs.umich.edu
1893643Ssaidi@eecs.umich.edu    sources = [ Source(src, skip_lib=True) for src in sources ]
1903643Ssaidi@eecs.umich.edu    unit_tests.append((target, sources))
1913643Ssaidi@eecs.umich.edu
1923643Ssaidi@eecs.umich.edu# Children should have access
1933643Ssaidi@eecs.umich.eduExport('Source')
1944494Ssaidi@eecs.umich.eduExport('PySource')
1954494Ssaidi@eecs.umich.eduExport('SimObject')
1963716Sstever@eecs.umich.eduExport('SwigSource')
1971105SN/AExport('UnitTest')
1982667Sstever@eecs.umich.edu
1992667Sstever@eecs.umich.edu########################################################################
2002667Sstever@eecs.umich.edu#
2012667Sstever@eecs.umich.edu# Trace Flags
2022667Sstever@eecs.umich.edu#
2032667Sstever@eecs.umich.edutrace_flags = {}
2041869SN/Adef TraceFlag(name, desc=None):
2051869SN/A    if name in trace_flags:
2061869SN/A        raise AttributeError, "Flag %s already specified" % name
2071869SN/A    trace_flags[name] = (name, (), desc)
2081869SN/A
2091065SN/Adef CompoundFlag(name, flags, desc=None):
2102632Sstever@eecs.umich.edu    if name in trace_flags:
2112632Sstever@eecs.umich.edu        raise AttributeError, "Flag %s already specified" % name
2123918Ssaidi@eecs.umich.edu
2133918Ssaidi@eecs.umich.edu    compound = tuple(flags)
2143940Ssaidi@eecs.umich.edu    trace_flags[name] = (name, compound, desc)
2153918Ssaidi@eecs.umich.edu
2163918Ssaidi@eecs.umich.eduExport('TraceFlag')
2173918Ssaidi@eecs.umich.eduExport('CompoundFlag')
2183918Ssaidi@eecs.umich.edu
2193918Ssaidi@eecs.umich.edu########################################################################
2203918Ssaidi@eecs.umich.edu#
2213940Ssaidi@eecs.umich.edu# Set some compiler variables
2223940Ssaidi@eecs.umich.edu#
2233940Ssaidi@eecs.umich.edu
2243942Ssaidi@eecs.umich.edu# Include file paths are rooted in this directory.  SCons will
2253940Ssaidi@eecs.umich.edu# automatically expand '.' to refer to both the source directory and
2263918Ssaidi@eecs.umich.edu# the corresponding build directory to pick up generated include
2273918Ssaidi@eecs.umich.edu# files.
228955SN/Aenv.Append(CPPPATH=Dir('.'))
2291858SN/A
2303918Ssaidi@eecs.umich.edufor extra_dir in extras_dir_list:
2313918Ssaidi@eecs.umich.edu    env.Append(CPPPATH=Dir(extra_dir))
2323918Ssaidi@eecs.umich.edu
2333918Ssaidi@eecs.umich.edu# Workaround for bug in SCons version > 0.97d20071212
2343940Ssaidi@eecs.umich.edu# Scons bug id: 2006 M5 Bug id: 308 
2353940Ssaidi@eecs.umich.edufor root, dirs, files in os.walk(base_dir, topdown=True):
2363918Ssaidi@eecs.umich.edu    Dir(root[len(base_dir) + 1:])
2373918Ssaidi@eecs.umich.edu
2383918Ssaidi@eecs.umich.edu########################################################################
2393918Ssaidi@eecs.umich.edu#
2403918Ssaidi@eecs.umich.edu# Walk the tree and execute all SConscripts in subdirectories
2413918Ssaidi@eecs.umich.edu#
2423918Ssaidi@eecs.umich.edu
2433918Ssaidi@eecs.umich.eduhere = Dir('.').srcnode().abspath
2443918Ssaidi@eecs.umich.edufor root, dirs, files in os.walk(base_dir, topdown=True):
2453940Ssaidi@eecs.umich.edu    if root == here:
2463918Ssaidi@eecs.umich.edu        # we don't want to recurse back into this SConscript
2473918Ssaidi@eecs.umich.edu        continue
2481851SN/A
2491851SN/A    if 'SConscript' in files:
2501858SN/A        build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:])
2512632Sstever@eecs.umich.edu        SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir)
252955SN/A
2533053Sstever@eecs.umich.edufor extra_dir in extras_dir_list:
2543053Sstever@eecs.umich.edu    prefix_len = len(dirname(extra_dir)) + 1
2553053Sstever@eecs.umich.edu    for root, dirs, files in os.walk(extra_dir, topdown=True):
2563053Sstever@eecs.umich.edu        if 'SConscript' in files:
2573053Sstever@eecs.umich.edu            build_dir = joinpath(env['BUILDDIR'], root[prefix_len:])
2583053Sstever@eecs.umich.edu            SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir)
2593053Sstever@eecs.umich.edu
2603053Sstever@eecs.umich.edufor opt in export_vars:
2613053Sstever@eecs.umich.edu    env.ConfigFile(opt)
2624742Sstever@eecs.umich.edu
2634742Sstever@eecs.umich.edudef makeTheISA(source, target, env):
2643053Sstever@eecs.umich.edu    isas = [ src.get_contents() for src in source ]
2653053Sstever@eecs.umich.edu    target_isa = env['TARGET_ISA']
2663053Sstever@eecs.umich.edu    def define(isa):
2673053Sstever@eecs.umich.edu        return isa.upper() + '_ISA'
2683053Sstever@eecs.umich.edu    
2693053Sstever@eecs.umich.edu    def namespace(isa):
2703053Sstever@eecs.umich.edu        return isa[0].upper() + isa[1:].lower() + 'ISA' 
2713053Sstever@eecs.umich.edu
2723053Sstever@eecs.umich.edu
2732667Sstever@eecs.umich.edu    code = code_formatter()
2744554Sbinkertn@umich.edu    code('''\
2754554Sbinkertn@umich.edu#ifndef __CONFIG_THE_ISA_HH__
2762667Sstever@eecs.umich.edu#define __CONFIG_THE_ISA_HH__
2774554Sbinkertn@umich.edu
2784554Sbinkertn@umich.edu''')
2794554Sbinkertn@umich.edu
2804554Sbinkertn@umich.edu    for i,isa in enumerate(isas):
2814554Sbinkertn@umich.edu        code('#define $0 $1', define(isa), i + 1)
2824554Sbinkertn@umich.edu
2834554Sbinkertn@umich.edu    code('''
2844554Sbinkertn@umich.edu
2854554Sbinkertn@umich.edu#define THE_ISA ${{define(target_isa)}}
2864554Sbinkertn@umich.edu#define TheISA ${{namespace(target_isa)}}
2872667Sstever@eecs.umich.edu
2884554Sbinkertn@umich.edu#endif // __CONFIG_THE_ISA_HH__''')
2894554Sbinkertn@umich.edu
2904554Sbinkertn@umich.edu    code.write(str(target[0]))
2914554Sbinkertn@umich.edu
2922667Sstever@eecs.umich.eduenv.Command('config/the_isa.hh', map(Value, all_isa_list),
2934554Sbinkertn@umich.edu            MakeAction(makeTheISA, Transform("CFG ISA", 0)))
2942667Sstever@eecs.umich.edu
2954554Sbinkertn@umich.edu########################################################################
2964554Sbinkertn@umich.edu#
2972667Sstever@eecs.umich.edu# Prevent any SimObjects from being added after this point, they
2982638Sstever@eecs.umich.edu# should all have been added in the SConscripts above
2992638Sstever@eecs.umich.edu#
3002638Sstever@eecs.umich.eduSimObject.fixed = True
3013716Sstever@eecs.umich.edu
3023716Sstever@eecs.umich.educlass DictImporter(object):
3031858SN/A    '''This importer takes a dictionary of arbitrary module names that
3043118Sstever@eecs.umich.edu    map to arbitrary filenames.'''
3053118Sstever@eecs.umich.edu    def __init__(self, modules):
3063118Sstever@eecs.umich.edu        self.modules = modules
3073118Sstever@eecs.umich.edu        self.installed = set()
3083118Sstever@eecs.umich.edu
3093118Sstever@eecs.umich.edu    def __del__(self):
3103118Sstever@eecs.umich.edu        self.unload()
3113118Sstever@eecs.umich.edu
3123118Sstever@eecs.umich.edu    def unload(self):
3133118Sstever@eecs.umich.edu        import sys
3143118Sstever@eecs.umich.edu        for module in self.installed:
3153716Sstever@eecs.umich.edu            del sys.modules[module]
3163118Sstever@eecs.umich.edu        self.installed = set()
3173118Sstever@eecs.umich.edu
3183118Sstever@eecs.umich.edu    def find_module(self, fullname, path):
3193118Sstever@eecs.umich.edu        if fullname == 'm5.defines':
3203118Sstever@eecs.umich.edu            return self
3213118Sstever@eecs.umich.edu
3223118Sstever@eecs.umich.edu        if fullname == 'm5.objects':
3233118Sstever@eecs.umich.edu            return self
3243118Sstever@eecs.umich.edu
3253716Sstever@eecs.umich.edu        if fullname.startswith('m5.internal'):
3263118Sstever@eecs.umich.edu            return None
3273118Sstever@eecs.umich.edu
3283118Sstever@eecs.umich.edu        source = self.modules.get(fullname, None)
3293118Sstever@eecs.umich.edu        if source is not None and fullname.startswith('m5.objects'):
3303118Sstever@eecs.umich.edu            return self
3313118Sstever@eecs.umich.edu
3323118Sstever@eecs.umich.edu        return None
3333118Sstever@eecs.umich.edu
3343118Sstever@eecs.umich.edu    def load_module(self, fullname):
3353118Sstever@eecs.umich.edu        mod = imp.new_module(fullname)
3363483Ssaidi@eecs.umich.edu        sys.modules[fullname] = mod
3373494Ssaidi@eecs.umich.edu        self.installed.add(fullname)
3383494Ssaidi@eecs.umich.edu
3393483Ssaidi@eecs.umich.edu        mod.__loader__ = self
3403483Ssaidi@eecs.umich.edu        if fullname == 'm5.objects':
3413483Ssaidi@eecs.umich.edu            mod.__path__ = fullname.split('.')
3423053Sstever@eecs.umich.edu            return mod
3433053Sstever@eecs.umich.edu
3443918Ssaidi@eecs.umich.edu        if fullname == 'm5.defines':
3453053Sstever@eecs.umich.edu            mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env)
3463053Sstever@eecs.umich.edu            return mod
3473053Sstever@eecs.umich.edu
3483053Sstever@eecs.umich.edu        source = self.modules[fullname]
3493053Sstever@eecs.umich.edu        if source.modname == '__init__':
3501858SN/A            mod.__path__ = source.modpath
3511858SN/A        mod.__file__ = source.abspath
3521858SN/A
3531858SN/A        exec file(source.abspath, 'r') in mod.__dict__
3541858SN/A
3551858SN/A        return mod
3561859SN/A
3571858SN/Aimport m5.SimObject
3581858SN/Aimport m5.params
3591858SN/Afrom m5.util import code_formatter
3601859SN/A
3611859SN/Am5.SimObject.clear()
3621862SN/Am5.params.clear()
3633053Sstever@eecs.umich.edu
3643053Sstever@eecs.umich.edu# install the python importer so we can grab stuff from the source
3653053Sstever@eecs.umich.edu# tree itself.  We can't have SimObjects added after this point or
3663053Sstever@eecs.umich.edu# else we won't know about them for the rest of the stuff.
3671859SN/Aimporter = DictImporter(PySource.modules)
3681859SN/Asys.meta_path[0:0] = [ importer ]
3691859SN/A
3701859SN/A# import all sim objects so we can populate the all_objects list
3711859SN/A# make sure that we're working with a list, then let's sort it
3721859SN/Afor modname in SimObject.modnames:
3731859SN/A    exec('from m5.objects import %s' % modname)
3741859SN/A
3751862SN/A# we need to unload all of the currently imported modules so that they
3761859SN/A# will be re-imported the next time the sconscript is run
3771859SN/Aimporter.unload()
3781859SN/Asys.meta_path.remove(importer)
3791858SN/A
3801858SN/Asim_objects = m5.SimObject.allClasses
3812139SN/Aall_enums = m5.params.allEnums
3824202Sbinkertn@umich.edu
3834202Sbinkertn@umich.eduall_params = {}
3842139SN/Afor name,obj in sorted(sim_objects.iteritems()):
3852155SN/A    for param in obj._params.local.values():
3864202Sbinkertn@umich.edu        # load the ptype attribute now because it depends on the
3874202Sbinkertn@umich.edu        # current version of SimObject.allClasses, but when scons
3884202Sbinkertn@umich.edu        # actually uses the value, all versions of
3892155SN/A        # SimObject.allClasses will have been loaded
3901869SN/A        param.ptype
3911869SN/A
3921869SN/A        if not hasattr(param, 'swig_decl'):
3931869SN/A            continue
3944202Sbinkertn@umich.edu        pname = param.ptype_str
3954202Sbinkertn@umich.edu        if pname not in all_params:
3964202Sbinkertn@umich.edu            all_params[pname] = param
3974202Sbinkertn@umich.edu
3984202Sbinkertn@umich.edu########################################################################
3994202Sbinkertn@umich.edu#
4004202Sbinkertn@umich.edu# calculate extra dependencies
4014202Sbinkertn@umich.edu#
4024202Sbinkertn@umich.edumodule_depends = ["m5", "m5.SimObject", "m5.params"]
4034202Sbinkertn@umich.edudepends = [ PySource.modules[dep].snode for dep in module_depends ]
4044202Sbinkertn@umich.edu
4054202Sbinkertn@umich.edu########################################################################
4064202Sbinkertn@umich.edu#
4074202Sbinkertn@umich.edu# Commands for the basic automatically generated python files
4084202Sbinkertn@umich.edu#
4094202Sbinkertn@umich.edu
4101869SN/A# Generate Python file containing a dict specifying the current
4114202Sbinkertn@umich.edu# buildEnv flags.
4121869SN/Adef makeDefinesPyFile(target, source, env):
4132508SN/A    build_env, hg_info = [ x.get_contents() for x in source ]
4142508SN/A
4152508SN/A    code = code_formatter()
4162508SN/A    code("""
4174202Sbinkertn@umich.eduimport m5.internal
4181869SN/Aimport m5.util
4191869SN/A
4201869SN/AbuildEnv = m5.util.SmartDict($build_env)
4211869SN/AhgRev = '$hg_info'
4221869SN/A
4231869SN/AcompileDate = m5.internal.core.compileDate
4241965SN/A_globals = globals()
4251965SN/Afor key,val in m5.internal.core.__dict__.iteritems():
4261965SN/A    if key.startswith('flag_'):
4271869SN/A        flag = key[5:]
4281869SN/A        _globals[flag] = val
4292733Sktlim@umich.edudel _globals
4301869SN/A""")
4311884SN/A    code.write(target[0].abspath)
4321884SN/A
4333356Sbinkertn@umich.edudefines_info = [ Value(build_env), Value(env['HG_INFO']) ]
4343356Sbinkertn@umich.edu# Generate a file with all of the compile options in it
4353356Sbinkertn@umich.eduenv.Command('python/m5/defines.py', defines_info,
4363356Sbinkertn@umich.edu            MakeAction(makeDefinesPyFile, Transform("DEFINES", 0)))
4371869SN/APySource('m5', 'python/m5/defines.py')
4381858SN/A
4391869SN/A# Generate python file containing info about the M5 source code
4401869SN/Adef makeInfoPyFile(target, source, env):
4411869SN/A    code = code_formatter()
4421858SN/A    for src in source:
4432761Sstever@eecs.umich.edu        data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
4441869SN/A        code('$src = ${{repr(data)}}')
4452733Sktlim@umich.edu    code.write(str(target[0]))
4463584Ssaidi@eecs.umich.edu
4471869SN/A# Generate a file that wraps the basic top level files
4481869SN/Aenv.Command('python/m5/info.py',
4491869SN/A            [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ],
4501869SN/A            MakeAction(makeInfoPyFile, Transform("INFO")))
4511869SN/APySource('m5', 'python/m5/info.py')
4521869SN/A
4531858SN/A########################################################################
454955SN/A#
455955SN/A# Create all of the SimObject param headers and enum headers
4561869SN/A#
4571869SN/A
4581869SN/Adef createSimObjectParam(target, source, env):
4591869SN/A    assert len(target) == 1 and len(source) == 1
4601869SN/A
4611869SN/A    name = str(source[0].get_contents())
4621869SN/A    obj = sim_objects[name]
4631869SN/A
4641869SN/A    code = code_formatter()
4651869SN/A    obj.cxx_decl(code)
4661869SN/A    code.write(target[0].abspath)
4671869SN/A
4681869SN/Adef createSwigParam(target, source, env):
4691869SN/A    assert len(target) == 1 and len(source) == 1
4701869SN/A
4711869SN/A    name = str(source[0].get_contents())
4721869SN/A    param = all_params[name]
4731869SN/A
4741869SN/A    code = code_formatter()
4751869SN/A    code('%module(package="m5.internal") $0_${name}', param.file_ext)
4761869SN/A    param.swig_decl(code)
4771869SN/A    code.write(target[0].abspath)
4781869SN/A
4791869SN/Adef createEnumStrings(target, source, env):
4801869SN/A    assert len(target) == 1 and len(source) == 1
4811869SN/A
4821869SN/A    name = str(source[0].get_contents())
4831869SN/A    obj = all_enums[name]
4841869SN/A
4853716Sstever@eecs.umich.edu    code = code_formatter()
4863356Sbinkertn@umich.edu    obj.cxx_def(code)
4873356Sbinkertn@umich.edu    code.write(target[0].abspath)
4883356Sbinkertn@umich.edu
4893356Sbinkertn@umich.edudef createEnumParam(target, source, env):
4903356Sbinkertn@umich.edu    assert len(target) == 1 and len(source) == 1
4913356Sbinkertn@umich.edu
4923356Sbinkertn@umich.edu    name = str(source[0].get_contents())
4931869SN/A    obj = all_enums[name]
4941869SN/A
4951869SN/A    code = code_formatter()
4961869SN/A    obj.cxx_decl(code)
4971869SN/A    code.write(target[0].abspath)
4981869SN/A
4991869SN/Adef createEnumSwig(target, source, env):
5002655Sstever@eecs.umich.edu    assert len(target) == 1 and len(source) == 1
5012655Sstever@eecs.umich.edu
5022655Sstever@eecs.umich.edu    name = str(source[0].get_contents())
5032655Sstever@eecs.umich.edu    obj = all_enums[name]
5042655Sstever@eecs.umich.edu
5052655Sstever@eecs.umich.edu    code = code_formatter()
5062655Sstever@eecs.umich.edu    code('''\
5072655Sstever@eecs.umich.edu%module(package="m5.internal") enum_$name
5082655Sstever@eecs.umich.edu
5092655Sstever@eecs.umich.edu%{
5102655Sstever@eecs.umich.edu#include "enums/$name.hh"
5112655Sstever@eecs.umich.edu%}
5122655Sstever@eecs.umich.edu
5132655Sstever@eecs.umich.edu%include "enums/$name.hh"
5142655Sstever@eecs.umich.edu''')
5152655Sstever@eecs.umich.edu    code.write(target[0].abspath)
5162655Sstever@eecs.umich.edu
5172655Sstever@eecs.umich.edu# Generate all of the SimObject param struct header files
5182655Sstever@eecs.umich.eduparams_hh_files = []
5192655Sstever@eecs.umich.edufor name,simobj in sorted(sim_objects.iteritems()):
5202655Sstever@eecs.umich.edu    py_source = PySource.modules[simobj.__module__]
5212655Sstever@eecs.umich.edu    extra_deps = [ py_source.tnode ]
5222655Sstever@eecs.umich.edu
5232655Sstever@eecs.umich.edu    hh_file = File('params/%s.hh' % name)
5242655Sstever@eecs.umich.edu    params_hh_files.append(hh_file)
5252655Sstever@eecs.umich.edu    env.Command(hh_file, Value(name),
5262634Sstever@eecs.umich.edu                MakeAction(createSimObjectParam, Transform("SO PARAM")))
5272634Sstever@eecs.umich.edu    env.Depends(hh_file, depends + extra_deps)
5282634Sstever@eecs.umich.edu
5292634Sstever@eecs.umich.edu# Generate any parameter header files needed
5302634Sstever@eecs.umich.eduparams_i_files = []
5312634Sstever@eecs.umich.edufor name,param in all_params.iteritems():
5322638Sstever@eecs.umich.edu    i_file = File('python/m5/internal/%s_%s.i' % (param.file_ext, name))
5332638Sstever@eecs.umich.edu    params_i_files.append(i_file)
5343716Sstever@eecs.umich.edu    env.Command(i_file, Value(name),
5352638Sstever@eecs.umich.edu                MakeAction(createSwigParam, Transform("SW PARAM")))
5362638Sstever@eecs.umich.edu    env.Depends(i_file, depends)
5371869SN/A    SwigSource('m5.internal', i_file)
5381869SN/A
5393546Sgblack@eecs.umich.edu# Generate all enum header files
5403546Sgblack@eecs.umich.edufor name,enum in sorted(all_enums.iteritems()):
5413546Sgblack@eecs.umich.edu    py_source = PySource.modules[enum.__module__]
5423546Sgblack@eecs.umich.edu    extra_deps = [ py_source.tnode ]
5434202Sbinkertn@umich.edu
5443546Sgblack@eecs.umich.edu    cc_file = File('enums/%s.cc' % name)
5453546Sgblack@eecs.umich.edu    env.Command(cc_file, Value(name),
5463546Sgblack@eecs.umich.edu                MakeAction(createEnumStrings, Transform("ENUM STR")))
5473546Sgblack@eecs.umich.edu    env.Depends(cc_file, depends + extra_deps)
5483546Sgblack@eecs.umich.edu    Source(cc_file)
5493546Sgblack@eecs.umich.edu
5503546Sgblack@eecs.umich.edu    hh_file = File('enums/%s.hh' % name)
5513546Sgblack@eecs.umich.edu    env.Command(hh_file, Value(name),
5523546Sgblack@eecs.umich.edu                MakeAction(createEnumParam, Transform("EN PARAM")))
5533546Sgblack@eecs.umich.edu    env.Depends(hh_file, depends + extra_deps)
5544202Sbinkertn@umich.edu
5553546Sgblack@eecs.umich.edu    i_file = File('python/m5/internal/enum_%s.i' % name)
5563546Sgblack@eecs.umich.edu    env.Command(i_file, Value(name),
5573546Sgblack@eecs.umich.edu                MakeAction(createEnumSwig, Transform("ENUMSWIG")))
5583546Sgblack@eecs.umich.edu    env.Depends(i_file, depends + extra_deps)
5593546Sgblack@eecs.umich.edu    SwigSource('m5.internal', i_file)
5603546Sgblack@eecs.umich.edu
5613546Sgblack@eecs.umich.edudef buildParam(target, source, env):
5623546Sgblack@eecs.umich.edu    name = source[0].get_contents()
5633546Sgblack@eecs.umich.edu    obj = sim_objects[name]
5643546Sgblack@eecs.umich.edu    class_path = obj.cxx_class.split('::')
5653546Sgblack@eecs.umich.edu    classname = class_path[-1]
5663546Sgblack@eecs.umich.edu    namespaces = class_path[:-1]
5673546Sgblack@eecs.umich.edu    params = obj._params.local.values()
5683546Sgblack@eecs.umich.edu
5693546Sgblack@eecs.umich.edu    code = code_formatter()
5703546Sgblack@eecs.umich.edu
5713546Sgblack@eecs.umich.edu    code('%module(package="m5.internal") param_$name')
5723546Sgblack@eecs.umich.edu    code()
5733546Sgblack@eecs.umich.edu    code('%{')
5743546Sgblack@eecs.umich.edu    code('#include "params/$obj.hh"')
5754202Sbinkertn@umich.edu    for param in params:
5763546Sgblack@eecs.umich.edu        param.cxx_predecls(code)
5773546Sgblack@eecs.umich.edu    code('%}')
5783546Sgblack@eecs.umich.edu    code()
579955SN/A
580955SN/A    for param in params:
581955SN/A        param.swig_predecls(code)
582955SN/A
5831858SN/A    code()
5841858SN/A    if obj._base:
5851858SN/A        code('%import "python/m5/internal/param_${{obj._base}}.i"')
5862632Sstever@eecs.umich.edu    code()
5872632Sstever@eecs.umich.edu    obj.swig_objdecls(code)
5882632Sstever@eecs.umich.edu    code()
5892632Sstever@eecs.umich.edu
5902632Sstever@eecs.umich.edu    code('%include "params/$obj.hh"')
5912634Sstever@eecs.umich.edu
5922638Sstever@eecs.umich.edu    code.write(target[0].abspath)
5932023SN/A
5942632Sstever@eecs.umich.edufor name in sim_objects.iterkeys():
5952632Sstever@eecs.umich.edu    params_file = File('python/m5/internal/param_%s.i' % name)
5962632Sstever@eecs.umich.edu    env.Command(params_file, Value(name),
5972632Sstever@eecs.umich.edu                MakeAction(buildParam, Transform("BLDPARAM")))
5982632Sstever@eecs.umich.edu    env.Depends(params_file, depends)
5993716Sstever@eecs.umich.edu    SwigSource('m5.internal', params_file)
6002632Sstever@eecs.umich.edu
6012632Sstever@eecs.umich.edu# Generate the main swig init file
6022632Sstever@eecs.umich.edudef makeEmbeddedSwigInit(target, source, env):
6032632Sstever@eecs.umich.edu    code = code_formatter()
6042632Sstever@eecs.umich.edu    module = source[0].get_contents()
6052023SN/A    code('''\
6062632Sstever@eecs.umich.edu#include "sim/init.hh"
6072632Sstever@eecs.umich.edu
6081889SN/Aextern "C" {
6091889SN/A    void init_${module}();
6102632Sstever@eecs.umich.edu}
6112632Sstever@eecs.umich.edu
6122632Sstever@eecs.umich.eduEmbeddedSwig embed_swig_${module}(init_${module});
6132632Sstever@eecs.umich.edu''')
6143716Sstever@eecs.umich.edu    code.write(str(target[0]))
6153716Sstever@eecs.umich.edu    
6162632Sstever@eecs.umich.edu# Build all swig modules
6172632Sstever@eecs.umich.edufor swig in SwigSource.all:
6182632Sstever@eecs.umich.edu    env.Command([swig.cc_source.tnode, swig.py_source.tnode], swig.tnode,
6192632Sstever@eecs.umich.edu                MakeAction('$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
6202632Sstever@eecs.umich.edu                '-o ${TARGETS[0]} $SOURCES', Transform("SWIG")))
6212632Sstever@eecs.umich.edu    init_file = 'python/swig/init_%s.cc' % swig.module
6222632Sstever@eecs.umich.edu    env.Command(init_file, Value(swig.module),
6232632Sstever@eecs.umich.edu                MakeAction(makeEmbeddedSwigInit, Transform("EMBED SW")))
6241888SN/A    Source(init_file)
6251888SN/A
6261869SN/Adef getFlags(source_flags):
6271869SN/A    flagsMap = {}
6281858SN/A    flagsList = []
6292598SN/A    for s in source_flags:
6302598SN/A        val = eval(s.get_contents())
6312598SN/A        name, compound, desc = val
6322598SN/A        flagsList.append(val)
6332598SN/A        flagsMap[name] = bool(compound)
6341858SN/A    
6351858SN/A    for name, compound, desc in flagsList:
6361858SN/A        for flag in compound:
6371858SN/A            if flag not in flagsMap:
6381858SN/A                raise AttributeError, "Trace flag %s not found" % flag
6391858SN/A            if flagsMap[flag]:
6401858SN/A                raise AttributeError, \
6411858SN/A                    "Compound flag can't point to another compound flag"
6421858SN/A
6431871SN/A    flagsList.sort()
6441858SN/A    return flagsList
6451858SN/A
6461858SN/A
6471858SN/A# Generate traceflags.py
6481858SN/Adef traceFlagsPy(target, source, env):
6491858SN/A    assert(len(target) == 1)
6501858SN/A    code = code_formatter()
6511858SN/A
6521858SN/A    allFlags = getFlags(source)
6531858SN/A
6541858SN/A    code('basic = [')
6551859SN/A    code.indent()
6561859SN/A    for flag, compound, desc in allFlags:
6571869SN/A        if not compound:
6581888SN/A            code("'$flag',")
6592632Sstever@eecs.umich.edu    code(']')
6601869SN/A    code.dedent()
6611884SN/A    code()
6621884SN/A
6631884SN/A    code('compound = [')
6641884SN/A    code.indent()
6651884SN/A    code("'All',")
6661884SN/A    for flag, compound, desc in allFlags:
6671965SN/A        if compound:
6681965SN/A            code("'$flag',")
6691965SN/A    code("]")
6702761Sstever@eecs.umich.edu    code.dedent()
6711869SN/A    code()
6721869SN/A
6732632Sstever@eecs.umich.edu    code("all = frozenset(basic + compound)")
6742667Sstever@eecs.umich.edu    code()
6751869SN/A
6761869SN/A    code('compoundMap = {')
6772929Sktlim@umich.edu    code.indent()
6782929Sktlim@umich.edu    all = tuple([flag for flag,compound,desc in allFlags if not compound])
6793716Sstever@eecs.umich.edu    code("'All' : $all,")
6802929Sktlim@umich.edu    for flag, compound, desc in allFlags:
681955SN/A        if compound:
6822598SN/A            code("'$flag' : $compound,")
6832598SN/A    code('}')
6843546Sgblack@eecs.umich.edu    code.dedent()
685955SN/A    code()
686955SN/A
687955SN/A    code('descriptions = {')
6881530SN/A    code.indent()
689955SN/A    code("'All' : 'All flags',")
690955SN/A    for flag, compound, desc in allFlags:
691955SN/A        code("'$flag' : '$desc',")
692    code("}")
693    code.dedent()
694
695    code.write(str(target[0]))
696
697def traceFlagsCC(target, source, env):
698    assert(len(target) == 1)
699
700    allFlags = getFlags(source)
701    code = code_formatter()
702
703    # file header
704    code('''
705/*
706 * DO NOT EDIT THIS FILE! Automatically generated
707 */
708
709#include "base/traceflags.hh"
710
711using namespace Trace;
712
713const char *Trace::flagStrings[] =
714{''')
715
716    code.indent()
717    # The string array is used by SimpleEnumParam to map the strings
718    # provided by the user to enum values.
719    for flag, compound, desc in allFlags:
720        if not compound:
721            code('"$flag",')
722
723    code('"All",')
724    for flag, compound, desc in allFlags:
725        if compound:
726            code('"$flag",')
727    code.dedent()
728
729    code('''\
730};
731
732const int Trace::numFlagStrings = ${{len(allFlags) + 1}};
733
734''')
735
736    # Now define the individual compound flag arrays.  There is an array
737    # for each compound flag listing the component base flags.
738    all = tuple([flag for flag,compound,desc in allFlags if not compound])
739    code('static const Flags AllMap[] = {')
740    code.indent()
741    for flag, compound, desc in allFlags:
742        if not compound:
743            code('$flag,')
744    code.dedent()
745    code('};')
746    code()
747
748    for flag, compound, desc in allFlags:
749        if not compound:
750            continue
751        code('static const Flags ${flag}Map[] = {')
752        code.indent()
753        for flag in compound:
754            code('$flag,')
755        code('(Flags)-1')
756        code.dedent()
757        code('};')
758        code()
759
760    # Finally the compoundFlags[] array maps the compound flags
761    # to their individual arrays/
762    code('const Flags *Trace::compoundFlags[] = {')
763    code.indent()
764    code('AllMap,')
765    for flag, compound, desc in allFlags:
766        if compound:
767            code('${flag}Map,')
768    # file trailer
769    code.dedent()
770    code('};')
771
772    code.write(str(target[0]))
773
774def traceFlagsHH(target, source, env):
775    assert(len(target) == 1)
776
777    allFlags = getFlags(source)
778    code = code_formatter()
779
780    # file header boilerplate
781    code('''\
782/*
783 * DO NOT EDIT THIS FILE!
784 *
785 * Automatically generated from traceflags.py
786 */
787
788#ifndef __BASE_TRACE_FLAGS_HH__
789#define __BASE_TRACE_FLAGS_HH__
790
791namespace Trace {
792
793enum Flags {''')
794
795    # Generate the enum.  Base flags come first, then compound flags.
796    idx = 0
797    code.indent()
798    for flag, compound, desc in allFlags:
799        if not compound:
800            code('$flag = $idx,')
801            idx += 1
802
803    numBaseFlags = idx
804    code('NumFlags = $idx,')
805    code.dedent()
806    code()
807
808    # put a comment in here to separate base from compound flags
809    code('''
810// The remaining enum values are *not* valid indices for Trace::flags.
811// They are "compound" flags, which correspond to sets of base
812// flags, and are used by changeFlag.''')
813
814    code.indent()
815    code('All = $idx,')
816    idx += 1
817    for flag, compound, desc in allFlags:
818        if compound:
819            code('$flag = $idx,')
820            idx += 1
821
822    numCompoundFlags = idx - numBaseFlags
823    code('NumCompoundFlags = $numCompoundFlags')
824    code.dedent()
825
826    # trailer boilerplate
827    code('''\
828}; // enum Flags
829
830// Array of strings for SimpleEnumParam
831extern const char *flagStrings[];
832extern const int numFlagStrings;
833
834// Array of arraay pointers: for each compound flag, gives the list of
835// base flags to set.  Inidividual flag arrays are terminated by -1.
836extern const Flags *compoundFlags[];
837
838} // namespace Trace
839
840#endif // __BASE_TRACE_FLAGS_HH__
841''')
842
843    code.write(str(target[0]))
844
845flags = map(Value, trace_flags.values())
846env.Command('base/traceflags.py', flags, 
847            MakeAction(traceFlagsPy, Transform("TRACING", 0)))
848PySource('m5', 'base/traceflags.py')
849
850env.Command('base/traceflags.hh', flags,
851            MakeAction(traceFlagsHH, Transform("TRACING", 0)))
852env.Command('base/traceflags.cc', flags, 
853            MakeAction(traceFlagsCC, Transform("TRACING", 0)))
854Source('base/traceflags.cc')
855
856# Embed python files.  All .py files that have been indicated by a
857# PySource() call in a SConscript need to be embedded into the M5
858# library.  To do that, we compile the file to byte code, marshal the
859# byte code, compress it, and then generate a c++ file that
860# inserts the result into an array.
861def embedPyFile(target, source, env):
862    def c_str(string):
863        if string is None:
864            return "0"
865        return '"%s"' % string
866
867    '''Action function to compile a .py into a code object, marshal
868    it, compress it, and stick it into an asm file so the code appears
869    as just bytes with a label in the data section'''
870
871    src = file(str(source[0]), 'r').read()
872
873    pysource = PySource.tnodes[source[0]]
874    compiled = compile(src, pysource.abspath, 'exec')
875    marshalled = marshal.dumps(compiled)
876    compressed = zlib.compress(marshalled)
877    data = compressed
878    sym = pysource.symname
879
880    code = code_formatter()
881    code('''\
882#include "sim/init.hh"
883
884namespace {
885
886const char data_${sym}[] = {
887''')
888    code.indent()
889    step = 16
890    for i in xrange(0, len(data), step):
891        x = array.array('B', data[i:i+step])
892        code(''.join('%d,' % d for d in x))
893    code.dedent()
894    
895    code('''};
896
897EmbeddedPython embedded_${sym}(
898    ${{c_str(pysource.arcname)}},
899    ${{c_str(pysource.abspath)}},
900    ${{c_str(pysource.modpath)}},
901    data_${sym},
902    ${{len(data)}},
903    ${{len(marshalled)}});
904
905} // anonymous namespace
906''')
907    code.write(str(target[0]))
908
909for source in PySource.all:
910    env.Command(source.cpp, source.tnode, 
911                MakeAction(embedPyFile, Transform("EMBED PY")))
912    Source(source.cpp)
913
914########################################################################
915#
916# Define binaries.  Each different build type (debug, opt, etc.) gets
917# a slightly different build environment.
918#
919
920# List of constructed environments to pass back to SConstruct
921envList = []
922
923date_source = Source('base/date.cc', skip_lib=True)
924
925# Function to create a new build environment as clone of current
926# environment 'env' with modified object suffix and optional stripped
927# binary.  Additional keyword arguments are appended to corresponding
928# build environment vars.
929def makeEnv(label, objsfx, strip = False, **kwargs):
930    # SCons doesn't know to append a library suffix when there is a '.' in the
931    # name.  Use '_' instead.
932    libname = 'm5_' + label
933    exename = 'm5.' + label
934
935    new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's')
936    new_env.Label = label
937    new_env.Append(**kwargs)
938
939    swig_env = new_env.Clone()
940    swig_env.Append(CCFLAGS='-Werror')
941    if env['GCC']:
942        swig_env.Append(CCFLAGS='-Wno-uninitialized')
943        swig_env.Append(CCFLAGS='-Wno-sign-compare')
944        swig_env.Append(CCFLAGS='-Wno-parentheses')
945
946    werror_env = new_env.Clone()
947    werror_env.Append(CCFLAGS='-Werror')
948
949    def make_obj(source, static, extra_deps = None):
950        '''This function adds the specified source to the correct
951        build environment, and returns the corresponding SCons Object
952        nodes'''
953
954        if source.swig:
955            env = swig_env
956        elif source.Werror:
957            env = werror_env
958        else:
959            env = new_env
960
961        if static:
962            obj = env.StaticObject(source.tnode)
963        else:
964            obj = env.SharedObject(source.tnode)
965
966        if extra_deps:
967            env.Depends(obj, extra_deps)
968
969        return obj
970
971    static_objs = [ make_obj(s, True) for s in Source.get(skip_lib=False)]
972    shared_objs = [ make_obj(s, False) for s in Source.get(skip_lib=False)]
973
974    static_date = make_obj(date_source, static=True, extra_deps=static_objs)
975    static_objs.append(static_date)
976    
977    shared_date = make_obj(date_source, static=False, extra_deps=shared_objs)
978    shared_objs.append(shared_date)
979
980    # First make a library of everything but main() so other programs can
981    # link against m5.
982    static_lib = new_env.StaticLibrary(libname, static_objs)
983    shared_lib = new_env.SharedLibrary(libname, shared_objs)
984
985    for target, sources in unit_tests:
986        objs = [ make_obj(s, static=True) for s in sources ]
987        new_env.Program("unittest/%s.%s" % (target, label), objs + static_objs)
988
989    # Now link a stub with main() and the static library.
990    bin_objs = [make_obj(s, True) for s in Source.get(bin_only=True) ]
991    progname = exename
992    if strip:
993        progname += '.unstripped'
994
995    targets = new_env.Program(progname, bin_objs + static_objs)
996
997    if strip:
998        if sys.platform == 'sunos5':
999            cmd = 'cp $SOURCE $TARGET; strip $TARGET'
1000        else:
1001            cmd = 'strip $SOURCE -o $TARGET'
1002        targets = new_env.Command(exename, progname,
1003                    MakeAction(cmd, Transform("STRIP")))
1004            
1005    new_env.M5Binary = targets[0]
1006    envList.append(new_env)
1007
1008# Debug binary
1009ccflags = {}
1010if env['GCC']:
1011    if sys.platform == 'sunos5':
1012        ccflags['debug'] = '-gstabs+'
1013    else:
1014        ccflags['debug'] = '-ggdb3'
1015    ccflags['opt'] = '-g -O3'
1016    ccflags['fast'] = '-O3'
1017    ccflags['prof'] = '-O3 -g -pg'
1018elif env['SUNCC']:
1019    ccflags['debug'] = '-g0'
1020    ccflags['opt'] = '-g -O'
1021    ccflags['fast'] = '-fast'
1022    ccflags['prof'] = '-fast -g -pg'
1023elif env['ICC']:
1024    ccflags['debug'] = '-g -O0'
1025    ccflags['opt'] = '-g -O'
1026    ccflags['fast'] = '-fast'
1027    ccflags['prof'] = '-fast -g -pg'
1028else:
1029    print 'Unknown compiler, please fix compiler options'
1030    Exit(1)
1031
1032makeEnv('debug', '.do',
1033        CCFLAGS = Split(ccflags['debug']),
1034        CPPDEFINES = ['DEBUG', 'TRACING_ON=1'])
1035
1036# Optimized binary
1037makeEnv('opt', '.o',
1038        CCFLAGS = Split(ccflags['opt']),
1039        CPPDEFINES = ['TRACING_ON=1'])
1040
1041# "Fast" binary
1042makeEnv('fast', '.fo', strip = True,
1043        CCFLAGS = Split(ccflags['fast']),
1044        CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'])
1045
1046# Profiled binary
1047makeEnv('prof', '.po',
1048        CCFLAGS = Split(ccflags['prof']),
1049        CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
1050        LINKFLAGS = '-pg')
1051
1052Return('envList')
1053