SConscript revision 13730
1955SN/A# -*- mode:python -*-
2955SN/A
311408Sandreas.sandberg@arm.com# Copyright (c) 2018 ARM Limited
49812Sandreas.hansson@arm.com#
59812Sandreas.hansson@arm.com# The license below extends only to copyright in the software and shall
69812Sandreas.hansson@arm.com# not be construed as granting a license to any other intellectual
79812Sandreas.hansson@arm.com# property including but not limited to intellectual property relating
89812Sandreas.hansson@arm.com# to a hardware implementation of the functionality of the software
99812Sandreas.hansson@arm.com# licensed hereunder.  You may use the software subject to the license
109812Sandreas.hansson@arm.com# terms below provided that you ensure that this notice is replicated
119812Sandreas.hansson@arm.com# unmodified and in its entirety in all distributions of the software,
129812Sandreas.hansson@arm.com# modified or unmodified, in source code or in binary form.
139812Sandreas.hansson@arm.com#
149812Sandreas.hansson@arm.com# Copyright (c) 2004-2005 The Regents of The University of Michigan
157816Ssteve.reinhardt@amd.com# All rights reserved.
165871Snate@binkert.org#
171762SN/A# Redistribution and use in source and binary forms, with or without
18955SN/A# modification, are permitted provided that the following conditions are
19955SN/A# met: redistributions of source code must retain the above copyright
20955SN/A# notice, this list of conditions and the following disclaimer;
21955SN/A# redistributions in binary form must reproduce the above copyright
22955SN/A# notice, this list of conditions and the following disclaimer in the
23955SN/A# documentation and/or other materials provided with the distribution;
24955SN/A# neither the name of the copyright holders nor the names of its
25955SN/A# contributors may be used to endorse or promote products derived from
26955SN/A# this software without specific prior written permission.
27955SN/A#
28955SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29955SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30955SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31955SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32955SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33955SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34955SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35955SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36955SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37955SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38955SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39955SN/A#
40955SN/A# Authors: Nathan Binkert
41955SN/A
422665Ssaidi@eecs.umich.edufrom __future__ import print_function
432665Ssaidi@eecs.umich.edu
445863Snate@binkert.orgimport array
45955SN/Aimport bisect
46955SN/Aimport functools
47955SN/Aimport imp
48955SN/Aimport os
49955SN/Aimport re
508878Ssteve.reinhardt@amd.comimport sys
512632Sstever@eecs.umich.eduimport zlib
528878Ssteve.reinhardt@amd.com
532632Sstever@eecs.umich.edufrom os.path import basename, dirname, exists, isdir, isfile, join as joinpath
54955SN/A
558878Ssteve.reinhardt@amd.comimport SCons
562632Sstever@eecs.umich.edu
572761Sstever@eecs.umich.edufrom gem5_scons import Transform
582632Sstever@eecs.umich.edu
592632Sstever@eecs.umich.edu# This file defines how to build a particular configuration of gem5
602632Sstever@eecs.umich.edu# based on variable settings in the 'env' build environment.
612761Sstever@eecs.umich.edu
622761Sstever@eecs.umich.eduImport('*')
632761Sstever@eecs.umich.edu
648878Ssteve.reinhardt@amd.com# Children need to see the environment
658878Ssteve.reinhardt@amd.comExport('env')
662761Sstever@eecs.umich.edu
672761Sstever@eecs.umich.edubuild_env = [(opt, env[opt]) for opt in export_vars]
682761Sstever@eecs.umich.edu
692761Sstever@eecs.umich.edufrom m5.util import code_formatter, compareVersions
702761Sstever@eecs.umich.edu
718878Ssteve.reinhardt@amd.com########################################################################
728878Ssteve.reinhardt@amd.com# Code for adding source files of various types
732632Sstever@eecs.umich.edu#
742632Sstever@eecs.umich.edu# When specifying a source file of some type, a set of tags can be
758878Ssteve.reinhardt@amd.com# specified for that file.
768878Ssteve.reinhardt@amd.com
772632Sstever@eecs.umich.educlass SourceFilter(object):
78955SN/A    def __init__(self, predicate):
79955SN/A        self.predicate = predicate
80955SN/A
815863Snate@binkert.org    def __or__(self, other):
825863Snate@binkert.org        return SourceFilter(lambda tags: self.predicate(tags) or
835863Snate@binkert.org                                         other.predicate(tags))
845863Snate@binkert.org
855863Snate@binkert.org    def __and__(self, other):
865863Snate@binkert.org        return SourceFilter(lambda tags: self.predicate(tags) and
875863Snate@binkert.org                                         other.predicate(tags))
885863Snate@binkert.org
895863Snate@binkert.orgdef with_tags_that(predicate):
905863Snate@binkert.org    '''Return a list of sources with tags that satisfy a predicate.'''
915863Snate@binkert.org    return SourceFilter(predicate)
928878Ssteve.reinhardt@amd.com
935863Snate@binkert.orgdef with_any_tags(*tags):
945863Snate@binkert.org    '''Return a list of sources with any of the supplied tags.'''
955863Snate@binkert.org    return SourceFilter(lambda stags: len(set(tags) & stags) > 0)
969812Sandreas.hansson@arm.com
979812Sandreas.hansson@arm.comdef with_all_tags(*tags):
985863Snate@binkert.org    '''Return a list of sources with all of the supplied tags.'''
999812Sandreas.hansson@arm.com    return SourceFilter(lambda stags: set(tags) <= stags)
1005863Snate@binkert.org
1015863Snate@binkert.orgdef with_tag(tag):
1025863Snate@binkert.org    '''Return a list of sources with the supplied tag.'''
1039812Sandreas.hansson@arm.com    return SourceFilter(lambda stags: tag in stags)
1049812Sandreas.hansson@arm.com
1055863Snate@binkert.orgdef without_tags(*tags):
1065863Snate@binkert.org    '''Return a list of sources without any of the supplied tags.'''
1078878Ssteve.reinhardt@amd.com    return SourceFilter(lambda stags: len(set(tags) & stags) == 0)
1085863Snate@binkert.org
1095863Snate@binkert.orgdef without_tag(tag):
1105863Snate@binkert.org    '''Return a list of sources with the supplied tag.'''
1116654Snate@binkert.org    return SourceFilter(lambda stags: tag not in stags)
11210196SCurtis.Dunham@arm.com
113955SN/Asource_filter_factories = {
1145396Ssaidi@eecs.umich.edu    'with_tags_that': with_tags_that,
11511401Sandreas.sandberg@arm.com    'with_any_tags': with_any_tags,
1165863Snate@binkert.org    'with_all_tags': with_all_tags,
1175863Snate@binkert.org    'with_tag': with_tag,
1184202Sbinkertn@umich.edu    'without_tags': without_tags,
1195863Snate@binkert.org    'without_tag': without_tag,
1205863Snate@binkert.org}
1215863Snate@binkert.org
1225863Snate@binkert.orgExport(source_filter_factories)
123955SN/A
1246654Snate@binkert.orgclass SourceList(list):
1255273Sstever@gmail.com    def apply_filter(self, f):
1265871Snate@binkert.org        def match(source):
1275273Sstever@gmail.com            return f.predicate(source.tags)
1286655Snate@binkert.org        return SourceList(filter(match, self))
1298878Ssteve.reinhardt@amd.com
1306655Snate@binkert.org    def __getattr__(self, name):
1316655Snate@binkert.org        func = source_filter_factories.get(name, None)
1329219Spower.jg@gmail.com        if not func:
1336655Snate@binkert.org            raise AttributeError
1345871Snate@binkert.org
1356654Snate@binkert.org        @functools.wraps(func)
1368947Sandreas.hansson@arm.com        def wrapper(*args, **kwargs):
1375396Ssaidi@eecs.umich.edu            return self.apply_filter(func(*args, **kwargs))
1388120Sgblack@eecs.umich.edu        return wrapper
1398120Sgblack@eecs.umich.edu
1408120Sgblack@eecs.umich.educlass SourceMeta(type):
1418120Sgblack@eecs.umich.edu    '''Meta class for source files that keeps track of all files of a
1428120Sgblack@eecs.umich.edu    particular type.'''
1438120Sgblack@eecs.umich.edu    def __init__(cls, name, bases, dict):
1448120Sgblack@eecs.umich.edu        super(SourceMeta, cls).__init__(name, bases, dict)
1458120Sgblack@eecs.umich.edu        cls.all = SourceList()
1468879Ssteve.reinhardt@amd.com
1478879Ssteve.reinhardt@amd.comclass SourceFile(object):
1488879Ssteve.reinhardt@amd.com    '''Base object that encapsulates the notion of a source file.
1498879Ssteve.reinhardt@amd.com    This includes, the source node, target node, various manipulations
1508879Ssteve.reinhardt@amd.com    of those.  A source file also specifies a set of tags which
1518879Ssteve.reinhardt@amd.com    describing arbitrary properties of the source file.'''
1528879Ssteve.reinhardt@amd.com    __metaclass__ = SourceMeta
1538879Ssteve.reinhardt@amd.com
1548879Ssteve.reinhardt@amd.com    static_objs = {}
1558879Ssteve.reinhardt@amd.com    shared_objs = {}
1568879Ssteve.reinhardt@amd.com
1578879Ssteve.reinhardt@amd.com    def __init__(self, source, tags=None, add_tags=None):
1588879Ssteve.reinhardt@amd.com        if tags is None:
1598120Sgblack@eecs.umich.edu            tags='gem5 lib'
1608120Sgblack@eecs.umich.edu        if isinstance(tags, basestring):
1618120Sgblack@eecs.umich.edu            tags = set([tags])
1628120Sgblack@eecs.umich.edu        if not isinstance(tags, set):
1638120Sgblack@eecs.umich.edu            tags = set(tags)
1648120Sgblack@eecs.umich.edu        self.tags = tags
1658120Sgblack@eecs.umich.edu
1668120Sgblack@eecs.umich.edu        if add_tags:
1678120Sgblack@eecs.umich.edu            if isinstance(add_tags, basestring):
1688120Sgblack@eecs.umich.edu                add_tags = set([add_tags])
1698120Sgblack@eecs.umich.edu            if not isinstance(add_tags, set):
1708120Sgblack@eecs.umich.edu                add_tags = set(add_tags)
1718120Sgblack@eecs.umich.edu            self.tags |= add_tags
1728120Sgblack@eecs.umich.edu
1738879Ssteve.reinhardt@amd.com        tnode = source
1748879Ssteve.reinhardt@amd.com        if not isinstance(source, SCons.Node.FS.File):
1758879Ssteve.reinhardt@amd.com            tnode = File(source)
1768879Ssteve.reinhardt@amd.com
17710458Sandreas.hansson@arm.com        self.tnode = tnode
17810458Sandreas.hansson@arm.com        self.snode = tnode.srcnode()
17910458Sandreas.hansson@arm.com
1808879Ssteve.reinhardt@amd.com        for base in type(self).__mro__:
1818879Ssteve.reinhardt@amd.com            if issubclass(base, SourceFile):
1828879Ssteve.reinhardt@amd.com                base.all.append(self)
1838879Ssteve.reinhardt@amd.com
1849227Sandreas.hansson@arm.com    def static(self, env):
1859227Sandreas.hansson@arm.com        key = (self.tnode, env['OBJSUFFIX'])
18612063Sgabeblack@google.com        if not key in self.static_objs:
18712063Sgabeblack@google.com            self.static_objs[key] = env.StaticObject(self.tnode)
18812063Sgabeblack@google.com        return self.static_objs[key]
1898879Ssteve.reinhardt@amd.com
1908879Ssteve.reinhardt@amd.com    def shared(self, env):
1918879Ssteve.reinhardt@amd.com        key = (self.tnode, env['OBJSUFFIX'])
1928879Ssteve.reinhardt@amd.com        if not key in self.shared_objs:
19310453SAndrew.Bardsley@arm.com            self.shared_objs[key] = env.SharedObject(self.tnode)
19410453SAndrew.Bardsley@arm.com        return self.shared_objs[key]
19510453SAndrew.Bardsley@arm.com
19610456SCurtis.Dunham@arm.com    @property
19710456SCurtis.Dunham@arm.com    def filename(self):
19810456SCurtis.Dunham@arm.com        return str(self.tnode)
19910457Sandreas.hansson@arm.com
20010457Sandreas.hansson@arm.com    @property
20111342Sandreas.hansson@arm.com    def dirname(self):
20211342Sandreas.hansson@arm.com        return dirname(self.filename)
2038120Sgblack@eecs.umich.edu
20412063Sgabeblack@google.com    @property
20512063Sgabeblack@google.com    def basename(self):
20612063Sgabeblack@google.com        return basename(self.filename)
20712063Sgabeblack@google.com
2088947Sandreas.hansson@arm.com    @property
2097816Ssteve.reinhardt@amd.com    def extname(self):
2105871Snate@binkert.org        index = self.basename.rfind('.')
2115871Snate@binkert.org        if index <= 0:
2126121Snate@binkert.org            # dot files aren't extensions
2135871Snate@binkert.org            return self.basename, None
2145871Snate@binkert.org
2159926Sstan.czerniawski@arm.com        return self.basename[:index], self.basename[index+1:]
2169926Sstan.czerniawski@arm.com
2179119Sandreas.hansson@arm.com    def __lt__(self, other): return self.filename < other.filename
21810068Sandreas.hansson@arm.com    def __le__(self, other): return self.filename <= other.filename
21911989Sandreas.sandberg@arm.com    def __gt__(self, other): return self.filename > other.filename
220955SN/A    def __ge__(self, other): return self.filename >= other.filename
2219416SAndreas.Sandberg@ARM.com    def __eq__(self, other): return self.filename == other.filename
22211342Sandreas.hansson@arm.com    def __ne__(self, other): return self.filename != other.filename
22311212Sjoseph.gross@amd.com
22411212Sjoseph.gross@amd.comdef blobToCpp(data, symbol, cpp_code, hpp_code=None, namespace=None):
22511212Sjoseph.gross@amd.com    '''
22611212Sjoseph.gross@amd.com    Convert bytes data into C++ .cpp and .hh uint8_t byte array
22711212Sjoseph.gross@amd.com    code containing that binary data.
2289416SAndreas.Sandberg@ARM.com
2299416SAndreas.Sandberg@ARM.com    :param data: binary data to be converted to C++
2305871Snate@binkert.org    :param symbol: name of the symbol
23110584Sandreas.hansson@arm.com    :param cpp_code: append the generated cpp_code to this object
2329416SAndreas.Sandberg@ARM.com    :param hpp_code: append the generated hpp_code to this object
2339416SAndreas.Sandberg@ARM.com                     If None, ignore it. Otherwise, also include it
2345871Snate@binkert.org                     in the .cpp file.
235955SN/A    :param namespace: namespace to put the symbol into. If None,
23610671Sandreas.hansson@arm.com                      don't put the symbols into any namespace.
23710671Sandreas.hansson@arm.com    '''
23810671Sandreas.hansson@arm.com    symbol_len_declaration = 'const std::size_t {}_len'.format(symbol)
23910671Sandreas.hansson@arm.com    symbol_declaration = 'const std::uint8_t {}[]'.format(symbol)
2408881Smarc.orr@gmail.com    if hpp_code is not None:
2416121Snate@binkert.org        cpp_code('''\
2426121Snate@binkert.org#include "blobs/{}.hh"
2431533SN/A'''.format(symbol))
2449239Sandreas.hansson@arm.com        hpp_code('''\
2459239Sandreas.hansson@arm.com#include <cstddef>
2469239Sandreas.hansson@arm.com#include <cstdint>
2479239Sandreas.hansson@arm.com''')
2489239Sandreas.hansson@arm.com        if namespace is not None:
2499239Sandreas.hansson@arm.com            hpp_code('namespace {} {{'.format(namespace))
2509239Sandreas.hansson@arm.com        hpp_code('extern ' + symbol_len_declaration + ';')
2516655Snate@binkert.org        hpp_code('extern ' + symbol_declaration + ';')
2526655Snate@binkert.org        if namespace is not None:
2536655Snate@binkert.org            hpp_code('}')
2546655Snate@binkert.org    if namespace is not None:
2555871Snate@binkert.org        cpp_code('namespace {} {{'.format(namespace))
2565871Snate@binkert.org    if hpp_code is not None:
2575863Snate@binkert.org        cpp_code(symbol_len_declaration + ' = {};'.format(len(data)))
2585871Snate@binkert.org    cpp_code(symbol_declaration + ' = {')
2598878Ssteve.reinhardt@amd.com    cpp_code.indent()
2605871Snate@binkert.org    step = 16
2615871Snate@binkert.org    for i in xrange(0, len(data), step):
2625871Snate@binkert.org        x = array.array('B', data[i:i+step])
2635863Snate@binkert.org        cpp_code(''.join('%d,' % d for d in x))
2646121Snate@binkert.org    cpp_code.dedent()
2655863Snate@binkert.org    cpp_code('};')
26611408Sandreas.sandberg@arm.com    if namespace is not None:
26711408Sandreas.sandberg@arm.com        cpp_code('}')
2688336Ssteve.reinhardt@amd.com
26911469SCurtis.Dunham@arm.comdef Blob(blob_path, symbol):
27011469SCurtis.Dunham@arm.com    '''
2718336Ssteve.reinhardt@amd.com    Embed an arbitrary blob into the gem5 executable,
2724678Snate@binkert.org    and make it accessible to C++ as a byte array.
27311887Sandreas.sandberg@arm.com    '''
27411887Sandreas.sandberg@arm.com    blob_path = os.path.abspath(blob_path)
27511887Sandreas.sandberg@arm.com    blob_out_dir = os.path.join(env['BUILDDIR'], 'blobs')
27611887Sandreas.sandberg@arm.com    path_noext = joinpath(blob_out_dir, symbol)
27711887Sandreas.sandberg@arm.com    cpp_path = path_noext + '.cc'
27811887Sandreas.sandberg@arm.com    hpp_path = path_noext + '.hh'
27911887Sandreas.sandberg@arm.com    def embedBlob(target, source, env):
28011887Sandreas.sandberg@arm.com        data = file(str(source[0]), 'r').read()
28111887Sandreas.sandberg@arm.com        cpp_code = code_formatter()
28211887Sandreas.sandberg@arm.com        hpp_code = code_formatter()
28311887Sandreas.sandberg@arm.com        blobToCpp(data, symbol, cpp_code, hpp_code, namespace='Blobs')
28411408Sandreas.sandberg@arm.com        cpp_path = str(target[0])
28511401Sandreas.sandberg@arm.com        hpp_path = str(target[1])
28611401Sandreas.sandberg@arm.com        cpp_dir = os.path.split(cpp_path)[0]
28711401Sandreas.sandberg@arm.com        if not os.path.exists(cpp_dir):
28811401Sandreas.sandberg@arm.com            os.makedirs(cpp_dir)
28911401Sandreas.sandberg@arm.com        cpp_code.write(cpp_path)
29011401Sandreas.sandberg@arm.com        hpp_code.write(hpp_path)
2918336Ssteve.reinhardt@amd.com    env.Command([cpp_path, hpp_path], blob_path,
2928336Ssteve.reinhardt@amd.com                MakeAction(embedBlob, Transform("EMBED BLOB")))
2938336Ssteve.reinhardt@amd.com    Source(cpp_path)
2944678Snate@binkert.org
29511401Sandreas.sandberg@arm.comdef GdbXml(xml_id, symbol):
2964678Snate@binkert.org    Blob(joinpath(gdb_xml_dir, xml_id), symbol)
2974678Snate@binkert.org
29811401Sandreas.sandberg@arm.comclass Source(SourceFile):
29911401Sandreas.sandberg@arm.com    ungrouped_tag = 'No link group'
3008336Ssteve.reinhardt@amd.com    source_groups = set()
3014678Snate@binkert.org
3028336Ssteve.reinhardt@amd.com    _current_group_tag = ungrouped_tag
3038336Ssteve.reinhardt@amd.com
3048336Ssteve.reinhardt@amd.com    @staticmethod
3058336Ssteve.reinhardt@amd.com    def link_group_tag(group):
3068336Ssteve.reinhardt@amd.com        return 'link group: %s' % group
3078336Ssteve.reinhardt@amd.com
3085871Snate@binkert.org    @classmethod
3095871Snate@binkert.org    def set_group(cls, group):
3108336Ssteve.reinhardt@amd.com        new_tag = Source.link_group_tag(group)
31111408Sandreas.sandberg@arm.com        Source._current_group_tag = new_tag
31211408Sandreas.sandberg@arm.com        Source.source_groups.add(group)
31311408Sandreas.sandberg@arm.com
31411408Sandreas.sandberg@arm.com    def _add_link_group_tag(self):
31511408Sandreas.sandberg@arm.com        self.tags.add(Source._current_group_tag)
31611408Sandreas.sandberg@arm.com
31711408Sandreas.sandberg@arm.com    '''Add a c/c++ source file to the build'''
3188336Ssteve.reinhardt@amd.com    def __init__(self, source, tags=None, add_tags=None):
31911401Sandreas.sandberg@arm.com        '''specify the source file, and any tags'''
32011401Sandreas.sandberg@arm.com        super(Source, self).__init__(source, tags, add_tags)
32111401Sandreas.sandberg@arm.com        self._add_link_group_tag()
3225871Snate@binkert.org
3238336Ssteve.reinhardt@amd.comclass PySource(SourceFile):
3248336Ssteve.reinhardt@amd.com    '''Add a python source file to the named package'''
32511401Sandreas.sandberg@arm.com    invalid_sym_char = re.compile('[^A-z0-9_]')
32611401Sandreas.sandberg@arm.com    modules = {}
32711401Sandreas.sandberg@arm.com    tnodes = {}
32811401Sandreas.sandberg@arm.com    symnames = {}
32911401Sandreas.sandberg@arm.com
3304678Snate@binkert.org    def __init__(self, package, source, tags=None, add_tags=None):
3315871Snate@binkert.org        '''specify the python package, the source file, and any tags'''
3324678Snate@binkert.org        super(PySource, self).__init__(source, tags, add_tags)
33311401Sandreas.sandberg@arm.com
33411401Sandreas.sandberg@arm.com        modname,ext = self.extname
33511401Sandreas.sandberg@arm.com        assert ext == 'py'
33611401Sandreas.sandberg@arm.com
33711401Sandreas.sandberg@arm.com        if package:
33811401Sandreas.sandberg@arm.com            path = package.split('.')
33911401Sandreas.sandberg@arm.com        else:
34011401Sandreas.sandberg@arm.com            path = []
34111401Sandreas.sandberg@arm.com
34211401Sandreas.sandberg@arm.com        modpath = path[:]
34311401Sandreas.sandberg@arm.com        if modname != '__init__':
34411401Sandreas.sandberg@arm.com            modpath += [ modname ]
34511450Sandreas.sandberg@arm.com        modpath = '.'.join(modpath)
34611450Sandreas.sandberg@arm.com
34711450Sandreas.sandberg@arm.com        arcpath = path + [ self.basename ]
34811450Sandreas.sandberg@arm.com        abspath = self.snode.abspath
34911450Sandreas.sandberg@arm.com        if not exists(abspath):
35011450Sandreas.sandberg@arm.com            abspath = self.tnode.abspath
35111450Sandreas.sandberg@arm.com
35211450Sandreas.sandberg@arm.com        self.package = package
35311450Sandreas.sandberg@arm.com        self.modname = modname
35411450Sandreas.sandberg@arm.com        self.modpath = modpath
35511450Sandreas.sandberg@arm.com        self.arcname = joinpath(*arcpath)
35611401Sandreas.sandberg@arm.com        self.abspath = abspath
35711450Sandreas.sandberg@arm.com        self.compiled = File(self.filename + 'c')
35811450Sandreas.sandberg@arm.com        self.cpp = File(self.filename + '.cc')
35911450Sandreas.sandberg@arm.com        self.symname = PySource.invalid_sym_char.sub('_', modpath)
36011401Sandreas.sandberg@arm.com
36111450Sandreas.sandberg@arm.com        PySource.modules[modpath] = self
36211401Sandreas.sandberg@arm.com        PySource.tnodes[self.tnode] = self
3638336Ssteve.reinhardt@amd.com        PySource.symnames[self.symname] = self
3648336Ssteve.reinhardt@amd.com
3658336Ssteve.reinhardt@amd.comclass SimObject(PySource):
3668336Ssteve.reinhardt@amd.com    '''Add a SimObject python file as a python source object and add
3678336Ssteve.reinhardt@amd.com    it to a list of sim object modules'''
3688336Ssteve.reinhardt@amd.com
3698336Ssteve.reinhardt@amd.com    fixed = False
3708336Ssteve.reinhardt@amd.com    modnames = []
3718336Ssteve.reinhardt@amd.com
3728336Ssteve.reinhardt@amd.com    def __init__(self, source, tags=None, add_tags=None):
37311401Sandreas.sandberg@arm.com        '''Specify the source file and any tags (automatically in
37411401Sandreas.sandberg@arm.com        the m5.objects package)'''
3758336Ssteve.reinhardt@amd.com        super(SimObject, self).__init__('m5.objects', source, tags, add_tags)
3768336Ssteve.reinhardt@amd.com        if self.fixed:
3778336Ssteve.reinhardt@amd.com            raise AttributeError, "Too late to call SimObject now."
3785871Snate@binkert.org
37911476Sandreas.sandberg@arm.com        bisect.insort_right(SimObject.modnames, self.modname)
38011476Sandreas.sandberg@arm.com
38111476Sandreas.sandberg@arm.comclass ProtoBuf(SourceFile):
38211476Sandreas.sandberg@arm.com    '''Add a Protocol Buffer to build'''
38311476Sandreas.sandberg@arm.com
38411476Sandreas.sandberg@arm.com    def __init__(self, source, tags=None, add_tags=None):
38511476Sandreas.sandberg@arm.com        '''Specify the source file, and any tags'''
38611476Sandreas.sandberg@arm.com        super(ProtoBuf, self).__init__(source, tags, add_tags)
38711476Sandreas.sandberg@arm.com
38811887Sandreas.sandberg@arm.com        # Get the file name and the extension
38911887Sandreas.sandberg@arm.com        modname,ext = self.extname
39011887Sandreas.sandberg@arm.com        assert ext == 'proto'
39111408Sandreas.sandberg@arm.com
39211887Sandreas.sandberg@arm.com        # Currently, we stick to generating the C++ headers, so we
39311887Sandreas.sandberg@arm.com        # only need to track the source and header.
39411887Sandreas.sandberg@arm.com        self.cc_file = File(modname + '.pb.cc')
39511887Sandreas.sandberg@arm.com        self.hh_file = File(modname + '.pb.h')
39611887Sandreas.sandberg@arm.com
39711887Sandreas.sandberg@arm.com
39811926Sgabeblack@google.comexectuable_classes = []
39911926Sgabeblack@google.comclass ExecutableMeta(type):
40011926Sgabeblack@google.com    '''Meta class for Executables.'''
40111926Sgabeblack@google.com    all = []
40211887Sandreas.sandberg@arm.com
40311887Sandreas.sandberg@arm.com    def __init__(cls, name, bases, d):
40411944Sandreas.sandberg@arm.com        if not d.pop('abstract', False):
40511887Sandreas.sandberg@arm.com            ExecutableMeta.all.append(cls)
40611927Sgabeblack@google.com        super(ExecutableMeta, cls).__init__(name, bases, d)
40711927Sgabeblack@google.com
40811927Sgabeblack@google.com        cls.all = []
40911927Sgabeblack@google.com
41011927Sgabeblack@google.comclass Executable(object):
41111927Sgabeblack@google.com    '''Base class for creating an executable from sources.'''
41211887Sandreas.sandberg@arm.com    __metaclass__ = ExecutableMeta
41311928Sgabeblack@google.com
41411928Sgabeblack@google.com    abstract = True
41511887Sandreas.sandberg@arm.com
41611887Sandreas.sandberg@arm.com    def __init__(self, target, *srcs_and_filts):
41711887Sandreas.sandberg@arm.com        '''Specify the target name and any sources. Sources that are
41811887Sandreas.sandberg@arm.com        not SourceFiles are evalued with Source().'''
41911887Sandreas.sandberg@arm.com        super(Executable, self).__init__()
42011887Sandreas.sandberg@arm.com        self.all.append(self)
42111887Sandreas.sandberg@arm.com        self.target = target
42211887Sandreas.sandberg@arm.com
42311887Sandreas.sandberg@arm.com        isFilter = lambda arg: isinstance(arg, SourceFilter)
42411887Sandreas.sandberg@arm.com        self.filters = filter(isFilter, srcs_and_filts)
42511476Sandreas.sandberg@arm.com        sources = filter(lambda a: not isFilter(a), srcs_and_filts)
42611476Sandreas.sandberg@arm.com
42711408Sandreas.sandberg@arm.com        srcs = SourceList()
42811408Sandreas.sandberg@arm.com        for src in sources:
42911408Sandreas.sandberg@arm.com            if not isinstance(src, SourceFile):
43011408Sandreas.sandberg@arm.com                src = Source(src, tags=[])
43111408Sandreas.sandberg@arm.com            srcs.append(src)
43211408Sandreas.sandberg@arm.com
43311408Sandreas.sandberg@arm.com        self.sources = srcs
43411887Sandreas.sandberg@arm.com        self.dir = Dir('.')
43511887Sandreas.sandberg@arm.com
43611476Sandreas.sandberg@arm.com    def path(self, env):
43711887Sandreas.sandberg@arm.com        return self.dir.File(self.target + '.' + env['EXE_SUFFIX'])
43811887Sandreas.sandberg@arm.com
43911476Sandreas.sandberg@arm.com    def srcs_to_objs(self, env, sources):
44011476Sandreas.sandberg@arm.com        return list([ s.static(env) for s in sources ])
44111476Sandreas.sandberg@arm.com
44211476Sandreas.sandberg@arm.com    @classmethod
4436121Snate@binkert.org    def declare_all(cls, env):
444955SN/A        return list([ instance.declare(env) for instance in cls.all ])
445955SN/A
4462632Sstever@eecs.umich.edu    def declare(self, env, objs=None):
4472632Sstever@eecs.umich.edu        if objs is None:
448955SN/A            objs = self.srcs_to_objs(env, self.sources)
449955SN/A
450955SN/A        env = env.Clone()
451955SN/A        env['BIN_RPATH_PREFIX'] = os.path.relpath(
4528878Ssteve.reinhardt@amd.com                env['BUILDDIR'], self.path(env).dir.abspath)
453955SN/A
4542632Sstever@eecs.umich.edu        if env['STRIP_EXES']:
4552632Sstever@eecs.umich.edu            stripped = self.path(env)
4562632Sstever@eecs.umich.edu            unstripped = env.File(str(stripped) + '.unstripped')
4572632Sstever@eecs.umich.edu            if sys.platform == 'sunos5':
4582632Sstever@eecs.umich.edu                cmd = 'cp $SOURCE $TARGET; strip $TARGET'
4592632Sstever@eecs.umich.edu            else:
4602632Sstever@eecs.umich.edu                cmd = 'strip $SOURCE -o $TARGET'
4618268Ssteve.reinhardt@amd.com            env.Program(unstripped, objs)
4628268Ssteve.reinhardt@amd.com            return env.Command(stripped, unstripped,
4638268Ssteve.reinhardt@amd.com                               MakeAction(cmd, Transform("STRIP")))
4648268Ssteve.reinhardt@amd.com        else:
4658268Ssteve.reinhardt@amd.com            return env.Program(self.path(env), objs)
4668268Ssteve.reinhardt@amd.com
4678268Ssteve.reinhardt@amd.comclass UnitTest(Executable):
4682632Sstever@eecs.umich.edu    '''Create a UnitTest'''
4692632Sstever@eecs.umich.edu    def __init__(self, target, *srcs_and_filts, **kwargs):
4702632Sstever@eecs.umich.edu        super(UnitTest, self).__init__(target, *srcs_and_filts)
4712632Sstever@eecs.umich.edu
4728268Ssteve.reinhardt@amd.com        self.main = kwargs.get('main', False)
4732632Sstever@eecs.umich.edu
4748268Ssteve.reinhardt@amd.com    def declare(self, env):
4758268Ssteve.reinhardt@amd.com        sources = list(self.sources)
4768268Ssteve.reinhardt@amd.com        for f in self.filters:
4778268Ssteve.reinhardt@amd.com            sources += Source.all.apply_filter(f)
4783718Sstever@eecs.umich.edu        objs = self.srcs_to_objs(env, sources) + env['STATIC_OBJS']
4792634Sstever@eecs.umich.edu        if self.main:
4802634Sstever@eecs.umich.edu            objs += env['MAIN_OBJS']
4815863Snate@binkert.org        return super(UnitTest, self).declare(env, objs)
4822638Sstever@eecs.umich.edu
4838268Ssteve.reinhardt@amd.comclass GTest(Executable):
4842632Sstever@eecs.umich.edu    '''Create a unit test based on the google test framework.'''
4852632Sstever@eecs.umich.edu    all = []
4862632Sstever@eecs.umich.edu    def __init__(self, *srcs_and_filts, **kwargs):
4872632Sstever@eecs.umich.edu        super(GTest, self).__init__(*srcs_and_filts)
4882632Sstever@eecs.umich.edu
4891858SN/A        self.skip_lib = kwargs.pop('skip_lib', False)
4903716Sstever@eecs.umich.edu
4912638Sstever@eecs.umich.edu    @classmethod
4922638Sstever@eecs.umich.edu    def declare_all(cls, env):
4932638Sstever@eecs.umich.edu        env = env.Clone()
4942638Sstever@eecs.umich.edu        env.Append(LIBS=env['GTEST_LIBS'])
4952638Sstever@eecs.umich.edu        env.Append(CPPFLAGS=env['GTEST_CPPFLAGS'])
4962638Sstever@eecs.umich.edu        env['GTEST_LIB_SOURCES'] = Source.all.with_tag('gtest lib')
4972638Sstever@eecs.umich.edu        env['GTEST_OUT_DIR'] = \
4985863Snate@binkert.org            Dir(env['BUILDDIR']).Dir('unittests.' + env['EXE_SUFFIX'])
4995863Snate@binkert.org        return super(GTest, cls).declare_all(env)
5005863Snate@binkert.org
501955SN/A    def declare(self, env):
5025341Sstever@gmail.com        sources = list(self.sources)
5035341Sstever@gmail.com        if not self.skip_lib:
5045863Snate@binkert.org            sources += env['GTEST_LIB_SOURCES']
5057756SAli.Saidi@ARM.com        for f in self.filters:
5065341Sstever@gmail.com            sources += Source.all.apply_filter(f)
5076121Snate@binkert.org        objs = self.srcs_to_objs(env, sources)
5084494Ssaidi@eecs.umich.edu
5096121Snate@binkert.org        binary = super(GTest, self).declare(env, objs)
5101105SN/A
5112667Sstever@eecs.umich.edu        out_dir = env['GTEST_OUT_DIR']
5122667Sstever@eecs.umich.edu        xml_file = out_dir.Dir(str(self.dir)).File(self.target + '.xml')
5132667Sstever@eecs.umich.edu        AlwaysBuild(env.Command(xml_file, binary,
5142667Sstever@eecs.umich.edu            "${SOURCES[0]} --gtest_output=xml:${TARGETS[0]}"))
5156121Snate@binkert.org
5162667Sstever@eecs.umich.edu        return binary
5175341Sstever@gmail.com
5185863Snate@binkert.orgclass Gem5(Executable):
5195341Sstever@gmail.com    '''Create a gem5 executable.'''
5205341Sstever@gmail.com
5215341Sstever@gmail.com    def __init__(self, target):
5228120Sgblack@eecs.umich.edu        super(Gem5, self).__init__(target)
5235341Sstever@gmail.com
5248120Sgblack@eecs.umich.edu    def declare(self, env):
5255341Sstever@gmail.com        objs = env['MAIN_OBJS'] + env['STATIC_OBJS']
5268120Sgblack@eecs.umich.edu        return super(Gem5, self).declare(env, objs)
5276121Snate@binkert.org
5286121Snate@binkert.org
5299396Sandreas.hansson@arm.com# Children should have access
5305397Ssaidi@eecs.umich.eduExport('Blob')
5315397Ssaidi@eecs.umich.eduExport('GdbXml')
5327727SAli.Saidi@ARM.comExport('Source')
5338268Ssteve.reinhardt@amd.comExport('PySource')
5346168Snate@binkert.orgExport('SimObject')
5355341Sstever@gmail.comExport('ProtoBuf')
5368120Sgblack@eecs.umich.eduExport('Executable')
5378120Sgblack@eecs.umich.eduExport('UnitTest')
5388120Sgblack@eecs.umich.eduExport('GTest')
5396814Sgblack@eecs.umich.edu
5405863Snate@binkert.org########################################################################
5418120Sgblack@eecs.umich.edu#
5425341Sstever@gmail.com# Debug Flags
5435863Snate@binkert.org#
5448268Ssteve.reinhardt@amd.comdebug_flags = {}
5456121Snate@binkert.orgdef DebugFlag(name, desc=None):
5466121Snate@binkert.org    if name in debug_flags:
5478268Ssteve.reinhardt@amd.com        raise AttributeError, "Flag %s already specified" % name
5485742Snate@binkert.org    debug_flags[name] = (name, (), desc)
5495742Snate@binkert.org
5505341Sstever@gmail.comdef CompoundFlag(name, flags, desc=None):
5515742Snate@binkert.org    if name in debug_flags:
5525742Snate@binkert.org        raise AttributeError, "Flag %s already specified" % name
5535341Sstever@gmail.com
5546017Snate@binkert.org    compound = tuple(flags)
5556121Snate@binkert.org    debug_flags[name] = (name, compound, desc)
5566017Snate@binkert.org
5577816Ssteve.reinhardt@amd.comExport('DebugFlag')
5587756SAli.Saidi@ARM.comExport('CompoundFlag')
5597756SAli.Saidi@ARM.com
5607756SAli.Saidi@ARM.com########################################################################
5617756SAli.Saidi@ARM.com#
5627756SAli.Saidi@ARM.com# Set some compiler variables
5637756SAli.Saidi@ARM.com#
5647756SAli.Saidi@ARM.com
5657756SAli.Saidi@ARM.com# Include file paths are rooted in this directory.  SCons will
5667816Ssteve.reinhardt@amd.com# automatically expand '.' to refer to both the source directory and
5677816Ssteve.reinhardt@amd.com# the corresponding build directory to pick up generated include
5687816Ssteve.reinhardt@amd.com# files.
5697816Ssteve.reinhardt@amd.comenv.Append(CPPPATH=Dir('.'))
5707816Ssteve.reinhardt@amd.com
5717816Ssteve.reinhardt@amd.comfor extra_dir in extras_dir_list:
5727816Ssteve.reinhardt@amd.com    env.Append(CPPPATH=Dir(extra_dir))
5737816Ssteve.reinhardt@amd.com
5747816Ssteve.reinhardt@amd.com# Workaround for bug in SCons version > 0.97d20071212
5757816Ssteve.reinhardt@amd.com# Scons bug id: 2006 gem5 Bug id: 308
5767756SAli.Saidi@ARM.comfor root, dirs, files in os.walk(base_dir, topdown=True):
5777816Ssteve.reinhardt@amd.com    Dir(root[len(base_dir) + 1:])
5787816Ssteve.reinhardt@amd.com
5797816Ssteve.reinhardt@amd.com########################################################################
5807816Ssteve.reinhardt@amd.com#
5817816Ssteve.reinhardt@amd.com# Walk the tree and execute all SConscripts in subdirectories
5827816Ssteve.reinhardt@amd.com#
5837816Ssteve.reinhardt@amd.com
5847816Ssteve.reinhardt@amd.comhere = Dir('.').srcnode().abspath
5857816Ssteve.reinhardt@amd.comfor root, dirs, files in os.walk(base_dir, topdown=True):
5867816Ssteve.reinhardt@amd.com    if root == here:
5877816Ssteve.reinhardt@amd.com        # we don't want to recurse back into this SConscript
5887816Ssteve.reinhardt@amd.com        continue
5897816Ssteve.reinhardt@amd.com
5907816Ssteve.reinhardt@amd.com    if 'SConscript' in files:
5917816Ssteve.reinhardt@amd.com        build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:])
5927816Ssteve.reinhardt@amd.com        Source.set_group(build_dir)
5937816Ssteve.reinhardt@amd.com        SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir)
5947816Ssteve.reinhardt@amd.com
5957816Ssteve.reinhardt@amd.comfor extra_dir in extras_dir_list:
5967816Ssteve.reinhardt@amd.com    prefix_len = len(dirname(extra_dir)) + 1
5977816Ssteve.reinhardt@amd.com
5987816Ssteve.reinhardt@amd.com    # Also add the corresponding build directory to pick up generated
5997816Ssteve.reinhardt@amd.com    # include files.
6007816Ssteve.reinhardt@amd.com    env.Append(CPPPATH=Dir(joinpath(env['BUILDDIR'], extra_dir[prefix_len:])))
6017816Ssteve.reinhardt@amd.com
6027816Ssteve.reinhardt@amd.com    for root, dirs, files in os.walk(extra_dir, topdown=True):
6037816Ssteve.reinhardt@amd.com        # if build lives in the extras directory, don't walk down it
6047816Ssteve.reinhardt@amd.com        if 'build' in dirs:
6057816Ssteve.reinhardt@amd.com            dirs.remove('build')
6067816Ssteve.reinhardt@amd.com
6077816Ssteve.reinhardt@amd.com        if 'SConscript' in files:
6087816Ssteve.reinhardt@amd.com            build_dir = joinpath(env['BUILDDIR'], root[prefix_len:])
6097816Ssteve.reinhardt@amd.com            SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir)
6107816Ssteve.reinhardt@amd.com
6117816Ssteve.reinhardt@amd.comfor opt in export_vars:
6127816Ssteve.reinhardt@amd.com    env.ConfigFile(opt)
6137816Ssteve.reinhardt@amd.com
6147816Ssteve.reinhardt@amd.comdef makeTheISA(source, target, env):
6157816Ssteve.reinhardt@amd.com    isas = [ src.get_contents() for src in source ]
6167816Ssteve.reinhardt@amd.com    target_isa = env['TARGET_ISA']
6177816Ssteve.reinhardt@amd.com    def define(isa):
6187816Ssteve.reinhardt@amd.com        return isa.upper() + '_ISA'
6197816Ssteve.reinhardt@amd.com
6207816Ssteve.reinhardt@amd.com    def namespace(isa):
6217816Ssteve.reinhardt@amd.com        return isa[0].upper() + isa[1:].lower() + 'ISA'
6227816Ssteve.reinhardt@amd.com
6237816Ssteve.reinhardt@amd.com
6247816Ssteve.reinhardt@amd.com    code = code_formatter()
6257816Ssteve.reinhardt@amd.com    code('''\
6267816Ssteve.reinhardt@amd.com#ifndef __CONFIG_THE_ISA_HH__
6277816Ssteve.reinhardt@amd.com#define __CONFIG_THE_ISA_HH__
6287816Ssteve.reinhardt@amd.com
6297816Ssteve.reinhardt@amd.com''')
6307816Ssteve.reinhardt@amd.com
6317816Ssteve.reinhardt@amd.com    # create defines for the preprocessing and compile-time determination
6327816Ssteve.reinhardt@amd.com    for i,isa in enumerate(isas):
6337816Ssteve.reinhardt@amd.com        code('#define $0 $1', define(isa), i + 1)
6347816Ssteve.reinhardt@amd.com    code()
6357816Ssteve.reinhardt@amd.com
6367816Ssteve.reinhardt@amd.com    # create an enum for any run-time determination of the ISA, we
6377816Ssteve.reinhardt@amd.com    # reuse the same name as the namespaces
6388947Sandreas.hansson@arm.com    code('enum class Arch {')
6398947Sandreas.hansson@arm.com    for i,isa in enumerate(isas):
6407756SAli.Saidi@ARM.com        if i + 1 == len(isas):
6418120Sgblack@eecs.umich.edu            code('  $0 = $1', namespace(isa), define(isa))
6427756SAli.Saidi@ARM.com        else:
6437756SAli.Saidi@ARM.com            code('  $0 = $1,', namespace(isa), define(isa))
6447756SAli.Saidi@ARM.com    code('};')
6457756SAli.Saidi@ARM.com
6467816Ssteve.reinhardt@amd.com    code('''
6477816Ssteve.reinhardt@amd.com
6487816Ssteve.reinhardt@amd.com#define THE_ISA ${{define(target_isa)}}
6497816Ssteve.reinhardt@amd.com#define TheISA ${{namespace(target_isa)}}
6507816Ssteve.reinhardt@amd.com#define THE_ISA_STR "${{target_isa}}"
65111979Sgabeblack@google.com
6527816Ssteve.reinhardt@amd.com#endif // __CONFIG_THE_ISA_HH__''')
6537816Ssteve.reinhardt@amd.com
6547816Ssteve.reinhardt@amd.com    code.write(str(target[0]))
6557816Ssteve.reinhardt@amd.com
6567756SAli.Saidi@ARM.comenv.Command('config/the_isa.hh', map(Value, all_isa_list),
6577756SAli.Saidi@ARM.com            MakeAction(makeTheISA, Transform("CFG ISA", 0)))
6589227Sandreas.hansson@arm.com
6599227Sandreas.hansson@arm.comdef makeTheGPUISA(source, target, env):
6609227Sandreas.hansson@arm.com    isas = [ src.get_contents() for src in source ]
6619227Sandreas.hansson@arm.com    target_gpu_isa = env['TARGET_GPU_ISA']
6629590Sandreas@sandberg.pp.se    def define(isa):
6639590Sandreas@sandberg.pp.se        return isa.upper() + '_ISA'
6649590Sandreas@sandberg.pp.se
6659590Sandreas@sandberg.pp.se    def namespace(isa):
6669590Sandreas@sandberg.pp.se        return isa[0].upper() + isa[1:].lower() + 'ISA'
6679590Sandreas@sandberg.pp.se
6686654Snate@binkert.org
6696654Snate@binkert.org    code = code_formatter()
6705871Snate@binkert.org    code('''\
6716121Snate@binkert.org#ifndef __CONFIG_THE_GPU_ISA_HH__
6728946Sandreas.hansson@arm.com#define __CONFIG_THE_GPU_ISA_HH__
6739419Sandreas.hansson@arm.com
6743940Ssaidi@eecs.umich.edu''')
6753918Ssaidi@eecs.umich.edu
6763918Ssaidi@eecs.umich.edu    # create defines for the preprocessing and compile-time determination
6771858SN/A    for i,isa in enumerate(isas):
6789556Sandreas.hansson@arm.com        code('#define $0 $1', define(isa), i + 1)
6799556Sandreas.hansson@arm.com    code()
6809556Sandreas.hansson@arm.com
6819556Sandreas.hansson@arm.com    # create an enum for any run-time determination of the ISA, we
68211294Sandreas.hansson@arm.com    # reuse the same name as the namespaces
68311294Sandreas.hansson@arm.com    code('enum class GPUArch {')
68411294Sandreas.hansson@arm.com    for i,isa in enumerate(isas):
68511294Sandreas.hansson@arm.com        if i + 1 == len(isas):
68610878Sandreas.hansson@arm.com            code('  $0 = $1', namespace(isa), define(isa))
68710878Sandreas.hansson@arm.com        else:
68811811Sbaz21@cam.ac.uk            code('  $0 = $1,', namespace(isa), define(isa))
68911811Sbaz21@cam.ac.uk    code('};')
69011811Sbaz21@cam.ac.uk
69111982Sgabeblack@google.com    code('''
69211982Sgabeblack@google.com
69311982Sgabeblack@google.com#define THE_GPU_ISA ${{define(target_gpu_isa)}}
69411982Sgabeblack@google.com#define TheGpuISA ${{namespace(target_gpu_isa)}}
69511992Sgabeblack@google.com#define THE_GPU_ISA_STR "${{target_gpu_isa}}"
69611982Sgabeblack@google.com
69711982Sgabeblack@google.com#endif // __CONFIG_THE_GPU_ISA_HH__''')
6989556Sandreas.hansson@arm.com
6999556Sandreas.hansson@arm.com    code.write(str(target[0]))
7009556Sandreas.hansson@arm.com
7019556Sandreas.hansson@arm.comenv.Command('config/the_gpu_isa.hh', map(Value, all_gpu_isa_list),
7029556Sandreas.hansson@arm.com            MakeAction(makeTheGPUISA, Transform("CFG ISA", 0)))
7039556Sandreas.hansson@arm.com
7049556Sandreas.hansson@arm.com########################################################################
7059556Sandreas.hansson@arm.com#
7069556Sandreas.hansson@arm.com# Prevent any SimObjects from being added after this point, they
7079556Sandreas.hansson@arm.com# should all have been added in the SConscripts above
7089556Sandreas.hansson@arm.com#
7099556Sandreas.hansson@arm.comSimObject.fixed = True
7109556Sandreas.hansson@arm.com
7119556Sandreas.hansson@arm.comclass DictImporter(object):
7129556Sandreas.hansson@arm.com    '''This importer takes a dictionary of arbitrary module names that
7139556Sandreas.hansson@arm.com    map to arbitrary filenames.'''
7149556Sandreas.hansson@arm.com    def __init__(self, modules):
7159556Sandreas.hansson@arm.com        self.modules = modules
7169556Sandreas.hansson@arm.com        self.installed = set()
7176121Snate@binkert.org
71811500Sandreas.hansson@arm.com    def __del__(self):
71910238Sandreas.hansson@arm.com        self.unload()
72010878Sandreas.hansson@arm.com
7219420Sandreas.hansson@arm.com    def unload(self):
72211500Sandreas.hansson@arm.com        import sys
72311500Sandreas.hansson@arm.com        for module in self.installed:
7249420Sandreas.hansson@arm.com            del sys.modules[module]
7259420Sandreas.hansson@arm.com        self.installed = set()
7269420Sandreas.hansson@arm.com
7279420Sandreas.hansson@arm.com    def find_module(self, fullname, path):
7289420Sandreas.hansson@arm.com        if fullname == 'm5.defines':
72912063Sgabeblack@google.com            return self
73012063Sgabeblack@google.com
73112063Sgabeblack@google.com        if fullname == 'm5.objects':
73212063Sgabeblack@google.com            return self
73312063Sgabeblack@google.com
73412063Sgabeblack@google.com        if fullname.startswith('_m5'):
73512063Sgabeblack@google.com            return None
73612063Sgabeblack@google.com
73712063Sgabeblack@google.com        source = self.modules.get(fullname, None)
73812063Sgabeblack@google.com        if source is not None and fullname.startswith('m5.objects'):
73912063Sgabeblack@google.com            return self
74012063Sgabeblack@google.com
74112063Sgabeblack@google.com        return None
74212063Sgabeblack@google.com
74312063Sgabeblack@google.com    def load_module(self, fullname):
74412063Sgabeblack@google.com        mod = imp.new_module(fullname)
74512063Sgabeblack@google.com        sys.modules[fullname] = mod
74612063Sgabeblack@google.com        self.installed.add(fullname)
74712063Sgabeblack@google.com
74812063Sgabeblack@google.com        mod.__loader__ = self
74912063Sgabeblack@google.com        if fullname == 'm5.objects':
75012063Sgabeblack@google.com            mod.__path__ = fullname.split('.')
75110264Sandreas.hansson@arm.com            return mod
75210264Sandreas.hansson@arm.com
75310264Sandreas.hansson@arm.com        if fullname == 'm5.defines':
75410264Sandreas.hansson@arm.com            mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env)
75511925Sgabeblack@google.com            return mod
75611925Sgabeblack@google.com
75711500Sandreas.hansson@arm.com        source = self.modules[fullname]
75810264Sandreas.hansson@arm.com        if source.modname == '__init__':
75911500Sandreas.hansson@arm.com            mod.__path__ = source.modpath
76011500Sandreas.hansson@arm.com        mod.__file__ = source.abspath
76111500Sandreas.hansson@arm.com
76211500Sandreas.hansson@arm.com        exec file(source.abspath, 'r') in mod.__dict__
76310866Sandreas.hansson@arm.com
76411500Sandreas.hansson@arm.com        return mod
76511500Sandreas.hansson@arm.com
76611500Sandreas.hansson@arm.comimport m5.SimObject
76711500Sandreas.hansson@arm.comimport m5.params
76811500Sandreas.hansson@arm.comfrom m5.util import code_formatter
76911500Sandreas.hansson@arm.com
77011500Sandreas.hansson@arm.comm5.SimObject.clear()
77110264Sandreas.hansson@arm.comm5.params.clear()
77210457Sandreas.hansson@arm.com
77310457Sandreas.hansson@arm.com# install the python importer so we can grab stuff from the source
77410457Sandreas.hansson@arm.com# tree itself.  We can't have SimObjects added after this point or
77510457Sandreas.hansson@arm.com# else we won't know about them for the rest of the stuff.
77610457Sandreas.hansson@arm.comimporter = DictImporter(PySource.modules)
77710457Sandreas.hansson@arm.comsys.meta_path[0:0] = [ importer ]
77810457Sandreas.hansson@arm.com
77910457Sandreas.hansson@arm.com# import all sim objects so we can populate the all_objects list
78010457Sandreas.hansson@arm.com# make sure that we're working with a list, then let's sort it
78112063Sgabeblack@google.comfor modname in SimObject.modnames:
78212063Sgabeblack@google.com    exec('from m5.objects import %s' % modname)
78312063Sgabeblack@google.com
78412063Sgabeblack@google.com# we need to unload all of the currently imported modules so that they
78512063Sgabeblack@google.com# will be re-imported the next time the sconscript is run
78612063Sgabeblack@google.comimporter.unload()
78712063Sgabeblack@google.comsys.meta_path.remove(importer)
78812063Sgabeblack@google.com
78912063Sgabeblack@google.comsim_objects = m5.SimObject.allClasses
79012063Sgabeblack@google.comall_enums = m5.params.allEnums
79112063Sgabeblack@google.com
79210238Sandreas.hansson@arm.comfor name,obj in sorted(sim_objects.iteritems()):
79310238Sandreas.hansson@arm.com    for param in obj._params.local.values():
79410238Sandreas.hansson@arm.com        # load the ptype attribute now because it depends on the
79512063Sgabeblack@google.com        # current version of SimObject.allClasses, but when scons
79610238Sandreas.hansson@arm.com        # actually uses the value, all versions of
79710238Sandreas.hansson@arm.com        # SimObject.allClasses will have been loaded
79810416Sandreas.hansson@arm.com        param.ptype
79910238Sandreas.hansson@arm.com
8009227Sandreas.hansson@arm.com########################################################################
80110238Sandreas.hansson@arm.com#
80210416Sandreas.hansson@arm.com# calculate extra dependencies
80310416Sandreas.hansson@arm.com#
8049227Sandreas.hansson@arm.commodule_depends = ["m5", "m5.SimObject", "m5.params"]
8059590Sandreas@sandberg.pp.sedepends = [ PySource.modules[dep].snode for dep in module_depends ]
8069590Sandreas@sandberg.pp.sedepends.sort(key = lambda x: x.name)
8079590Sandreas@sandberg.pp.se
80811497SMatteo.Andreozzi@arm.com########################################################################
80911497SMatteo.Andreozzi@arm.com#
81011497SMatteo.Andreozzi@arm.com# Commands for the basic automatically generated python files
81111497SMatteo.Andreozzi@arm.com#
8128737Skoansin.tan@gmail.com
81310878Sandreas.hansson@arm.com# Generate Python file containing a dict specifying the current
81411500Sandreas.hansson@arm.com# buildEnv flags.
8159420Sandreas.hansson@arm.comdef makeDefinesPyFile(target, source, env):
8168737Skoansin.tan@gmail.com    build_env = source[0].get_contents()
81710106SMitch.Hayenga@arm.com
8188737Skoansin.tan@gmail.com    code = code_formatter()
8198737Skoansin.tan@gmail.com    code("""
82010878Sandreas.hansson@arm.comimport _m5.core
82110878Sandreas.hansson@arm.comimport m5.util
8228737Skoansin.tan@gmail.com
8238737Skoansin.tan@gmail.combuildEnv = m5.util.SmartDict($build_env)
8248737Skoansin.tan@gmail.com
8258737Skoansin.tan@gmail.comcompileDate = _m5.core.compileDate
8268737Skoansin.tan@gmail.com_globals = globals()
8278737Skoansin.tan@gmail.comfor key,val in _m5.core.__dict__.items():
82811294Sandreas.hansson@arm.com    if key.startswith('flag_'):
8299556Sandreas.hansson@arm.com        flag = key[5:]
8309556Sandreas.hansson@arm.com        _globals[flag] = val
8319556Sandreas.hansson@arm.comdel _globals
83211294Sandreas.hansson@arm.com""")
83310278SAndreas.Sandberg@ARM.com    code.write(target[0].abspath)
83410278SAndreas.Sandberg@ARM.com
83510278SAndreas.Sandberg@ARM.comdefines_info = Value(build_env)
83610278SAndreas.Sandberg@ARM.com# Generate a file with all of the compile options in it
83710278SAndreas.Sandberg@ARM.comenv.Command('python/m5/defines.py', defines_info,
83810278SAndreas.Sandberg@ARM.com            MakeAction(makeDefinesPyFile, Transform("DEFINES", 0)))
8399556Sandreas.hansson@arm.comPySource('m5', 'python/m5/defines.py')
8409590Sandreas@sandberg.pp.se
8419590Sandreas@sandberg.pp.se# Generate python file containing info about the M5 source code
8429420Sandreas.hansson@arm.comdef makeInfoPyFile(target, source, env):
8439846Sandreas.hansson@arm.com    code = code_formatter()
8449846Sandreas.hansson@arm.com    for src in source:
8459846Sandreas.hansson@arm.com        data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
8469846Sandreas.hansson@arm.com        code('$src = ${{repr(data)}}')
8478946Sandreas.hansson@arm.com    code.write(str(target[0]))
84811811Sbaz21@cam.ac.uk
84911811Sbaz21@cam.ac.uk# Generate a file that wraps the basic top level files
85011811Sbaz21@cam.ac.ukenv.Command('python/m5/info.py',
85111811Sbaz21@cam.ac.uk            [ '#/COPYING', '#/LICENSE', '#/README', ],
8523918Ssaidi@eecs.umich.edu            MakeAction(makeInfoPyFile, Transform("INFO")))
8539068SAli.Saidi@ARM.comPySource('m5', 'python/m5/info.py')
8549068SAli.Saidi@ARM.com
8559068SAli.Saidi@ARM.com########################################################################
8569068SAli.Saidi@ARM.com#
8579068SAli.Saidi@ARM.com# Create all of the SimObject param headers and enum headers
8589068SAli.Saidi@ARM.com#
8599068SAli.Saidi@ARM.com
8609068SAli.Saidi@ARM.comdef createSimObjectParamStruct(target, source, env):
8619068SAli.Saidi@ARM.com    assert len(target) == 1 and len(source) == 1
8629419Sandreas.hansson@arm.com
8639068SAli.Saidi@ARM.com    name = source[0].get_text_contents()
8649068SAli.Saidi@ARM.com    obj = sim_objects[name]
8659068SAli.Saidi@ARM.com
8669068SAli.Saidi@ARM.com    code = code_formatter()
8679068SAli.Saidi@ARM.com    obj.cxx_param_decl(code)
8689068SAli.Saidi@ARM.com    code.write(target[0].abspath)
8693918Ssaidi@eecs.umich.edu
8703918Ssaidi@eecs.umich.edudef createSimObjectCxxConfig(is_header):
8716157Snate@binkert.org    def body(target, source, env):
8726157Snate@binkert.org        assert len(target) == 1 and len(source) == 1
8736157Snate@binkert.org
8746157Snate@binkert.org        name = str(source[0].get_contents())
8755397Ssaidi@eecs.umich.edu        obj = sim_objects[name]
8765397Ssaidi@eecs.umich.edu
8776121Snate@binkert.org        code = code_formatter()
8786121Snate@binkert.org        obj.cxx_config_param_file(code, is_header)
8796121Snate@binkert.org        code.write(target[0].abspath)
8806121Snate@binkert.org    return body
8816121Snate@binkert.org
8826121Snate@binkert.orgdef createEnumStrings(target, source, env):
8835397Ssaidi@eecs.umich.edu    assert len(target) == 1 and len(source) == 2
8841851SN/A
8851851SN/A    name = source[0].get_text_contents()
8867739Sgblack@eecs.umich.edu    use_python = source[1].read()
887955SN/A    obj = all_enums[name]
8889396Sandreas.hansson@arm.com
8899396Sandreas.hansson@arm.com    code = code_formatter()
8909396Sandreas.hansson@arm.com    obj.cxx_def(code)
8919396Sandreas.hansson@arm.com    if use_python:
8929396Sandreas.hansson@arm.com        obj.pybind_def(code)
8939396Sandreas.hansson@arm.com    code.write(target[0].abspath)
8949396Sandreas.hansson@arm.com
8959396Sandreas.hansson@arm.comdef createEnumDecls(target, source, env):
8969396Sandreas.hansson@arm.com    assert len(target) == 1 and len(source) == 1
8979396Sandreas.hansson@arm.com
8989396Sandreas.hansson@arm.com    name = source[0].get_text_contents()
8999396Sandreas.hansson@arm.com    obj = all_enums[name]
9009396Sandreas.hansson@arm.com
9019396Sandreas.hansson@arm.com    code = code_formatter()
9029396Sandreas.hansson@arm.com    obj.cxx_decl(code)
9039396Sandreas.hansson@arm.com    code.write(target[0].abspath)
9049477Sandreas.hansson@arm.com
9059477Sandreas.hansson@arm.comdef createSimObjectPyBindWrapper(target, source, env):
9069477Sandreas.hansson@arm.com    name = source[0].get_text_contents()
9079477Sandreas.hansson@arm.com    obj = sim_objects[name]
9089477Sandreas.hansson@arm.com
9099477Sandreas.hansson@arm.com    code = code_formatter()
9109477Sandreas.hansson@arm.com    obj.pybind_decl(code)
9119477Sandreas.hansson@arm.com    code.write(target[0].abspath)
9129477Sandreas.hansson@arm.com
9139477Sandreas.hansson@arm.com# Generate all of the SimObject param C++ struct header files
9149477Sandreas.hansson@arm.comparams_hh_files = []
9159477Sandreas.hansson@arm.comfor name,simobj in sorted(sim_objects.iteritems()):
9169477Sandreas.hansson@arm.com    py_source = PySource.modules[simobj.__module__]
9179477Sandreas.hansson@arm.com    extra_deps = [ py_source.tnode ]
9189477Sandreas.hansson@arm.com
9199477Sandreas.hansson@arm.com    hh_file = File('params/%s.hh' % name)
9209477Sandreas.hansson@arm.com    params_hh_files.append(hh_file)
9219477Sandreas.hansson@arm.com    env.Command(hh_file, Value(name),
9229477Sandreas.hansson@arm.com                MakeAction(createSimObjectParamStruct, Transform("SO PARAM")))
9239477Sandreas.hansson@arm.com    env.Depends(hh_file, depends + extra_deps)
9249477Sandreas.hansson@arm.com
9259477Sandreas.hansson@arm.com# C++ parameter description files
9269396Sandreas.hansson@arm.comif GetOption('with_cxx_config'):
9272667Sstever@eecs.umich.edu    for name,simobj in sorted(sim_objects.iteritems()):
92810710Sandreas.hansson@arm.com        py_source = PySource.modules[simobj.__module__]
92910710Sandreas.hansson@arm.com        extra_deps = [ py_source.tnode ]
93010710Sandreas.hansson@arm.com
93111811Sbaz21@cam.ac.uk        cxx_config_hh_file = File('cxx_config/%s.hh' % name)
93211811Sbaz21@cam.ac.uk        cxx_config_cc_file = File('cxx_config/%s.cc' % name)
93311811Sbaz21@cam.ac.uk        env.Command(cxx_config_hh_file, Value(name),
93411811Sbaz21@cam.ac.uk                    MakeAction(createSimObjectCxxConfig(True),
93511811Sbaz21@cam.ac.uk                    Transform("CXXCPRHH")))
93611811Sbaz21@cam.ac.uk        env.Command(cxx_config_cc_file, Value(name),
93710710Sandreas.hansson@arm.com                    MakeAction(createSimObjectCxxConfig(False),
93810710Sandreas.hansson@arm.com                    Transform("CXXCPRCC")))
93910710Sandreas.hansson@arm.com        env.Depends(cxx_config_hh_file, depends + extra_deps +
94010710Sandreas.hansson@arm.com                    [File('params/%s.hh' % name), File('sim/cxx_config.hh')])
94110384SCurtis.Dunham@arm.com        env.Depends(cxx_config_cc_file, depends + extra_deps +
9429986Sandreas@sandberg.pp.se                    [cxx_config_hh_file])
9439986Sandreas@sandberg.pp.se        Source(cxx_config_cc_file)
9449986Sandreas@sandberg.pp.se
9459986Sandreas@sandberg.pp.se    cxx_config_init_cc_file = File('cxx_config/init.cc')
9469986Sandreas@sandberg.pp.se
9479986Sandreas@sandberg.pp.se    def createCxxConfigInitCC(target, source, env):
9489986Sandreas@sandberg.pp.se        assert len(target) == 1 and len(source) == 1
9499986Sandreas@sandberg.pp.se
9509986Sandreas@sandberg.pp.se        code = code_formatter()
9519986Sandreas@sandberg.pp.se
9529986Sandreas@sandberg.pp.se        for name,simobj in sorted(sim_objects.iteritems()):
9539986Sandreas@sandberg.pp.se            if not hasattr(simobj, 'abstract') or not simobj.abstract:
9549986Sandreas@sandberg.pp.se                code('#include "cxx_config/${name}.hh"')
9559986Sandreas@sandberg.pp.se        code()
9569986Sandreas@sandberg.pp.se        code('void cxxConfigInit()')
9579986Sandreas@sandberg.pp.se        code('{')
9589986Sandreas@sandberg.pp.se        code.indent()
9599986Sandreas@sandberg.pp.se        for name,simobj in sorted(sim_objects.iteritems()):
9609986Sandreas@sandberg.pp.se            not_abstract = not hasattr(simobj, 'abstract') or \
9619986Sandreas@sandberg.pp.se                not simobj.abstract
9622638Sstever@eecs.umich.edu            if not_abstract and 'type' in simobj.__dict__:
9632638Sstever@eecs.umich.edu                code('cxx_config_directory["${name}"] = '
9646121Snate@binkert.org                     '${name}CxxConfigParams::makeDirectoryEntry();')
9653716Sstever@eecs.umich.edu        code.dedent()
9665522Snate@binkert.org        code('}')
9679986Sandreas@sandberg.pp.se        code.write(target[0].abspath)
9689986Sandreas@sandberg.pp.se
9699986Sandreas@sandberg.pp.se    py_source = PySource.modules[simobj.__module__]
9705522Snate@binkert.org    extra_deps = [ py_source.tnode ]
9715227Ssaidi@eecs.umich.edu    env.Command(cxx_config_init_cc_file, Value(name),
9725227Ssaidi@eecs.umich.edu        MakeAction(createCxxConfigInitCC, Transform("CXXCINIT")))
9735227Ssaidi@eecs.umich.edu    cxx_param_hh_files = ["cxx_config/%s.hh" % simobj
9745227Ssaidi@eecs.umich.edu        for name,simobj in sorted(sim_objects.iteritems())
9756654Snate@binkert.org        if not hasattr(simobj, 'abstract') or not simobj.abstract]
9766654Snate@binkert.org    Depends(cxx_config_init_cc_file, cxx_param_hh_files +
9777769SAli.Saidi@ARM.com            [File('sim/cxx_config.hh')])
9787769SAli.Saidi@ARM.com    Source(cxx_config_init_cc_file)
9797769SAli.Saidi@ARM.com
9807769SAli.Saidi@ARM.com# Generate all enum header files
9815227Ssaidi@eecs.umich.edufor name,enum in sorted(all_enums.iteritems()):
9825227Ssaidi@eecs.umich.edu    py_source = PySource.modules[enum.__module__]
9835227Ssaidi@eecs.umich.edu    extra_deps = [ py_source.tnode ]
9845204Sstever@gmail.com
9855204Sstever@gmail.com    cc_file = File('enums/%s.cc' % name)
9865204Sstever@gmail.com    env.Command(cc_file, [Value(name), Value(env['USE_PYTHON'])],
9875204Sstever@gmail.com                MakeAction(createEnumStrings, Transform("ENUM STR")))
9885204Sstever@gmail.com    env.Depends(cc_file, depends + extra_deps)
9895204Sstever@gmail.com    Source(cc_file)
9905204Sstever@gmail.com
9915204Sstever@gmail.com    hh_file = File('enums/%s.hh' % name)
9925204Sstever@gmail.com    env.Command(hh_file, Value(name),
9935204Sstever@gmail.com                MakeAction(createEnumDecls, Transform("ENUMDECL")))
9945204Sstever@gmail.com    env.Depends(hh_file, depends + extra_deps)
9955204Sstever@gmail.com
9965204Sstever@gmail.com# Generate SimObject Python bindings wrapper files
9975204Sstever@gmail.comif env['USE_PYTHON']:
9985204Sstever@gmail.com    for name,simobj in sorted(sim_objects.iteritems()):
9995204Sstever@gmail.com        py_source = PySource.modules[simobj.__module__]
10005204Sstever@gmail.com        extra_deps = [ py_source.tnode ]
10016121Snate@binkert.org        cc_file = File('python/_m5/param_%s.cc' % name)
10025204Sstever@gmail.com        env.Command(cc_file, Value(name),
10037727SAli.Saidi@ARM.com                    MakeAction(createSimObjectPyBindWrapper,
10047727SAli.Saidi@ARM.com                               Transform("SO PyBind")))
10057727SAli.Saidi@ARM.com        env.Depends(cc_file, depends + extra_deps)
10067727SAli.Saidi@ARM.com        Source(cc_file)
10077727SAli.Saidi@ARM.com
100811988Sandreas.sandberg@arm.com# Build all protocol buffers if we have got protoc and protobuf available
100911988Sandreas.sandberg@arm.comif env['HAVE_PROTOBUF']:
101010453SAndrew.Bardsley@arm.com    for proto in ProtoBuf.all:
101110453SAndrew.Bardsley@arm.com        # Use both the source and header as the target, and the .proto
101210453SAndrew.Bardsley@arm.com        # file as the source. When executing the protoc compiler, also
101310453SAndrew.Bardsley@arm.com        # specify the proto_path to avoid having the generated files
101410453SAndrew.Bardsley@arm.com        # include the path.
101510453SAndrew.Bardsley@arm.com        env.Command([proto.cc_file, proto.hh_file], proto.tnode,
101610453SAndrew.Bardsley@arm.com                    MakeAction('$PROTOC --cpp_out ${TARGET.dir} '
101710453SAndrew.Bardsley@arm.com                               '--proto_path ${SOURCE.dir} $SOURCE',
101810453SAndrew.Bardsley@arm.com                               Transform("PROTOC")))
101910453SAndrew.Bardsley@arm.com
102010160Sandreas.hansson@arm.com        # Add the C++ source file
102110453SAndrew.Bardsley@arm.com        Source(proto.cc_file, tags=proto.tags)
102210453SAndrew.Bardsley@arm.comelif ProtoBuf.all:
102310453SAndrew.Bardsley@arm.com    print('Got protobuf to build, but lacks support!')
102410453SAndrew.Bardsley@arm.com    Exit(1)
102510453SAndrew.Bardsley@arm.com
102610453SAndrew.Bardsley@arm.com#
102710453SAndrew.Bardsley@arm.com# Handle debug flags
102810453SAndrew.Bardsley@arm.com#
10299812Sandreas.hansson@arm.comdef makeDebugFlagCC(target, source, env):
103010453SAndrew.Bardsley@arm.com    assert(len(target) == 1 and len(source) == 1)
103110453SAndrew.Bardsley@arm.com
103210453SAndrew.Bardsley@arm.com    code = code_formatter()
103310453SAndrew.Bardsley@arm.com
103410453SAndrew.Bardsley@arm.com    # delay definition of CompoundFlags until after all the definition
103510453SAndrew.Bardsley@arm.com    # of all constituent SimpleFlags
103610453SAndrew.Bardsley@arm.com    comp_code = code_formatter()
103710453SAndrew.Bardsley@arm.com
103810453SAndrew.Bardsley@arm.com    # file header
103910453SAndrew.Bardsley@arm.com    code('''
104010453SAndrew.Bardsley@arm.com/*
104110453SAndrew.Bardsley@arm.com * DO NOT EDIT THIS FILE! Automatically generated by SCons.
10427727SAli.Saidi@ARM.com */
104310453SAndrew.Bardsley@arm.com
104410453SAndrew.Bardsley@arm.com#include "base/debug.hh"
104510453SAndrew.Bardsley@arm.com
104610453SAndrew.Bardsley@arm.comnamespace Debug {
104710453SAndrew.Bardsley@arm.com
10483118Sstever@eecs.umich.edu''')
104910453SAndrew.Bardsley@arm.com
105010453SAndrew.Bardsley@arm.com    for name, flag in sorted(source[0].read().iteritems()):
105110453SAndrew.Bardsley@arm.com        n, compound, desc = flag
105210453SAndrew.Bardsley@arm.com        assert n == name
10533118Sstever@eecs.umich.edu
10543483Ssaidi@eecs.umich.edu        if not compound:
10553494Ssaidi@eecs.umich.edu            code('SimpleFlag $name("$name", "$desc");')
10563494Ssaidi@eecs.umich.edu        else:
10573483Ssaidi@eecs.umich.edu            comp_code('CompoundFlag $name("$name", "$desc",')
10583483Ssaidi@eecs.umich.edu            comp_code.indent()
10593483Ssaidi@eecs.umich.edu            last = len(compound) - 1
10603053Sstever@eecs.umich.edu            for i,flag in enumerate(compound):
10613053Sstever@eecs.umich.edu                if i != last:
10623918Ssaidi@eecs.umich.edu                    comp_code('&$flag,')
10633053Sstever@eecs.umich.edu                else:
10643053Sstever@eecs.umich.edu                    comp_code('&$flag);')
10653053Sstever@eecs.umich.edu            comp_code.dedent()
10663053Sstever@eecs.umich.edu
10673053Sstever@eecs.umich.edu    code.append(comp_code)
10689396Sandreas.hansson@arm.com    code()
10699396Sandreas.hansson@arm.com    code('} // namespace Debug')
10709396Sandreas.hansson@arm.com
10719396Sandreas.hansson@arm.com    code.write(str(target[0]))
10729396Sandreas.hansson@arm.com
10739396Sandreas.hansson@arm.comdef makeDebugFlagHH(target, source, env):
10749396Sandreas.hansson@arm.com    assert(len(target) == 1 and len(source) == 1)
10759396Sandreas.hansson@arm.com
10769396Sandreas.hansson@arm.com    val = eval(source[0].get_contents())
10779477Sandreas.hansson@arm.com    name, compound, desc = val
10789396Sandreas.hansson@arm.com
10799477Sandreas.hansson@arm.com    code = code_formatter()
10809477Sandreas.hansson@arm.com
10819477Sandreas.hansson@arm.com    # file header boilerplate
10829477Sandreas.hansson@arm.com    code('''\
10839396Sandreas.hansson@arm.com/*
10847840Snate@binkert.org * DO NOT EDIT THIS FILE! Automatically generated by SCons.
10857865Sgblack@eecs.umich.edu */
10867865Sgblack@eecs.umich.edu
10877865Sgblack@eecs.umich.edu#ifndef __DEBUG_${name}_HH__
10887865Sgblack@eecs.umich.edu#define __DEBUG_${name}_HH__
10897865Sgblack@eecs.umich.edu
10907840Snate@binkert.orgnamespace Debug {
10919900Sandreas@sandberg.pp.se''')
10929900Sandreas@sandberg.pp.se
10939900Sandreas@sandberg.pp.se    if compound:
10949900Sandreas@sandberg.pp.se        code('class CompoundFlag;')
109510456SCurtis.Dunham@arm.com    code('class SimpleFlag;')
109610456SCurtis.Dunham@arm.com
109710456SCurtis.Dunham@arm.com    if compound:
109810456SCurtis.Dunham@arm.com        code('extern CompoundFlag $name;')
109910456SCurtis.Dunham@arm.com        for flag in compound:
110010456SCurtis.Dunham@arm.com            code('extern SimpleFlag $flag;')
110110456SCurtis.Dunham@arm.com    else:
110210456SCurtis.Dunham@arm.com        code('extern SimpleFlag $name;')
110310456SCurtis.Dunham@arm.com
110410456SCurtis.Dunham@arm.com    code('''
11059045SAli.Saidi@ARM.com}
110611235Sandreas.sandberg@arm.com
110711235Sandreas.sandberg@arm.com#endif // __DEBUG_${name}_HH__
110811235Sandreas.sandberg@arm.com''')
110911235Sandreas.sandberg@arm.com
111011235Sandreas.sandberg@arm.com    code.write(str(target[0]))
111111235Sandreas.sandberg@arm.com
111211235Sandreas.sandberg@arm.comfor name,flag in sorted(debug_flags.iteritems()):
111311235Sandreas.sandberg@arm.com    n, compound, desc = flag
111411811Sbaz21@cam.ac.uk    assert n == name
111511811Sbaz21@cam.ac.uk
111611811Sbaz21@cam.ac.uk    hh_file = 'debug/%s.hh' % name
111711811Sbaz21@cam.ac.uk    env.Command(hh_file, Value(flag),
111811811Sbaz21@cam.ac.uk                MakeAction(makeDebugFlagHH, Transform("TRACING", 0)))
111911235Sandreas.sandberg@arm.com
112011235Sandreas.sandberg@arm.comenv.Command('debug/flags.cc', Value(debug_flags),
112111235Sandreas.sandberg@arm.com            MakeAction(makeDebugFlagCC, Transform("TRACING", 0)))
112211235Sandreas.sandberg@arm.comSource('debug/flags.cc')
112311235Sandreas.sandberg@arm.com
112411235Sandreas.sandberg@arm.com# version tags
112511235Sandreas.sandberg@arm.comtags = \
11267840Snate@binkert.orgenv.Command('sim/tags.cc', None,
11277840Snate@binkert.org            MakeAction('util/cpt_upgrader.py --get-cc-file > $TARGET',
11287840Snate@binkert.org                       Transform("VER TAGS")))
11291858SN/Aenv.AlwaysBuild(tags)
11301858SN/A
11311858SN/A# Build a small helper that marshals the Python code using the same
11321858SN/A# version of Python as gem5. This is in an unorthodox location to
11331858SN/A# avoid building it for every variant.
11341858SN/Apy_marshal = env.Program('python/marshal.cc')[0]
11359903Sandreas.hansson@arm.com
11369903Sandreas.hansson@arm.com# Embed python files.  All .py files that have been indicated by a
11379903Sandreas.hansson@arm.com# PySource() call in a SConscript need to be embedded into the M5
11389903Sandreas.hansson@arm.com# library.  To do that, we compile the file to byte code, marshal the
113910841Sandreas.sandberg@arm.com# byte code, compress it, and then generate a c++ file that
11409651SAndreas.Sandberg@ARM.com# inserts the result into an array.
11419903Sandreas.hansson@arm.comdef embedPyFile(target, source, env):
11429651SAndreas.Sandberg@ARM.com    def c_str(string):
11439651SAndreas.Sandberg@ARM.com        if string is None:
114412056Sgabeblack@google.com            return "0"
114512056Sgabeblack@google.com        return '"%s"' % string
114612056Sgabeblack@google.com
114712056Sgabeblack@google.com    '''Action function to compile a .py into a code object, marshal it,
114812056Sgabeblack@google.com    compress it, and stick it into an asm file so the code appears as
114910841Sandreas.sandberg@arm.com    just bytes with a label in the data section. The action takes two
115010841Sandreas.sandberg@arm.com    sources:
115110841Sandreas.sandberg@arm.com
115210841Sandreas.sandberg@arm.com    source[0]: Binary used to marshal Python sources
115310841Sandreas.sandberg@arm.com    source[1]: Python script to marshal
115410841Sandreas.sandberg@arm.com    '''
11559651SAndreas.Sandberg@ARM.com
11569651SAndreas.Sandberg@ARM.com    import subprocess
11579651SAndreas.Sandberg@ARM.com
11589651SAndreas.Sandberg@ARM.com    marshalled = subprocess.check_output([source[0].abspath, str(source[1])])
11599651SAndreas.Sandberg@ARM.com
11609651SAndreas.Sandberg@ARM.com    compressed = zlib.compress(marshalled)
11619651SAndreas.Sandberg@ARM.com    data = compressed
11629651SAndreas.Sandberg@ARM.com    pysource = PySource.tnodes[source[1]]
11639651SAndreas.Sandberg@ARM.com    sym = pysource.symname
116410841Sandreas.sandberg@arm.com
116510841Sandreas.sandberg@arm.com    code = code_formatter()
116610841Sandreas.sandberg@arm.com    code('''\
116710841Sandreas.sandberg@arm.com#include "sim/init.hh"
116810841Sandreas.sandberg@arm.com
116910841Sandreas.sandberg@arm.comnamespace {
117010860Sandreas.sandberg@arm.com
117110841Sandreas.sandberg@arm.com''')
117210841Sandreas.sandberg@arm.com    blobToCpp(data, 'data_' + sym, code)
117310841Sandreas.sandberg@arm.com    code('''\
117410841Sandreas.sandberg@arm.com
117510841Sandreas.sandberg@arm.com
117610841Sandreas.sandberg@arm.comEmbeddedPython embedded_${sym}(
117710841Sandreas.sandberg@arm.com    ${{c_str(pysource.arcname)}},
117810841Sandreas.sandberg@arm.com    ${{c_str(pysource.abspath)}},
117910841Sandreas.sandberg@arm.com    ${{c_str(pysource.modpath)}},
118010841Sandreas.sandberg@arm.com    data_${sym},
118110841Sandreas.sandberg@arm.com    ${{len(data)}},
11829651SAndreas.Sandberg@ARM.com    ${{len(marshalled)}});
11839651SAndreas.Sandberg@ARM.com
11849986Sandreas@sandberg.pp.se} // anonymous namespace
11859986Sandreas@sandberg.pp.se''')
11869986Sandreas@sandberg.pp.se    code.write(str(target[0]))
11879986Sandreas@sandberg.pp.se
11889986Sandreas@sandberg.pp.sefor source in PySource.all:
11899986Sandreas@sandberg.pp.se    env.Command(source.cpp, [ py_marshal, source.tnode ],
11905863Snate@binkert.org                MakeAction(embedPyFile, Transform("EMBED PY")))
11915863Snate@binkert.org    Source(source.cpp, tags=source.tags, add_tags='python')
11925863Snate@binkert.org
11935863Snate@binkert.org########################################################################
11946121Snate@binkert.org#
11951858SN/A# Define binaries.  Each different build type (debug, opt, etc.) gets
11965863Snate@binkert.org# a slightly different build environment.
11975863Snate@binkert.org#
11985863Snate@binkert.org
11995863Snate@binkert.org# List of constructed environments to pass back to SConstruct
12005863Snate@binkert.orgdate_source = Source('base/date.cc', tags=[])
12012139SN/A
12024202Sbinkertn@umich.edugem5_binary = Gem5('gem5')
120311308Santhony.gutierrez@amd.com
12044202Sbinkertn@umich.edu# Function to create a new build environment as clone of current
120511308Santhony.gutierrez@amd.com# environment 'env' with modified object suffix and optional stripped
12062139SN/A# binary.  Additional keyword arguments are appended to corresponding
12076994Snate@binkert.org# build environment vars.
12086994Snate@binkert.orgdef makeEnv(env, label, objsfx, strip=False, disable_partial=False, **kwargs):
12096994Snate@binkert.org    # SCons doesn't know to append a library suffix when there is a '.' in the
12106994Snate@binkert.org    # name.  Use '_' instead.
12116994Snate@binkert.org    libname = 'gem5_' + label
12126994Snate@binkert.org    secondary_exename = 'm5.' + label
12136994Snate@binkert.org
12146994Snate@binkert.org    new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's')
121510319SAndreas.Sandberg@ARM.com    new_env.Label = label
12166994Snate@binkert.org    new_env.Append(**kwargs)
12176994Snate@binkert.org
12186994Snate@binkert.org    lib_sources = Source.all.with_tag('gem5 lib')
12196994Snate@binkert.org
12206994Snate@binkert.org    # Without Python, leave out all Python content from the library
12216994Snate@binkert.org    # builds.  The option doesn't affect gem5 built as a program
12226994Snate@binkert.org    if GetOption('without_python'):
12236994Snate@binkert.org        lib_sources = lib_sources.without_tag('python')
12246994Snate@binkert.org
12256994Snate@binkert.org    static_objs = []
12266994Snate@binkert.org    shared_objs = []
12272155SN/A
12285863Snate@binkert.org    for s in lib_sources.with_tag(Source.ungrouped_tag):
12291869SN/A        static_objs.append(s.static(new_env))
12301869SN/A        shared_objs.append(s.shared(new_env))
12315863Snate@binkert.org
12325863Snate@binkert.org    for group in Source.source_groups:
12334202Sbinkertn@umich.edu        srcs = lib_sources.with_tag(Source.link_group_tag(group))
12346108Snate@binkert.org        if not srcs:
12356108Snate@binkert.org            continue
12366108Snate@binkert.org
12376108Snate@binkert.org        group_static = [ s.static(new_env) for s in srcs ]
12389219Spower.jg@gmail.com        group_shared = [ s.shared(new_env) for s in srcs ]
12399219Spower.jg@gmail.com
12409219Spower.jg@gmail.com        # If partial linking is disabled, add these sources to the build
12419219Spower.jg@gmail.com        # directly, and short circuit this loop.
12429219Spower.jg@gmail.com        if disable_partial:
12439219Spower.jg@gmail.com            static_objs.extend(group_static)
12449219Spower.jg@gmail.com            shared_objs.extend(group_shared)
12459219Spower.jg@gmail.com            continue
12464202Sbinkertn@umich.edu
12475863Snate@binkert.org        # Set up the static partially linked objects.
124810135SCurtis.Dunham@arm.com        file_name = new_env.subst("${OBJPREFIX}lib${OBJSUFFIX}.partial")
12498474Sgblack@eecs.umich.edu        target = File(joinpath(group, file_name))
12505742Snate@binkert.org        partial = env.PartialStatic(target=target, source=group_static)
12518268Ssteve.reinhardt@amd.com        static_objs.extend(partial)
12528268Ssteve.reinhardt@amd.com
12538268Ssteve.reinhardt@amd.com        # Set up the shared partially linked objects.
12545742Snate@binkert.org        file_name = new_env.subst("${SHOBJPREFIX}lib${SHOBJSUFFIX}.partial")
12555341Sstever@gmail.com        target = File(joinpath(group, file_name))
12568474Sgblack@eecs.umich.edu        partial = env.PartialShared(target=target, source=group_shared)
12578474Sgblack@eecs.umich.edu        shared_objs.extend(partial)
12585342Sstever@gmail.com
12594202Sbinkertn@umich.edu    static_date = date_source.static(new_env)
12604202Sbinkertn@umich.edu    new_env.Depends(static_date, static_objs)
126111308Santhony.gutierrez@amd.com    static_objs.extend(static_date)
12624202Sbinkertn@umich.edu
12635863Snate@binkert.org    shared_date = date_source.shared(new_env)
12645863Snate@binkert.org    new_env.Depends(shared_date, shared_objs)
126511308Santhony.gutierrez@amd.com    shared_objs.extend(shared_date)
12666994Snate@binkert.org
12676994Snate@binkert.org    main_objs = [ s.static(new_env) for s in Source.all.with_tag('main') ]
126810319SAndreas.Sandberg@ARM.com
12695863Snate@binkert.org    # First make a library of everything but main() so other programs can
12705863Snate@binkert.org    # link against m5.
12715863Snate@binkert.org    static_lib = new_env.StaticLibrary(libname, static_objs)
12725863Snate@binkert.org    shared_lib = new_env.SharedLibrary(libname, shared_objs)
12735863Snate@binkert.org
12745863Snate@binkert.org    # Keep track of the object files generated so far so Executables can
12755863Snate@binkert.org    # include them.
12765863Snate@binkert.org    new_env['STATIC_OBJS'] = static_objs
12777840Snate@binkert.org    new_env['SHARED_OBJS'] = shared_objs
12785863Snate@binkert.org    new_env['MAIN_OBJS'] = main_objs
12795952Ssaidi@eecs.umich.edu
12809651SAndreas.Sandberg@ARM.com    new_env['STATIC_LIB'] = static_lib
128112056Sgabeblack@google.com    new_env['SHARED_LIB'] = shared_lib
128212056Sgabeblack@google.com
128312056Sgabeblack@google.com    # Record some settings for building Executables.
128411308Santhony.gutierrez@amd.com    new_env['EXE_SUFFIX'] = label
12859219Spower.jg@gmail.com    new_env['STRIP_EXES'] = strip
12869219Spower.jg@gmail.com
128711235Sandreas.sandberg@arm.com    for cls in ExecutableMeta.all:
128811235Sandreas.sandberg@arm.com        cls.declare_all(new_env)
12891869SN/A
12901858SN/A    new_env.M5Binary = File(gem5_binary.path(new_env))
12915863Snate@binkert.org
129211308Santhony.gutierrez@amd.com    new_env.Command(secondary_exename, new_env.M5Binary,
129312061Sjason@lowepower.com            MakeAction('ln $SOURCE $TARGET', Transform("HARDLINK")))
129412061Sjason@lowepower.com
12951858SN/A    # Set up regression tests.
1296955SN/A    SConscript(os.path.join(env.root.abspath, 'tests', 'SConscript'),
1297955SN/A               variant_dir=Dir('tests').Dir(new_env.Label),
12981869SN/A               exports={ 'env' : new_env }, duplicate=False)
12991869SN/A
13001869SN/A# Start out with the compiler flags common to all compilers,
13011869SN/A# i.e. they all use -g for opt and -g -pg for prof
13021869SN/Accflags = {'debug' : [], 'opt' : ['-g'], 'fast' : [], 'prof' : ['-g', '-pg'],
13035863Snate@binkert.org           'perf' : ['-g']}
13045863Snate@binkert.org
13055863Snate@binkert.org# Start out with the linker flags common to all linkers, i.e. -pg for
13061869SN/A# prof, and -lprofiler for perf. The -lprofile flag is surrounded by
13075863Snate@binkert.org# no-as-needed and as-needed as the binutils linker is too clever and
13081869SN/A# simply doesn't link to the library otherwise.
13095863Snate@binkert.orgldflags = {'debug' : [], 'opt' : [], 'fast' : [], 'prof' : ['-pg'],
13101869SN/A           'perf' : ['-Wl,--no-as-needed', '-lprofiler', '-Wl,--as-needed']}
13111869SN/A
13121869SN/A# For Link Time Optimization, the optimisation flags used to compile
13131869SN/A# individual files are decoupled from those used at link time
13148483Sgblack@eecs.umich.edu# (i.e. you can compile with -O3 and perform LTO with -O0), so we need
13151869SN/A# to also update the linker flags based on the target.
13161869SN/Aif env['GCC']:
13171869SN/A    if sys.platform == 'sunos5':
13181869SN/A        ccflags['debug'] += ['-gstabs+']
13195863Snate@binkert.org    else:
13205863Snate@binkert.org        ccflags['debug'] += ['-ggdb3']
13211869SN/A    ldflags['debug'] += ['-O0']
13225863Snate@binkert.org    # opt, fast, prof and perf all share the same cc flags, also add
13235863Snate@binkert.org    # the optimization to the ldflags as LTO defers the optimization
13243356Sbinkertn@umich.edu    # to link time
13253356Sbinkertn@umich.edu    for target in ['opt', 'fast', 'prof', 'perf']:
13263356Sbinkertn@umich.edu        ccflags[target] += ['-O3']
13273356Sbinkertn@umich.edu        ldflags[target] += ['-O3']
13283356Sbinkertn@umich.edu
13294781Snate@binkert.org    ccflags['fast'] += env['LTO_CCFLAGS']
13305863Snate@binkert.org    ldflags['fast'] += env['LTO_LDFLAGS']
13315863Snate@binkert.orgelif env['CLANG']:
13321869SN/A    ccflags['debug'] += ['-g', '-O0']
13331869SN/A    # opt, fast, prof and perf all share the same cc flags
13341869SN/A    for target in ['opt', 'fast', 'prof', 'perf']:
13356121Snate@binkert.org        ccflags[target] += ['-O3']
13361869SN/Aelse:
133711982Sgabeblack@google.com    print('Unknown compiler, please fix compiler options')
133811982Sgabeblack@google.com    Exit(1)
133911982Sgabeblack@google.com
134011982Sgabeblack@google.com
134111982Sgabeblack@google.com# To speed things up, we only instantiate the build environments we
134211982Sgabeblack@google.com# need.  We try to identify the needed environment for each target; if
134311982Sgabeblack@google.com# we can't, we fall back on instantiating all the environments just to
134411982Sgabeblack@google.com# be safe.
134511982Sgabeblack@google.comtarget_types = ['debug', 'opt', 'fast', 'prof', 'perf']
134611982Sgabeblack@google.comobj2target = {'do': 'debug', 'o': 'opt', 'fo': 'fast', 'po': 'prof',
134711982Sgabeblack@google.com              'gpo' : 'perf'}
134811982Sgabeblack@google.com
134911982Sgabeblack@google.comdef identifyTarget(t):
135011982Sgabeblack@google.com    ext = t.split('.')[-1]
135111982Sgabeblack@google.com    if ext in target_types:
135211982Sgabeblack@google.com        return ext
135311982Sgabeblack@google.com    if ext in obj2target:
135411982Sgabeblack@google.com        return obj2target[ext]
135511982Sgabeblack@google.com    match = re.search(r'/tests/([^/]+)/', t)
135611982Sgabeblack@google.com    if match and match.group(1) in target_types:
135711982Sgabeblack@google.com        return match.group(1)
135811982Sgabeblack@google.com    return 'all'
135911982Sgabeblack@google.com
136011982Sgabeblack@google.comneeded_envs = [identifyTarget(target) for target in BUILD_TARGETS]
136111982Sgabeblack@google.comif 'all' in needed_envs:
136211982Sgabeblack@google.com    needed_envs += target_types
136311978Sgabeblack@google.com
136411978Sgabeblack@google.comdisable_partial = False
136512034Sgabeblack@google.comif env['PLATFORM'] == 'darwin':
136611978Sgabeblack@google.com    # Up until Apple LLVM version 10.0.0 (clang-1000.11.45.5), partial
136711978Sgabeblack@google.com    # linked objects do not expose symbols that are marked with the
136811978Sgabeblack@google.com    # hidden visibility and consequently building gem5 on Mac OS
136912034Sgabeblack@google.com    # fails. As a workaround, we disable partial linking, however, we
137011978Sgabeblack@google.com    # may want to revisit in the future.
137111978Sgabeblack@google.com    disable_partial = True
137210915Sandreas.sandberg@arm.com
137311986Sandreas.sandberg@arm.com# Debug binary
137411986Sandreas.sandberg@arm.comif 'debug' in needed_envs:
13751869SN/A    makeEnv(env, 'debug', '.do',
13761869SN/A            CCFLAGS = Split(ccflags['debug']),
137712015Sgabeblack@google.com            CPPDEFINES = ['DEBUG', 'TRACING_ON=1'],
137812015Sgabeblack@google.com            LINKFLAGS = Split(ldflags['debug']),
137912015Sgabeblack@google.com            disable_partial=disable_partial)
138012015Sgabeblack@google.com
13813546Sgblack@eecs.umich.edu# Optimized binary
13823546Sgblack@eecs.umich.eduif 'opt' in needed_envs:
13833546Sgblack@eecs.umich.edu    makeEnv(env, 'opt', '.o',
138412015Sgabeblack@google.com            CCFLAGS = Split(ccflags['opt']),
138512015Sgabeblack@google.com            CPPDEFINES = ['TRACING_ON=1'],
138612015Sgabeblack@google.com            LINKFLAGS = Split(ldflags['opt']),
138712015Sgabeblack@google.com            disable_partial=disable_partial)
138812015Sgabeblack@google.com
138912015Sgabeblack@google.com# "Fast" binary
139012015Sgabeblack@google.comif 'fast' in needed_envs:
139112015Sgabeblack@google.com    disable_partial = disable_partial and \
13923546Sgblack@eecs.umich.edu            env.get('BROKEN_INCREMENTAL_LTO', False) and \
139312015Sgabeblack@google.com            GetOption('force_lto')
139412015Sgabeblack@google.com    makeEnv(env, 'fast', '.fo', strip = True,
139510196SCurtis.Dunham@arm.com            CCFLAGS = Split(ccflags['fast']),
139612015Sgabeblack@google.com            CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
139712015Sgabeblack@google.com            LINKFLAGS = Split(ldflags['fast']),
139812015Sgabeblack@google.com            disable_partial=disable_partial)
139912015Sgabeblack@google.com
140012015Sgabeblack@google.com# Profiled binary using gprof
140112015Sgabeblack@google.comif 'prof' in needed_envs:
140212015Sgabeblack@google.com    makeEnv(env, 'prof', '.po',
140312015Sgabeblack@google.com            CCFLAGS = Split(ccflags['prof']),
140412015Sgabeblack@google.com            CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
140512015Sgabeblack@google.com            LINKFLAGS = Split(ldflags['prof']),
140612015Sgabeblack@google.com            disable_partial=disable_partial)
14073546Sgblack@eecs.umich.edu
140810196SCurtis.Dunham@arm.com# Profiled binary using google-pprof
140910196SCurtis.Dunham@arm.comif 'perf' in needed_envs:
141010196SCurtis.Dunham@arm.com    makeEnv(env, 'perf', '.gpo',
141110196SCurtis.Dunham@arm.com            CCFLAGS = Split(ccflags['perf']),
141210196SCurtis.Dunham@arm.com            CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
141310196SCurtis.Dunham@arm.com            LINKFLAGS = Split(ldflags['perf']),
141410196SCurtis.Dunham@arm.com            disable_partial=disable_partial)
141510196SCurtis.Dunham@arm.com