SConscript revision 13675:afeab32b3655
113531Sjairo.balart@metempsy.com# -*- mode:python -*-
214167Sgiacomo.travaglini@arm.com
314167Sgiacomo.travaglini@arm.com# Copyright (c) 2018 ARM Limited
414167Sgiacomo.travaglini@arm.com#
514167Sgiacomo.travaglini@arm.com# The license below extends only to copyright in the software and shall
614167Sgiacomo.travaglini@arm.com# not be construed as granting a license to any other intellectual
714167Sgiacomo.travaglini@arm.com# property including but not limited to intellectual property relating
814167Sgiacomo.travaglini@arm.com# to a hardware implementation of the functionality of the software
914167Sgiacomo.travaglini@arm.com# licensed hereunder.  You may use the software subject to the license
1014167Sgiacomo.travaglini@arm.com# terms below provided that you ensure that this notice is replicated
1114167Sgiacomo.travaglini@arm.com# unmodified and in its entirety in all distributions of the software,
1214167Sgiacomo.travaglini@arm.com# modified or unmodified, in source code or in binary form.
1314167Sgiacomo.travaglini@arm.com#
1413531Sjairo.balart@metempsy.com# Copyright (c) 2004-2005 The Regents of The University of Michigan
1513531Sjairo.balart@metempsy.com# All rights reserved.
1613531Sjairo.balart@metempsy.com#
1713531Sjairo.balart@metempsy.com# Redistribution and use in source and binary forms, with or without
1813531Sjairo.balart@metempsy.com# modification, are permitted provided that the following conditions are
1913531Sjairo.balart@metempsy.com# met: redistributions of source code must retain the above copyright
2013531Sjairo.balart@metempsy.com# notice, this list of conditions and the following disclaimer;
2113531Sjairo.balart@metempsy.com# redistributions in binary form must reproduce the above copyright
2213531Sjairo.balart@metempsy.com# notice, this list of conditions and the following disclaimer in the
2313531Sjairo.balart@metempsy.com# documentation and/or other materials provided with the distribution;
2413531Sjairo.balart@metempsy.com# neither the name of the copyright holders nor the names of its
2513531Sjairo.balart@metempsy.com# contributors may be used to endorse or promote products derived from
2613531Sjairo.balart@metempsy.com# this software without specific prior written permission.
2713531Sjairo.balart@metempsy.com#
2813531Sjairo.balart@metempsy.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2913531Sjairo.balart@metempsy.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3013531Sjairo.balart@metempsy.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3113531Sjairo.balart@metempsy.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3213531Sjairo.balart@metempsy.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3313531Sjairo.balart@metempsy.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3413531Sjairo.balart@metempsy.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3513531Sjairo.balart@metempsy.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3613531Sjairo.balart@metempsy.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3713531Sjairo.balart@metempsy.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3813531Sjairo.balart@metempsy.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3913531Sjairo.balart@metempsy.com#
4013531Sjairo.balart@metempsy.com# Authors: Nathan Binkert
4113531Sjairo.balart@metempsy.com
4213756Sjairo.balart@metempsy.comfrom __future__ import print_function
4313531Sjairo.balart@metempsy.com
4413531Sjairo.balart@metempsy.comimport array
4513531Sjairo.balart@metempsy.comimport bisect
4613531Sjairo.balart@metempsy.comimport functools
4714257Sgiacomo.travaglini@arm.comimport imp
4813531Sjairo.balart@metempsy.comimport marshal
4913531Sjairo.balart@metempsy.comimport os
5013531Sjairo.balart@metempsy.comimport re
5113531Sjairo.balart@metempsy.comimport subprocess
5213531Sjairo.balart@metempsy.comimport sys
5313756Sjairo.balart@metempsy.comimport zlib
5413756Sjairo.balart@metempsy.com
5513756Sjairo.balart@metempsy.comfrom os.path import basename, dirname, exists, isdir, isfile, join as joinpath
5613756Sjairo.balart@metempsy.com
5713756Sjairo.balart@metempsy.comimport SCons
5813756Sjairo.balart@metempsy.com
5913756Sjairo.balart@metempsy.comfrom gem5_scons import Transform
6013531Sjairo.balart@metempsy.com
6113756Sjairo.balart@metempsy.com# This file defines how to build a particular configuration of gem5
6213756Sjairo.balart@metempsy.com# based on variable settings in the 'env' build environment.
6313756Sjairo.balart@metempsy.com
6413756Sjairo.balart@metempsy.comImport('*')
6513756Sjairo.balart@metempsy.com
6613756Sjairo.balart@metempsy.com# Children need to see the environment
6713756Sjairo.balart@metempsy.comExport('env')
6813531Sjairo.balart@metempsy.com
6913531Sjairo.balart@metempsy.combuild_env = [(opt, env[opt]) for opt in export_vars]
7013531Sjairo.balart@metempsy.com
7113531Sjairo.balart@metempsy.comfrom m5.util import code_formatter, compareVersions
7214258Sgiacomo.travaglini@arm.com
7314258Sgiacomo.travaglini@arm.com########################################################################
7414258Sgiacomo.travaglini@arm.com# Code for adding source files of various types
7514258Sgiacomo.travaglini@arm.com#
7614258Sgiacomo.travaglini@arm.com# When specifying a source file of some type, a set of tags can be
7714258Sgiacomo.travaglini@arm.com# specified for that file.
7814258Sgiacomo.travaglini@arm.com
7914258Sgiacomo.travaglini@arm.comclass SourceFilter(object):
8014258Sgiacomo.travaglini@arm.com    def __init__(self, predicate):
8114258Sgiacomo.travaglini@arm.com        self.predicate = predicate
8214258Sgiacomo.travaglini@arm.com
8314258Sgiacomo.travaglini@arm.com    def __or__(self, other):
8414258Sgiacomo.travaglini@arm.com        return SourceFilter(lambda tags: self.predicate(tags) or
8514257Sgiacomo.travaglini@arm.com                                         other.predicate(tags))
8614167Sgiacomo.travaglini@arm.com
8714167Sgiacomo.travaglini@arm.com    def __and__(self, other):
8814167Sgiacomo.travaglini@arm.com        return SourceFilter(lambda tags: self.predicate(tags) and
8914167Sgiacomo.travaglini@arm.com                                         other.predicate(tags))
9014167Sgiacomo.travaglini@arm.com
9113531Sjairo.balart@metempsy.comdef with_tags_that(predicate):
9213531Sjairo.balart@metempsy.com    '''Return a list of sources with tags that satisfy a predicate.'''
9314257Sgiacomo.travaglini@arm.com    return SourceFilter(predicate)
9414257Sgiacomo.travaglini@arm.com
9514257Sgiacomo.travaglini@arm.comdef with_any_tags(*tags):
9614257Sgiacomo.travaglini@arm.com    '''Return a list of sources with any of the supplied tags.'''
9714257Sgiacomo.travaglini@arm.com    return SourceFilter(lambda stags: len(set(tags) & stags) > 0)
9814257Sgiacomo.travaglini@arm.com
9914257Sgiacomo.travaglini@arm.comdef with_all_tags(*tags):
10014257Sgiacomo.travaglini@arm.com    '''Return a list of sources with all of the supplied tags.'''
10114257Sgiacomo.travaglini@arm.com    return SourceFilter(lambda stags: set(tags) <= stags)
10214257Sgiacomo.travaglini@arm.com
10314257Sgiacomo.travaglini@arm.comdef with_tag(tag):
10414257Sgiacomo.travaglini@arm.com    '''Return a list of sources with the supplied tag.'''
10514257Sgiacomo.travaglini@arm.com    return SourceFilter(lambda stags: tag in stags)
10614257Sgiacomo.travaglini@arm.com
10714257Sgiacomo.travaglini@arm.comdef without_tags(*tags):
10814257Sgiacomo.travaglini@arm.com    '''Return a list of sources without any of the supplied tags.'''
10914257Sgiacomo.travaglini@arm.com    return SourceFilter(lambda stags: len(set(tags) & stags) == 0)
11014257Sgiacomo.travaglini@arm.com
11114257Sgiacomo.travaglini@arm.comdef without_tag(tag):
11214257Sgiacomo.travaglini@arm.com    '''Return a list of sources with the supplied tag.'''
11314257Sgiacomo.travaglini@arm.com    return SourceFilter(lambda stags: tag not in stags)
11414257Sgiacomo.travaglini@arm.com
11514257Sgiacomo.travaglini@arm.comsource_filter_factories = {
11614257Sgiacomo.travaglini@arm.com    'with_tags_that': with_tags_that,
11714257Sgiacomo.travaglini@arm.com    'with_any_tags': with_any_tags,
11814257Sgiacomo.travaglini@arm.com    'with_all_tags': with_all_tags,
11914257Sgiacomo.travaglini@arm.com    'with_tag': with_tag,
12014257Sgiacomo.travaglini@arm.com    'without_tags': without_tags,
12114257Sgiacomo.travaglini@arm.com    'without_tag': without_tag,
12214257Sgiacomo.travaglini@arm.com}
12314257Sgiacomo.travaglini@arm.com
12413531Sjairo.balart@metempsy.comExport(source_filter_factories)
12513531Sjairo.balart@metempsy.com
12613531Sjairo.balart@metempsy.comclass SourceList(list):
12713531Sjairo.balart@metempsy.com    def apply_filter(self, f):
12813531Sjairo.balart@metempsy.com        def match(source):
12913531Sjairo.balart@metempsy.com            return f.predicate(source.tags)
13014258Sgiacomo.travaglini@arm.com        return SourceList(filter(match, self))
13113531Sjairo.balart@metempsy.com
13214258Sgiacomo.travaglini@arm.com    def __getattr__(self, name):
13314258Sgiacomo.travaglini@arm.com        func = source_filter_factories.get(name, None)
13414258Sgiacomo.travaglini@arm.com        if not func:
13513531Sjairo.balart@metempsy.com            raise AttributeError
13613531Sjairo.balart@metempsy.com
13713531Sjairo.balart@metempsy.com        @functools.wraps(func)
13813531Sjairo.balart@metempsy.com        def wrapper(*args, **kwargs):
13913531Sjairo.balart@metempsy.com            return self.apply_filter(func(*args, **kwargs))
14013531Sjairo.balart@metempsy.com        return wrapper
14113531Sjairo.balart@metempsy.com
14213531Sjairo.balart@metempsy.comclass SourceMeta(type):
14313531Sjairo.balart@metempsy.com    '''Meta class for source files that keeps track of all files of a
14413531Sjairo.balart@metempsy.com    particular type.'''
14513531Sjairo.balart@metempsy.com    def __init__(cls, name, bases, dict):
14613531Sjairo.balart@metempsy.com        super(SourceMeta, cls).__init__(name, bases, dict)
14713531Sjairo.balart@metempsy.com        cls.all = SourceList()
14813531Sjairo.balart@metempsy.com
14913531Sjairo.balart@metempsy.comclass SourceFile(object):
15013531Sjairo.balart@metempsy.com    '''Base object that encapsulates the notion of a source file.
15113531Sjairo.balart@metempsy.com    This includes, the source node, target node, various manipulations
15213531Sjairo.balart@metempsy.com    of those.  A source file also specifies a set of tags which
15313531Sjairo.balart@metempsy.com    describing arbitrary properties of the source file.'''
15413531Sjairo.balart@metempsy.com    __metaclass__ = SourceMeta
15513756Sjairo.balart@metempsy.com
15613531Sjairo.balart@metempsy.com    static_objs = {}
15713531Sjairo.balart@metempsy.com    shared_objs = {}
15813531Sjairo.balart@metempsy.com
15913531Sjairo.balart@metempsy.com    def __init__(self, source, tags=None, add_tags=None):
16013756Sjairo.balart@metempsy.com        if tags is None:
16113531Sjairo.balart@metempsy.com            tags='gem5 lib'
16213531Sjairo.balart@metempsy.com        if isinstance(tags, basestring):
16313531Sjairo.balart@metempsy.com            tags = set([tags])
16413531Sjairo.balart@metempsy.com        if not isinstance(tags, set):
16513531Sjairo.balart@metempsy.com            tags = set(tags)
16613531Sjairo.balart@metempsy.com        self.tags = tags
16713531Sjairo.balart@metempsy.com
16813531Sjairo.balart@metempsy.com        if add_tags:
16913531Sjairo.balart@metempsy.com            if isinstance(add_tags, basestring):
17013756Sjairo.balart@metempsy.com                add_tags = set([add_tags])
17113756Sjairo.balart@metempsy.com            if not isinstance(add_tags, set):
17213531Sjairo.balart@metempsy.com                add_tags = set(add_tags)
17313531Sjairo.balart@metempsy.com            self.tags |= add_tags
17413531Sjairo.balart@metempsy.com
17513531Sjairo.balart@metempsy.com        tnode = source
17613531Sjairo.balart@metempsy.com        if not isinstance(source, SCons.Node.FS.File):
17713531Sjairo.balart@metempsy.com            tnode = File(source)
17813531Sjairo.balart@metempsy.com
17913531Sjairo.balart@metempsy.com        self.tnode = tnode
18013531Sjairo.balart@metempsy.com        self.snode = tnode.srcnode()
18113531Sjairo.balart@metempsy.com
18213531Sjairo.balart@metempsy.com        for base in type(self).__mro__:
18313531Sjairo.balart@metempsy.com            if issubclass(base, SourceFile):
18413531Sjairo.balart@metempsy.com                base.all.append(self)
18513531Sjairo.balart@metempsy.com
18613531Sjairo.balart@metempsy.com    def static(self, env):
18713531Sjairo.balart@metempsy.com        key = (self.tnode, env['OBJSUFFIX'])
18813531Sjairo.balart@metempsy.com        if not key in self.static_objs:
18913531Sjairo.balart@metempsy.com            self.static_objs[key] = env.StaticObject(self.tnode)
19013531Sjairo.balart@metempsy.com        return self.static_objs[key]
19113756Sjairo.balart@metempsy.com
19213756Sjairo.balart@metempsy.com    def shared(self, env):
19313531Sjairo.balart@metempsy.com        key = (self.tnode, env['OBJSUFFIX'])
19413531Sjairo.balart@metempsy.com        if not key in self.shared_objs:
19513531Sjairo.balart@metempsy.com            self.shared_objs[key] = env.SharedObject(self.tnode)
19613531Sjairo.balart@metempsy.com        return self.shared_objs[key]
19713531Sjairo.balart@metempsy.com
19813531Sjairo.balart@metempsy.com    @property
19913531Sjairo.balart@metempsy.com    def filename(self):
20013531Sjairo.balart@metempsy.com        return str(self.tnode)
20113531Sjairo.balart@metempsy.com
20213531Sjairo.balart@metempsy.com    @property
20313756Sjairo.balart@metempsy.com    def dirname(self):
20413531Sjairo.balart@metempsy.com        return dirname(self.filename)
20513531Sjairo.balart@metempsy.com
20613531Sjairo.balart@metempsy.com    @property
20713531Sjairo.balart@metempsy.com    def basename(self):
20813531Sjairo.balart@metempsy.com        return basename(self.filename)
20913531Sjairo.balart@metempsy.com
21013531Sjairo.balart@metempsy.com    @property
21113531Sjairo.balart@metempsy.com    def extname(self):
21213756Sjairo.balart@metempsy.com        index = self.basename.rfind('.')
21313756Sjairo.balart@metempsy.com        if index <= 0:
21413531Sjairo.balart@metempsy.com            # dot files aren't extensions
21513531Sjairo.balart@metempsy.com            return self.basename, None
21613531Sjairo.balart@metempsy.com
21713531Sjairo.balart@metempsy.com        return self.basename[:index], self.basename[index+1:]
21813531Sjairo.balart@metempsy.com
21913531Sjairo.balart@metempsy.com    def __lt__(self, other): return self.filename < other.filename
22013531Sjairo.balart@metempsy.com    def __le__(self, other): return self.filename <= other.filename
22113531Sjairo.balart@metempsy.com    def __gt__(self, other): return self.filename > other.filename
22213531Sjairo.balart@metempsy.com    def __ge__(self, other): return self.filename >= other.filename
22313531Sjairo.balart@metempsy.com    def __eq__(self, other): return self.filename == other.filename
22413531Sjairo.balart@metempsy.com    def __ne__(self, other): return self.filename != other.filename
22513531Sjairo.balart@metempsy.com
22613531Sjairo.balart@metempsy.comdef blobToCpp(data, symbol, cpp_code, hpp_code=None, namespace=None):
22713756Sjairo.balart@metempsy.com    '''
22813531Sjairo.balart@metempsy.com    Convert bytes data into C++ .cpp and .hh uint8_t byte array
22913531Sjairo.balart@metempsy.com    code containing that binary data.
23013531Sjairo.balart@metempsy.com
23113531Sjairo.balart@metempsy.com    :param data: binary data to be converted to C++
23213531Sjairo.balart@metempsy.com    :param symbol: name of the symbol
23313531Sjairo.balart@metempsy.com    :param cpp_code: append the generated cpp_code to this object
23413531Sjairo.balart@metempsy.com    :param hpp_code: append the generated hpp_code to this object
23513531Sjairo.balart@metempsy.com                     If None, ignore it. Otherwise, also include it
23613756Sjairo.balart@metempsy.com                     in the .cpp file.
23713756Sjairo.balart@metempsy.com    :param namespace: namespace to put the symbol into. If None,
23813531Sjairo.balart@metempsy.com                      don't put the symbols into any namespace.
23913531Sjairo.balart@metempsy.com    '''
24013531Sjairo.balart@metempsy.com    symbol_len_declaration = 'const std::size_t {}_len'.format(symbol)
24113531Sjairo.balart@metempsy.com    symbol_declaration = 'const std::uint8_t {}[]'.format(symbol)
24213531Sjairo.balart@metempsy.com    if hpp_code is not None:
24313531Sjairo.balart@metempsy.com        cpp_code('''\
24413531Sjairo.balart@metempsy.com#include "blobs/{}.hh"
24513531Sjairo.balart@metempsy.com'''.format(symbol))
24613531Sjairo.balart@metempsy.com        hpp_code('''\
24713531Sjairo.balart@metempsy.com#include <cstddef>
24813531Sjairo.balart@metempsy.com#include <cstdint>
24913531Sjairo.balart@metempsy.com''')
25013756Sjairo.balart@metempsy.com        if namespace is not None:
25113531Sjairo.balart@metempsy.com            hpp_code('namespace {} {{'.format(namespace))
25213531Sjairo.balart@metempsy.com        hpp_code('extern ' + symbol_len_declaration + ';')
25313531Sjairo.balart@metempsy.com        hpp_code('extern ' + symbol_declaration + ';')
25413531Sjairo.balart@metempsy.com        if namespace is not None:
25513531Sjairo.balart@metempsy.com            hpp_code('}')
25613531Sjairo.balart@metempsy.com    if namespace is not None:
25713531Sjairo.balart@metempsy.com        cpp_code('namespace {} {{'.format(namespace))
25813531Sjairo.balart@metempsy.com    if hpp_code is not None:
25913531Sjairo.balart@metempsy.com        cpp_code(symbol_len_declaration + ' = {};'.format(len(data)))
26013531Sjairo.balart@metempsy.com    cpp_code(symbol_declaration + ' = {')
26113756Sjairo.balart@metempsy.com    cpp_code.indent()
26213756Sjairo.balart@metempsy.com    step = 16
26313531Sjairo.balart@metempsy.com    for i in xrange(0, len(data), step):
26413531Sjairo.balart@metempsy.com        x = array.array('B', data[i:i+step])
26513531Sjairo.balart@metempsy.com        cpp_code(''.join('%d,' % d for d in x))
26613531Sjairo.balart@metempsy.com    cpp_code.dedent()
26713531Sjairo.balart@metempsy.com    cpp_code('};')
26813531Sjairo.balart@metempsy.com    if namespace is not None:
26913531Sjairo.balart@metempsy.com        cpp_code('}')
27013531Sjairo.balart@metempsy.com
27113531Sjairo.balart@metempsy.comdef Blob(blob_path, symbol):
27213531Sjairo.balart@metempsy.com    '''
27313531Sjairo.balart@metempsy.com    Embed an arbitrary blob into the gem5 executable,
27413531Sjairo.balart@metempsy.com    and make it accessible to C++ as a byte array.
27513756Sjairo.balart@metempsy.com    '''
27613531Sjairo.balart@metempsy.com    blob_path = os.path.abspath(blob_path)
27713531Sjairo.balart@metempsy.com    blob_out_dir = os.path.join(env['BUILDDIR'], 'blobs')
27813531Sjairo.balart@metempsy.com    path_noext = joinpath(blob_out_dir, symbol)
27913531Sjairo.balart@metempsy.com    cpp_path = path_noext + '.cc'
28013531Sjairo.balart@metempsy.com    hpp_path = path_noext + '.hh'
28113531Sjairo.balart@metempsy.com    def embedBlob(target, source, env):
28213531Sjairo.balart@metempsy.com        data = file(str(source[0]), 'r').read()
28313531Sjairo.balart@metempsy.com        cpp_code = code_formatter()
28413531Sjairo.balart@metempsy.com        hpp_code = code_formatter()
28513531Sjairo.balart@metempsy.com        blobToCpp(data, symbol, cpp_code, hpp_code, namespace='Blobs')
28613756Sjairo.balart@metempsy.com        cpp_path = str(target[0])
28713756Sjairo.balart@metempsy.com        hpp_path = str(target[1])
28813531Sjairo.balart@metempsy.com        cpp_dir = os.path.split(cpp_path)[0]
28913531Sjairo.balart@metempsy.com        if not os.path.exists(cpp_dir):
29013531Sjairo.balart@metempsy.com            os.makedirs(cpp_dir)
29113531Sjairo.balart@metempsy.com        cpp_code.write(cpp_path)
29213531Sjairo.balart@metempsy.com        hpp_code.write(hpp_path)
29313531Sjairo.balart@metempsy.com    env.Command([cpp_path, hpp_path], blob_path,
29413531Sjairo.balart@metempsy.com                MakeAction(embedBlob, Transform("EMBED BLOB")))
29513531Sjairo.balart@metempsy.com    Source(cpp_path)
29613531Sjairo.balart@metempsy.com
29713531Sjairo.balart@metempsy.comdef GdbXml(xml_id, symbol):
29813531Sjairo.balart@metempsy.com    Blob(joinpath(gdb_xml_dir, xml_id), symbol)
29913756Sjairo.balart@metempsy.com
30013531Sjairo.balart@metempsy.comclass Source(SourceFile):
30113531Sjairo.balart@metempsy.com    ungrouped_tag = 'No link group'
30213531Sjairo.balart@metempsy.com    source_groups = set()
30313531Sjairo.balart@metempsy.com
30413531Sjairo.balart@metempsy.com    _current_group_tag = ungrouped_tag
30513531Sjairo.balart@metempsy.com
30613531Sjairo.balart@metempsy.com    @staticmethod
30713531Sjairo.balart@metempsy.com    def link_group_tag(group):
30813531Sjairo.balart@metempsy.com        return 'link group: %s' % group
30913756Sjairo.balart@metempsy.com
31013756Sjairo.balart@metempsy.com    @classmethod
31113531Sjairo.balart@metempsy.com    def set_group(cls, group):
31213531Sjairo.balart@metempsy.com        new_tag = Source.link_group_tag(group)
31313531Sjairo.balart@metempsy.com        Source._current_group_tag = new_tag
31413531Sjairo.balart@metempsy.com        Source.source_groups.add(group)
31513531Sjairo.balart@metempsy.com
31613531Sjairo.balart@metempsy.com    def _add_link_group_tag(self):
31713531Sjairo.balart@metempsy.com        self.tags.add(Source._current_group_tag)
31813531Sjairo.balart@metempsy.com
31913531Sjairo.balart@metempsy.com    '''Add a c/c++ source file to the build'''
32013531Sjairo.balart@metempsy.com    def __init__(self, source, tags=None, add_tags=None):
32113531Sjairo.balart@metempsy.com        '''specify the source file, and any tags'''
32213531Sjairo.balart@metempsy.com        super(Source, self).__init__(source, tags, add_tags)
32313531Sjairo.balart@metempsy.com        self._add_link_group_tag()
32413531Sjairo.balart@metempsy.com
32513531Sjairo.balart@metempsy.comclass PySource(SourceFile):
32613531Sjairo.balart@metempsy.com    '''Add a python source file to the named package'''
32713531Sjairo.balart@metempsy.com    invalid_sym_char = re.compile('[^A-z0-9_]')
32813531Sjairo.balart@metempsy.com    modules = {}
32913531Sjairo.balart@metempsy.com    tnodes = {}
33013531Sjairo.balart@metempsy.com    symnames = {}
33113531Sjairo.balart@metempsy.com
33213531Sjairo.balart@metempsy.com    def __init__(self, package, source, tags=None, add_tags=None):
33313756Sjairo.balart@metempsy.com        '''specify the python package, the source file, and any tags'''
33413531Sjairo.balart@metempsy.com        super(PySource, self).__init__(source, tags, add_tags)
33513531Sjairo.balart@metempsy.com
33613531Sjairo.balart@metempsy.com        modname,ext = self.extname
33713531Sjairo.balart@metempsy.com        assert ext == 'py'
33813531Sjairo.balart@metempsy.com
33913531Sjairo.balart@metempsy.com        if package:
34013531Sjairo.balart@metempsy.com            path = package.split('.')
34113531Sjairo.balart@metempsy.com        else:
34213531Sjairo.balart@metempsy.com            path = []
34313531Sjairo.balart@metempsy.com
34413756Sjairo.balart@metempsy.com        modpath = path[:]
34513756Sjairo.balart@metempsy.com        if modname != '__init__':
34613531Sjairo.balart@metempsy.com            modpath += [ modname ]
34713531Sjairo.balart@metempsy.com        modpath = '.'.join(modpath)
34813531Sjairo.balart@metempsy.com
34913531Sjairo.balart@metempsy.com        arcpath = path + [ self.basename ]
35013531Sjairo.balart@metempsy.com        abspath = self.snode.abspath
35113531Sjairo.balart@metempsy.com        if not exists(abspath):
35213531Sjairo.balart@metempsy.com            abspath = self.tnode.abspath
35313531Sjairo.balart@metempsy.com
35413531Sjairo.balart@metempsy.com        self.package = package
35513531Sjairo.balart@metempsy.com        self.modname = modname
35613531Sjairo.balart@metempsy.com        self.modpath = modpath
35713531Sjairo.balart@metempsy.com        self.arcname = joinpath(*arcpath)
35813531Sjairo.balart@metempsy.com        self.abspath = abspath
35913531Sjairo.balart@metempsy.com        self.compiled = File(self.filename + 'c')
36013531Sjairo.balart@metempsy.com        self.cpp = File(self.filename + '.cc')
36113531Sjairo.balart@metempsy.com        self.symname = PySource.invalid_sym_char.sub('_', modpath)
36213531Sjairo.balart@metempsy.com
36313531Sjairo.balart@metempsy.com        PySource.modules[modpath] = self
36413531Sjairo.balart@metempsy.com        PySource.tnodes[self.tnode] = self
36513531Sjairo.balart@metempsy.com        PySource.symnames[self.symname] = self
36613531Sjairo.balart@metempsy.com
36713531Sjairo.balart@metempsy.comclass SimObject(PySource):
36813531Sjairo.balart@metempsy.com    '''Add a SimObject python file as a python source object and add
36913531Sjairo.balart@metempsy.com    it to a list of sim object modules'''
37013531Sjairo.balart@metempsy.com
37113531Sjairo.balart@metempsy.com    fixed = False
37213531Sjairo.balart@metempsy.com    modnames = []
37313531Sjairo.balart@metempsy.com
37413531Sjairo.balart@metempsy.com    def __init__(self, source, tags=None, add_tags=None):
37513531Sjairo.balart@metempsy.com        '''Specify the source file and any tags (automatically in
37613756Sjairo.balart@metempsy.com        the m5.objects package)'''
37713531Sjairo.balart@metempsy.com        super(SimObject, self).__init__('m5.objects', source, tags, add_tags)
37813531Sjairo.balart@metempsy.com        if self.fixed:
37913531Sjairo.balart@metempsy.com            raise AttributeError, "Too late to call SimObject now."
38013531Sjairo.balart@metempsy.com
38113531Sjairo.balart@metempsy.com        bisect.insort_right(SimObject.modnames, self.modname)
38213531Sjairo.balart@metempsy.com
38313756Sjairo.balart@metempsy.comclass ProtoBuf(SourceFile):
38413531Sjairo.balart@metempsy.com    '''Add a Protocol Buffer to build'''
38513531Sjairo.balart@metempsy.com
38613531Sjairo.balart@metempsy.com    def __init__(self, source, tags=None, add_tags=None):
38713531Sjairo.balart@metempsy.com        '''Specify the source file, and any tags'''
38813531Sjairo.balart@metempsy.com        super(ProtoBuf, self).__init__(source, tags, add_tags)
38913531Sjairo.balart@metempsy.com
39013531Sjairo.balart@metempsy.com        # Get the file name and the extension
39113531Sjairo.balart@metempsy.com        modname,ext = self.extname
39213531Sjairo.balart@metempsy.com        assert ext == 'proto'
39313531Sjairo.balart@metempsy.com
39413531Sjairo.balart@metempsy.com        # Currently, we stick to generating the C++ headers, so we
39513531Sjairo.balart@metempsy.com        # only need to track the source and header.
39613531Sjairo.balart@metempsy.com        self.cc_file = File(modname + '.pb.cc')
39713531Sjairo.balart@metempsy.com        self.hh_file = File(modname + '.pb.h')
39813531Sjairo.balart@metempsy.com
39913756Sjairo.balart@metempsy.com
40013531Sjairo.balart@metempsy.comexectuable_classes = []
40113531Sjairo.balart@metempsy.comclass ExecutableMeta(type):
40213531Sjairo.balart@metempsy.com    '''Meta class for Executables.'''
40313531Sjairo.balart@metempsy.com    all = []
40413531Sjairo.balart@metempsy.com
40513531Sjairo.balart@metempsy.com    def __init__(cls, name, bases, d):
40613531Sjairo.balart@metempsy.com        if not d.pop('abstract', False):
40713531Sjairo.balart@metempsy.com            ExecutableMeta.all.append(cls)
40813531Sjairo.balart@metempsy.com        super(ExecutableMeta, cls).__init__(name, bases, d)
40913531Sjairo.balart@metempsy.com
41013531Sjairo.balart@metempsy.com        cls.all = []
41113531Sjairo.balart@metempsy.com
41213531Sjairo.balart@metempsy.comclass Executable(object):
41313531Sjairo.balart@metempsy.com    '''Base class for creating an executable from sources.'''
41413531Sjairo.balart@metempsy.com    __metaclass__ = ExecutableMeta
41513531Sjairo.balart@metempsy.com
41613531Sjairo.balart@metempsy.com    abstract = True
41713531Sjairo.balart@metempsy.com
41813531Sjairo.balart@metempsy.com    def __init__(self, target, *srcs_and_filts):
41913531Sjairo.balart@metempsy.com        '''Specify the target name and any sources. Sources that are
42013531Sjairo.balart@metempsy.com        not SourceFiles are evalued with Source().'''
42113531Sjairo.balart@metempsy.com        super(Executable, self).__init__()
42213531Sjairo.balart@metempsy.com        self.all.append(self)
42313531Sjairo.balart@metempsy.com        self.target = target
42413531Sjairo.balart@metempsy.com
42513531Sjairo.balart@metempsy.com        isFilter = lambda arg: isinstance(arg, SourceFilter)
42613531Sjairo.balart@metempsy.com        self.filters = filter(isFilter, srcs_and_filts)
42713531Sjairo.balart@metempsy.com        sources = filter(lambda a: not isFilter(a), srcs_and_filts)
42813531Sjairo.balart@metempsy.com
42913531Sjairo.balart@metempsy.com        srcs = SourceList()
43013531Sjairo.balart@metempsy.com        for src in sources:
43113531Sjairo.balart@metempsy.com            if not isinstance(src, SourceFile):
43213531Sjairo.balart@metempsy.com                src = Source(src, tags=[])
43313531Sjairo.balart@metempsy.com            srcs.append(src)
43413531Sjairo.balart@metempsy.com
43513531Sjairo.balart@metempsy.com        self.sources = srcs
43613531Sjairo.balart@metempsy.com        self.dir = Dir('.')
43713531Sjairo.balart@metempsy.com
43813531Sjairo.balart@metempsy.com    def path(self, env):
43913531Sjairo.balart@metempsy.com        return self.dir.File(self.target + '.' + env['EXE_SUFFIX'])
44013531Sjairo.balart@metempsy.com
44113531Sjairo.balart@metempsy.com    def srcs_to_objs(self, env, sources):
44213531Sjairo.balart@metempsy.com        return list([ s.static(env) for s in sources ])
44313531Sjairo.balart@metempsy.com
44413531Sjairo.balart@metempsy.com    @classmethod
44513531Sjairo.balart@metempsy.com    def declare_all(cls, env):
44613531Sjairo.balart@metempsy.com        return list([ instance.declare(env) for instance in cls.all ])
44713531Sjairo.balart@metempsy.com
44813531Sjairo.balart@metempsy.com    def declare(self, env, objs=None):
44913531Sjairo.balart@metempsy.com        if objs is None:
45013531Sjairo.balart@metempsy.com            objs = self.srcs_to_objs(env, self.sources)
45113531Sjairo.balart@metempsy.com
45213531Sjairo.balart@metempsy.com        if env['STRIP_EXES']:
45313531Sjairo.balart@metempsy.com            stripped = self.path(env)
45413531Sjairo.balart@metempsy.com            unstripped = env.File(str(stripped) + '.unstripped')
45513531Sjairo.balart@metempsy.com            if sys.platform == 'sunos5':
45613531Sjairo.balart@metempsy.com                cmd = 'cp $SOURCE $TARGET; strip $TARGET'
45713531Sjairo.balart@metempsy.com            else:
45813531Sjairo.balart@metempsy.com                cmd = 'strip $SOURCE -o $TARGET'
45913531Sjairo.balart@metempsy.com            env.Program(unstripped, objs)
46013531Sjairo.balart@metempsy.com            return env.Command(stripped, unstripped,
46113531Sjairo.balart@metempsy.com                               MakeAction(cmd, Transform("STRIP")))
46213531Sjairo.balart@metempsy.com        else:
46313531Sjairo.balart@metempsy.com            return env.Program(self.path(env), objs)
46413531Sjairo.balart@metempsy.com
46513531Sjairo.balart@metempsy.comclass UnitTest(Executable):
46613531Sjairo.balart@metempsy.com    '''Create a UnitTest'''
46713531Sjairo.balart@metempsy.com    def __init__(self, target, *srcs_and_filts, **kwargs):
46813531Sjairo.balart@metempsy.com        super(UnitTest, self).__init__(target, *srcs_and_filts)
46913531Sjairo.balart@metempsy.com
47014257Sgiacomo.travaglini@arm.com        self.main = kwargs.get('main', False)
47113531Sjairo.balart@metempsy.com
47213531Sjairo.balart@metempsy.com    def declare(self, env):
47313531Sjairo.balart@metempsy.com        sources = list(self.sources)
47413531Sjairo.balart@metempsy.com        for f in self.filters:
47513531Sjairo.balart@metempsy.com            sources += Source.all.apply_filter(f)
47613531Sjairo.balart@metempsy.com        objs = self.srcs_to_objs(env, sources) + env['STATIC_OBJS']
47713531Sjairo.balart@metempsy.com        if self.main:
47813531Sjairo.balart@metempsy.com            objs += env['MAIN_OBJS']
47913531Sjairo.balart@metempsy.com        return super(UnitTest, self).declare(env, objs)
48013756Sjairo.balart@metempsy.com
48114167Sgiacomo.travaglini@arm.comclass GTest(Executable):
48213531Sjairo.balart@metempsy.com    '''Create a unit test based on the google test framework.'''
48314167Sgiacomo.travaglini@arm.com    all = []
48414167Sgiacomo.travaglini@arm.com    def __init__(self, *srcs_and_filts, **kwargs):
48513531Sjairo.balart@metempsy.com        super(GTest, self).__init__(*srcs_and_filts)
48614167Sgiacomo.travaglini@arm.com
48714167Sgiacomo.travaglini@arm.com        self.skip_lib = kwargs.pop('skip_lib', False)
48813531Sjairo.balart@metempsy.com
48913531Sjairo.balart@metempsy.com    @classmethod
49014167Sgiacomo.travaglini@arm.com    def declare_all(cls, env):
49113531Sjairo.balart@metempsy.com        env = env.Clone()
49214167Sgiacomo.travaglini@arm.com        env.Append(LIBS=env['GTEST_LIBS'])
49314167Sgiacomo.travaglini@arm.com        env.Append(CPPFLAGS=env['GTEST_CPPFLAGS'])
49413531Sjairo.balart@metempsy.com        env['GTEST_LIB_SOURCES'] = Source.all.with_tag('gtest lib')
49513531Sjairo.balart@metempsy.com        env['GTEST_OUT_DIR'] = \
49613531Sjairo.balart@metempsy.com            Dir(env['BUILDDIR']).Dir('unittests.' + env['EXE_SUFFIX'])
49713531Sjairo.balart@metempsy.com        return super(GTest, cls).declare_all(env)
49813531Sjairo.balart@metempsy.com
49913531Sjairo.balart@metempsy.com    def declare(self, env):
50013531Sjairo.balart@metempsy.com        sources = list(self.sources)
50113531Sjairo.balart@metempsy.com        if not self.skip_lib:
50213531Sjairo.balart@metempsy.com            sources += env['GTEST_LIB_SOURCES']
50313531Sjairo.balart@metempsy.com        for f in self.filters:
50413531Sjairo.balart@metempsy.com            sources += Source.all.apply_filter(f)
50513531Sjairo.balart@metempsy.com        objs = self.srcs_to_objs(env, sources)
50613531Sjairo.balart@metempsy.com
50713531Sjairo.balart@metempsy.com        binary = super(GTest, self).declare(env, objs)
50813531Sjairo.balart@metempsy.com
50913531Sjairo.balart@metempsy.com        out_dir = env['GTEST_OUT_DIR']
51013531Sjairo.balart@metempsy.com        xml_file = out_dir.Dir(str(self.dir)).File(self.target + '.xml')
51113531Sjairo.balart@metempsy.com        AlwaysBuild(env.Command(xml_file, binary,
51213531Sjairo.balart@metempsy.com            "${SOURCES[0]} --gtest_output=xml:${TARGETS[0]}"))
51313531Sjairo.balart@metempsy.com
51413531Sjairo.balart@metempsy.com        return binary
51513531Sjairo.balart@metempsy.com
51613531Sjairo.balart@metempsy.comclass Gem5(Executable):
51713531Sjairo.balart@metempsy.com    '''Create a gem5 executable.'''
51813531Sjairo.balart@metempsy.com
51913531Sjairo.balart@metempsy.com    def __init__(self, target):
52013531Sjairo.balart@metempsy.com        super(Gem5, self).__init__(target)
52113531Sjairo.balart@metempsy.com
52213531Sjairo.balart@metempsy.com    def declare(self, env):
52313756Sjairo.balart@metempsy.com        objs = env['MAIN_OBJS'] + env['STATIC_OBJS']
52413531Sjairo.balart@metempsy.com        return super(Gem5, self).declare(env, objs)
52513531Sjairo.balart@metempsy.com
52613531Sjairo.balart@metempsy.com
52713531Sjairo.balart@metempsy.com# Children should have access
52813531Sjairo.balart@metempsy.comExport('Blob')
52913531Sjairo.balart@metempsy.comExport('GdbXml')
53013756Sjairo.balart@metempsy.comExport('Source')
53113531Sjairo.balart@metempsy.comExport('PySource')
53213531Sjairo.balart@metempsy.comExport('SimObject')
53313531Sjairo.balart@metempsy.comExport('ProtoBuf')
53413531Sjairo.balart@metempsy.comExport('Executable')
53513531Sjairo.balart@metempsy.comExport('UnitTest')
53613531Sjairo.balart@metempsy.comExport('GTest')
53713531Sjairo.balart@metempsy.com
53813531Sjairo.balart@metempsy.com########################################################################
53913756Sjairo.balart@metempsy.com#
54013756Sjairo.balart@metempsy.com# Debug Flags
54113531Sjairo.balart@metempsy.com#
54213531Sjairo.balart@metempsy.comdebug_flags = {}
54313531Sjairo.balart@metempsy.comdef DebugFlag(name, desc=None):
54413531Sjairo.balart@metempsy.com    if name in debug_flags:
54513531Sjairo.balart@metempsy.com        raise AttributeError, "Flag %s already specified" % name
54613531Sjairo.balart@metempsy.com    debug_flags[name] = (name, (), desc)
54713531Sjairo.balart@metempsy.com
54813531Sjairo.balart@metempsy.comdef CompoundFlag(name, flags, desc=None):
54913531Sjairo.balart@metempsy.com    if name in debug_flags:
55013531Sjairo.balart@metempsy.com        raise AttributeError, "Flag %s already specified" % name
55113531Sjairo.balart@metempsy.com
55213531Sjairo.balart@metempsy.com    compound = tuple(flags)
55313531Sjairo.balart@metempsy.com    debug_flags[name] = (name, compound, desc)
55413531Sjairo.balart@metempsy.com
55513531Sjairo.balart@metempsy.comExport('DebugFlag')
55613531Sjairo.balart@metempsy.comExport('CompoundFlag')
55713531Sjairo.balart@metempsy.com
55813531Sjairo.balart@metempsy.com########################################################################
55913531Sjairo.balart@metempsy.com#
56013531Sjairo.balart@metempsy.com# Set some compiler variables
56113531Sjairo.balart@metempsy.com#
56213531Sjairo.balart@metempsy.com
56313812Sgiacomo.travaglini@arm.com# Include file paths are rooted in this directory.  SCons will
56413812Sgiacomo.travaglini@arm.com# automatically expand '.' to refer to both the source directory and
56513812Sgiacomo.travaglini@arm.com# the corresponding build directory to pick up generated include
56613812Sgiacomo.travaglini@arm.com# files.
56713531Sjairo.balart@metempsy.comenv.Append(CPPPATH=Dir('.'))
56813756Sjairo.balart@metempsy.com
56913756Sjairo.balart@metempsy.comfor extra_dir in extras_dir_list:
57013531Sjairo.balart@metempsy.com    env.Append(CPPPATH=Dir(extra_dir))
57113531Sjairo.balart@metempsy.com
57213531Sjairo.balart@metempsy.com# Workaround for bug in SCons version > 0.97d20071212
57313531Sjairo.balart@metempsy.com# Scons bug id: 2006 gem5 Bug id: 308
57413531Sjairo.balart@metempsy.comfor root, dirs, files in os.walk(base_dir, topdown=True):
57513531Sjairo.balart@metempsy.com    Dir(root[len(base_dir) + 1:])
57613531Sjairo.balart@metempsy.com
57713531Sjairo.balart@metempsy.com########################################################################
57813531Sjairo.balart@metempsy.com#
57913531Sjairo.balart@metempsy.com# Walk the tree and execute all SConscripts in subdirectories
58013531Sjairo.balart@metempsy.com#
58113531Sjairo.balart@metempsy.com
58213531Sjairo.balart@metempsy.comhere = Dir('.').srcnode().abspath
58313531Sjairo.balart@metempsy.comfor root, dirs, files in os.walk(base_dir, topdown=True):
58413531Sjairo.balart@metempsy.com    if root == here:
58513531Sjairo.balart@metempsy.com        # we don't want to recurse back into this SConscript
58613531Sjairo.balart@metempsy.com        continue
58713531Sjairo.balart@metempsy.com
58813531Sjairo.balart@metempsy.com    if 'SConscript' in files:
58913756Sjairo.balart@metempsy.com        build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:])
59013531Sjairo.balart@metempsy.com        Source.set_group(build_dir)
59113531Sjairo.balart@metempsy.com        SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir)
59213531Sjairo.balart@metempsy.com
59313531Sjairo.balart@metempsy.comfor extra_dir in extras_dir_list:
59413531Sjairo.balart@metempsy.com    prefix_len = len(dirname(extra_dir)) + 1
59513531Sjairo.balart@metempsy.com
59613531Sjairo.balart@metempsy.com    # Also add the corresponding build directory to pick up generated
59713756Sjairo.balart@metempsy.com    # include files.
59813756Sjairo.balart@metempsy.com    env.Append(CPPPATH=Dir(joinpath(env['BUILDDIR'], extra_dir[prefix_len:])))
59913531Sjairo.balart@metempsy.com
60013531Sjairo.balart@metempsy.com    for root, dirs, files in os.walk(extra_dir, topdown=True):
60113531Sjairo.balart@metempsy.com        # if build lives in the extras directory, don't walk down it
60213531Sjairo.balart@metempsy.com        if 'build' in dirs:
60313531Sjairo.balart@metempsy.com            dirs.remove('build')
60413531Sjairo.balart@metempsy.com
60513531Sjairo.balart@metempsy.com        if 'SConscript' in files:
60613531Sjairo.balart@metempsy.com            build_dir = joinpath(env['BUILDDIR'], root[prefix_len:])
60713531Sjairo.balart@metempsy.com            SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir)
60813531Sjairo.balart@metempsy.com
60913531Sjairo.balart@metempsy.comfor opt in export_vars:
61013531Sjairo.balart@metempsy.com    env.ConfigFile(opt)
61113531Sjairo.balart@metempsy.com
61213531Sjairo.balart@metempsy.comdef makeTheISA(source, target, env):
61313531Sjairo.balart@metempsy.com    isas = [ src.get_contents() for src in source ]
61413531Sjairo.balart@metempsy.com    target_isa = env['TARGET_ISA']
61513531Sjairo.balart@metempsy.com    def define(isa):
61614231Sgiacomo.travaglini@arm.com        return isa.upper() + '_ISA'
61713531Sjairo.balart@metempsy.com
61813531Sjairo.balart@metempsy.com    def namespace(isa):
61913756Sjairo.balart@metempsy.com        return isa[0].upper() + isa[1:].lower() + 'ISA'
62013531Sjairo.balart@metempsy.com
62113531Sjairo.balart@metempsy.com
62213531Sjairo.balart@metempsy.com    code = code_formatter()
62313531Sjairo.balart@metempsy.com    code('''\
62413531Sjairo.balart@metempsy.com#ifndef __CONFIG_THE_ISA_HH__
62513531Sjairo.balart@metempsy.com#define __CONFIG_THE_ISA_HH__
62613531Sjairo.balart@metempsy.com
62713756Sjairo.balart@metempsy.com''')
62813756Sjairo.balart@metempsy.com
62913531Sjairo.balart@metempsy.com    # create defines for the preprocessing and compile-time determination
63013531Sjairo.balart@metempsy.com    for i,isa in enumerate(isas):
63113531Sjairo.balart@metempsy.com        code('#define $0 $1', define(isa), i + 1)
63213531Sjairo.balart@metempsy.com    code()
63313531Sjairo.balart@metempsy.com
63413531Sjairo.balart@metempsy.com    # create an enum for any run-time determination of the ISA, we
63513531Sjairo.balart@metempsy.com    # reuse the same name as the namespaces
63613531Sjairo.balart@metempsy.com    code('enum class Arch {')
63713531Sjairo.balart@metempsy.com    for i,isa in enumerate(isas):
63813531Sjairo.balart@metempsy.com        if i + 1 == len(isas):
63913531Sjairo.balart@metempsy.com            code('  $0 = $1', namespace(isa), define(isa))
64013531Sjairo.balart@metempsy.com        else:
64114231Sgiacomo.travaglini@arm.com            code('  $0 = $1,', namespace(isa), define(isa))
64213531Sjairo.balart@metempsy.com    code('};')
64313531Sjairo.balart@metempsy.com
64413531Sjairo.balart@metempsy.com    code('''
64514231Sgiacomo.travaglini@arm.com
64613531Sjairo.balart@metempsy.com#define THE_ISA ${{define(target_isa)}}
64713756Sjairo.balart@metempsy.com#define TheISA ${{namespace(target_isa)}}
64813531Sjairo.balart@metempsy.com#define THE_ISA_STR "${{target_isa}}"
64913531Sjairo.balart@metempsy.com
65013531Sjairo.balart@metempsy.com#endif // __CONFIG_THE_ISA_HH__''')
65113531Sjairo.balart@metempsy.com
65213531Sjairo.balart@metempsy.com    code.write(str(target[0]))
65313531Sjairo.balart@metempsy.com
65413531Sjairo.balart@metempsy.comenv.Command('config/the_isa.hh', map(Value, all_isa_list),
65513531Sjairo.balart@metempsy.com            MakeAction(makeTheISA, Transform("CFG ISA", 0)))
65613756Sjairo.balart@metempsy.com
65713756Sjairo.balart@metempsy.comdef makeTheGPUISA(source, target, env):
65813531Sjairo.balart@metempsy.com    isas = [ src.get_contents() for src in source ]
65913531Sjairo.balart@metempsy.com    target_gpu_isa = env['TARGET_GPU_ISA']
66013531Sjairo.balart@metempsy.com    def define(isa):
66113531Sjairo.balart@metempsy.com        return isa.upper() + '_ISA'
66213531Sjairo.balart@metempsy.com
66313531Sjairo.balart@metempsy.com    def namespace(isa):
66413531Sjairo.balart@metempsy.com        return isa[0].upper() + isa[1:].lower() + 'ISA'
66513531Sjairo.balart@metempsy.com
66613531Sjairo.balart@metempsy.com
66713531Sjairo.balart@metempsy.com    code = code_formatter()
66813531Sjairo.balart@metempsy.com    code('''\
66913531Sjairo.balart@metempsy.com#ifndef __CONFIG_THE_GPU_ISA_HH__
67013531Sjairo.balart@metempsy.com#define __CONFIG_THE_GPU_ISA_HH__
67113531Sjairo.balart@metempsy.com
67213531Sjairo.balart@metempsy.com''')
67313531Sjairo.balart@metempsy.com
67413531Sjairo.balart@metempsy.com    # create defines for the preprocessing and compile-time determination
67513531Sjairo.balart@metempsy.com    for i,isa in enumerate(isas):
67613531Sjairo.balart@metempsy.com        code('#define $0 $1', define(isa), i + 1)
67713531Sjairo.balart@metempsy.com    code()
67813531Sjairo.balart@metempsy.com
67913531Sjairo.balart@metempsy.com    # create an enum for any run-time determination of the ISA, we
68013756Sjairo.balart@metempsy.com    # reuse the same name as the namespaces
68113756Sjairo.balart@metempsy.com    code('enum class GPUArch {')
68213531Sjairo.balart@metempsy.com    for i,isa in enumerate(isas):
68313531Sjairo.balart@metempsy.com        if i + 1 == len(isas):
68413531Sjairo.balart@metempsy.com            code('  $0 = $1', namespace(isa), define(isa))
68513531Sjairo.balart@metempsy.com        else:
68613531Sjairo.balart@metempsy.com            code('  $0 = $1,', namespace(isa), define(isa))
68713531Sjairo.balart@metempsy.com    code('};')
68813531Sjairo.balart@metempsy.com
68913531Sjairo.balart@metempsy.com    code('''
69013531Sjairo.balart@metempsy.com
69113531Sjairo.balart@metempsy.com#define THE_GPU_ISA ${{define(target_gpu_isa)}}
69213531Sjairo.balart@metempsy.com#define TheGpuISA ${{namespace(target_gpu_isa)}}
69313531Sjairo.balart@metempsy.com#define THE_GPU_ISA_STR "${{target_gpu_isa}}"
69413531Sjairo.balart@metempsy.com
69513531Sjairo.balart@metempsy.com#endif // __CONFIG_THE_GPU_ISA_HH__''')
69613531Sjairo.balart@metempsy.com
69713531Sjairo.balart@metempsy.com    code.write(str(target[0]))
69813531Sjairo.balart@metempsy.com
69913531Sjairo.balart@metempsy.comenv.Command('config/the_gpu_isa.hh', map(Value, all_gpu_isa_list),
70013756Sjairo.balart@metempsy.com            MakeAction(makeTheGPUISA, Transform("CFG ISA", 0)))
70113531Sjairo.balart@metempsy.com
70213531Sjairo.balart@metempsy.com########################################################################
70313531Sjairo.balart@metempsy.com#
70413531Sjairo.balart@metempsy.com# Prevent any SimObjects from being added after this point, they
70513531Sjairo.balart@metempsy.com# should all have been added in the SConscripts above
70613531Sjairo.balart@metempsy.com#
70713531Sjairo.balart@metempsy.comSimObject.fixed = True
70813531Sjairo.balart@metempsy.com
70913531Sjairo.balart@metempsy.comclass DictImporter(object):
71013531Sjairo.balart@metempsy.com    '''This importer takes a dictionary of arbitrary module names that
71113531Sjairo.balart@metempsy.com    map to arbitrary filenames.'''
71213531Sjairo.balart@metempsy.com    def __init__(self, modules):
71313531Sjairo.balart@metempsy.com        self.modules = modules
71413531Sjairo.balart@metempsy.com        self.installed = set()
71513531Sjairo.balart@metempsy.com
71613531Sjairo.balart@metempsy.com    def __del__(self):
71713531Sjairo.balart@metempsy.com        self.unload()
71813531Sjairo.balart@metempsy.com
71913531Sjairo.balart@metempsy.com    def unload(self):
72013531Sjairo.balart@metempsy.com        import sys
72113531Sjairo.balart@metempsy.com        for module in self.installed:
72213531Sjairo.balart@metempsy.com            del sys.modules[module]
72313531Sjairo.balart@metempsy.com        self.installed = set()
72413531Sjairo.balart@metempsy.com
72513531Sjairo.balart@metempsy.com    def find_module(self, fullname, path):
72613531Sjairo.balart@metempsy.com        if fullname == 'm5.defines':
72713531Sjairo.balart@metempsy.com            return self
72813531Sjairo.balart@metempsy.com
72913531Sjairo.balart@metempsy.com        if fullname == 'm5.objects':
73013531Sjairo.balart@metempsy.com            return self
73113531Sjairo.balart@metempsy.com
73213531Sjairo.balart@metempsy.com        if fullname.startswith('_m5'):
73313756Sjairo.balart@metempsy.com            return None
73413531Sjairo.balart@metempsy.com
73513756Sjairo.balart@metempsy.com        source = self.modules.get(fullname, None)
73613756Sjairo.balart@metempsy.com        if source is not None and fullname.startswith('m5.objects'):
73713756Sjairo.balart@metempsy.com            return self
73813756Sjairo.balart@metempsy.com
73913756Sjairo.balart@metempsy.com        return None
74013531Sjairo.balart@metempsy.com
74113531Sjairo.balart@metempsy.com    def load_module(self, fullname):
74213531Sjairo.balart@metempsy.com        mod = imp.new_module(fullname)
74313531Sjairo.balart@metempsy.com        sys.modules[fullname] = mod
74413531Sjairo.balart@metempsy.com        self.installed.add(fullname)
74513531Sjairo.balart@metempsy.com
74613531Sjairo.balart@metempsy.com        mod.__loader__ = self
74713756Sjairo.balart@metempsy.com        if fullname == 'm5.objects':
74813531Sjairo.balart@metempsy.com            mod.__path__ = fullname.split('.')
74913531Sjairo.balart@metempsy.com            return mod
75013531Sjairo.balart@metempsy.com
75113531Sjairo.balart@metempsy.com        if fullname == 'm5.defines':
75213531Sjairo.balart@metempsy.com            mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env)
75313531Sjairo.balart@metempsy.com            return mod
75413531Sjairo.balart@metempsy.com
75513531Sjairo.balart@metempsy.com        source = self.modules[fullname]
75613531Sjairo.balart@metempsy.com        if source.modname == '__init__':
75713531Sjairo.balart@metempsy.com            mod.__path__ = source.modpath
75813531Sjairo.balart@metempsy.com        mod.__file__ = source.abspath
75913531Sjairo.balart@metempsy.com
76013531Sjairo.balart@metempsy.com        exec file(source.abspath, 'r') in mod.__dict__
76113531Sjairo.balart@metempsy.com
76213531Sjairo.balart@metempsy.com        return mod
76313531Sjairo.balart@metempsy.com
76413531Sjairo.balart@metempsy.comimport m5.SimObject
76513531Sjairo.balart@metempsy.comimport m5.params
76613531Sjairo.balart@metempsy.comfrom m5.util import code_formatter
76713531Sjairo.balart@metempsy.com
76813531Sjairo.balart@metempsy.comm5.SimObject.clear()
76913531Sjairo.balart@metempsy.comm5.params.clear()
77013531Sjairo.balart@metempsy.com
77113531Sjairo.balart@metempsy.com# install the python importer so we can grab stuff from the source
77213756Sjairo.balart@metempsy.com# tree itself.  We can't have SimObjects added after this point or
77314230Sgiacomo.travaglini@arm.com# else we won't know about them for the rest of the stuff.
77413531Sjairo.balart@metempsy.comimporter = DictImporter(PySource.modules)
77513531Sjairo.balart@metempsy.comsys.meta_path[0:0] = [ importer ]
77613531Sjairo.balart@metempsy.com
77713531Sjairo.balart@metempsy.com# import all sim objects so we can populate the all_objects list
77813531Sjairo.balart@metempsy.com# make sure that we're working with a list, then let's sort it
77913531Sjairo.balart@metempsy.comfor modname in SimObject.modnames:
78013756Sjairo.balart@metempsy.com    exec('from m5.objects import %s' % modname)
78113531Sjairo.balart@metempsy.com
78213531Sjairo.balart@metempsy.com# we need to unload all of the currently imported modules so that they
78313531Sjairo.balart@metempsy.com# will be re-imported the next time the sconscript is run
78413531Sjairo.balart@metempsy.comimporter.unload()
78513531Sjairo.balart@metempsy.comsys.meta_path.remove(importer)
78613531Sjairo.balart@metempsy.com
78713531Sjairo.balart@metempsy.comsim_objects = m5.SimObject.allClasses
78813531Sjairo.balart@metempsy.comall_enums = m5.params.allEnums
78913531Sjairo.balart@metempsy.com
79013531Sjairo.balart@metempsy.comfor name,obj in sorted(sim_objects.iteritems()):
79113531Sjairo.balart@metempsy.com    for param in obj._params.local.values():
79213531Sjairo.balart@metempsy.com        # load the ptype attribute now because it depends on the
79313531Sjairo.balart@metempsy.com        # current version of SimObject.allClasses, but when scons
79413756Sjairo.balart@metempsy.com        # actually uses the value, all versions of
79513531Sjairo.balart@metempsy.com        # SimObject.allClasses will have been loaded
79613531Sjairo.balart@metempsy.com        param.ptype
79713531Sjairo.balart@metempsy.com
79813531Sjairo.balart@metempsy.com########################################################################
79913531Sjairo.balart@metempsy.com#
80013531Sjairo.balart@metempsy.com# calculate extra dependencies
80113531Sjairo.balart@metempsy.com#
80213531Sjairo.balart@metempsy.commodule_depends = ["m5", "m5.SimObject", "m5.params"]
80313531Sjairo.balart@metempsy.comdepends = [ PySource.modules[dep].snode for dep in module_depends ]
80413531Sjairo.balart@metempsy.comdepends.sort(key = lambda x: x.name)
80513531Sjairo.balart@metempsy.com
80613531Sjairo.balart@metempsy.com########################################################################
80713531Sjairo.balart@metempsy.com#
80813531Sjairo.balart@metempsy.com# Commands for the basic automatically generated python files
80913531Sjairo.balart@metempsy.com#
81013531Sjairo.balart@metempsy.com
81113531Sjairo.balart@metempsy.com# Generate Python file containing a dict specifying the current
81213531Sjairo.balart@metempsy.com# buildEnv flags.
81313531Sjairo.balart@metempsy.comdef makeDefinesPyFile(target, source, env):
81413531Sjairo.balart@metempsy.com    build_env = source[0].get_contents()
81513531Sjairo.balart@metempsy.com
81613531Sjairo.balart@metempsy.com    code = code_formatter()
81713531Sjairo.balart@metempsy.com    code("""
81813531Sjairo.balart@metempsy.comimport _m5.core
81913531Sjairo.balart@metempsy.comimport m5.util
82013531Sjairo.balart@metempsy.com
82113531Sjairo.balart@metempsy.combuildEnv = m5.util.SmartDict($build_env)
82213531Sjairo.balart@metempsy.com
82313531Sjairo.balart@metempsy.comcompileDate = _m5.core.compileDate
82413531Sjairo.balart@metempsy.com_globals = globals()
82513531Sjairo.balart@metempsy.comfor key,val in _m5.core.__dict__.iteritems():
82613531Sjairo.balart@metempsy.com    if key.startswith('flag_'):
82713531Sjairo.balart@metempsy.com        flag = key[5:]
82813531Sjairo.balart@metempsy.com        _globals[flag] = val
82913531Sjairo.balart@metempsy.comdel _globals
83013531Sjairo.balart@metempsy.com""")
83113531Sjairo.balart@metempsy.com    code.write(target[0].abspath)
83213531Sjairo.balart@metempsy.com
83313531Sjairo.balart@metempsy.comdefines_info = Value(build_env)
83413531Sjairo.balart@metempsy.com# Generate a file with all of the compile options in it
83513531Sjairo.balart@metempsy.comenv.Command('python/m5/defines.py', defines_info,
83613531Sjairo.balart@metempsy.com            MakeAction(makeDefinesPyFile, Transform("DEFINES", 0)))
83713531Sjairo.balart@metempsy.comPySource('m5', 'python/m5/defines.py')
83813531Sjairo.balart@metempsy.com
83913531Sjairo.balart@metempsy.com# Generate python file containing info about the M5 source code
84013531Sjairo.balart@metempsy.comdef makeInfoPyFile(target, source, env):
84113531Sjairo.balart@metempsy.com    code = code_formatter()
84213531Sjairo.balart@metempsy.com    for src in source:
84313531Sjairo.balart@metempsy.com        data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
84413531Sjairo.balart@metempsy.com        code('$src = ${{repr(data)}}')
84513531Sjairo.balart@metempsy.com    code.write(str(target[0]))
84613531Sjairo.balart@metempsy.com
84713531Sjairo.balart@metempsy.com# Generate a file that wraps the basic top level files
84813531Sjairo.balart@metempsy.comenv.Command('python/m5/info.py',
84913531Sjairo.balart@metempsy.com            [ '#/COPYING', '#/LICENSE', '#/README', ],
85013531Sjairo.balart@metempsy.com            MakeAction(makeInfoPyFile, Transform("INFO")))
85113531Sjairo.balart@metempsy.comPySource('m5', 'python/m5/info.py')
85213531Sjairo.balart@metempsy.com
85313531Sjairo.balart@metempsy.com########################################################################
85413531Sjairo.balart@metempsy.com#
85513531Sjairo.balart@metempsy.com# Create all of the SimObject param headers and enum headers
85613531Sjairo.balart@metempsy.com#
85713531Sjairo.balart@metempsy.com
85813531Sjairo.balart@metempsy.comdef createSimObjectParamStruct(target, source, env):
85913531Sjairo.balart@metempsy.com    assert len(target) == 1 and len(source) == 1
86013531Sjairo.balart@metempsy.com
86113531Sjairo.balart@metempsy.com    name = source[0].get_text_contents()
86213531Sjairo.balart@metempsy.com    obj = sim_objects[name]
86313531Sjairo.balart@metempsy.com
86413531Sjairo.balart@metempsy.com    code = code_formatter()
86513531Sjairo.balart@metempsy.com    obj.cxx_param_decl(code)
86613531Sjairo.balart@metempsy.com    code.write(target[0].abspath)
86713531Sjairo.balart@metempsy.com
86813531Sjairo.balart@metempsy.comdef createSimObjectCxxConfig(is_header):
86913531Sjairo.balart@metempsy.com    def body(target, source, env):
87013531Sjairo.balart@metempsy.com        assert len(target) == 1 and len(source) == 1
87113531Sjairo.balart@metempsy.com
87213531Sjairo.balart@metempsy.com        name = str(source[0].get_contents())
87313531Sjairo.balart@metempsy.com        obj = sim_objects[name]
87413531Sjairo.balart@metempsy.com
87513531Sjairo.balart@metempsy.com        code = code_formatter()
87613531Sjairo.balart@metempsy.com        obj.cxx_config_param_file(code, is_header)
87713531Sjairo.balart@metempsy.com        code.write(target[0].abspath)
87813531Sjairo.balart@metempsy.com    return body
87913531Sjairo.balart@metempsy.com
88013531Sjairo.balart@metempsy.comdef createEnumStrings(target, source, env):
88113531Sjairo.balart@metempsy.com    assert len(target) == 1 and len(source) == 2
88213531Sjairo.balart@metempsy.com
88313531Sjairo.balart@metempsy.com    name = source[0].get_text_contents()
88413531Sjairo.balart@metempsy.com    use_python = source[1].read()
88513531Sjairo.balart@metempsy.com    obj = all_enums[name]
88613531Sjairo.balart@metempsy.com
88713531Sjairo.balart@metempsy.com    code = code_formatter()
88813531Sjairo.balart@metempsy.com    obj.cxx_def(code)
88913531Sjairo.balart@metempsy.com    if use_python:
89013531Sjairo.balart@metempsy.com        obj.pybind_def(code)
89113531Sjairo.balart@metempsy.com    code.write(target[0].abspath)
89213531Sjairo.balart@metempsy.com
89313531Sjairo.balart@metempsy.comdef createEnumDecls(target, source, env):
89413531Sjairo.balart@metempsy.com    assert len(target) == 1 and len(source) == 1
89513531Sjairo.balart@metempsy.com
89613531Sjairo.balart@metempsy.com    name = source[0].get_text_contents()
89713531Sjairo.balart@metempsy.com    obj = all_enums[name]
89813531Sjairo.balart@metempsy.com
89913531Sjairo.balart@metempsy.com    code = code_formatter()
90013531Sjairo.balart@metempsy.com    obj.cxx_decl(code)
90113531Sjairo.balart@metempsy.com    code.write(target[0].abspath)
90213531Sjairo.balart@metempsy.com
90313531Sjairo.balart@metempsy.comdef createSimObjectPyBindWrapper(target, source, env):
90413531Sjairo.balart@metempsy.com    name = source[0].get_text_contents()
90513531Sjairo.balart@metempsy.com    obj = sim_objects[name]
90613531Sjairo.balart@metempsy.com
90713531Sjairo.balart@metempsy.com    code = code_formatter()
90813531Sjairo.balart@metempsy.com    obj.pybind_decl(code)
90913531Sjairo.balart@metempsy.com    code.write(target[0].abspath)
91014232Sgiacomo.travaglini@arm.com
91114232Sgiacomo.travaglini@arm.com# Generate all of the SimObject param C++ struct header files
91213531Sjairo.balart@metempsy.comparams_hh_files = []
91313531Sjairo.balart@metempsy.comfor name,simobj in sorted(sim_objects.iteritems()):
91414251Sgiacomo.travaglini@arm.com    py_source = PySource.modules[simobj.__module__]
91514251Sgiacomo.travaglini@arm.com    extra_deps = [ py_source.tnode ]
91614251Sgiacomo.travaglini@arm.com
91714251Sgiacomo.travaglini@arm.com    hh_file = File('params/%s.hh' % name)
91814253Sgiacomo.travaglini@arm.com    params_hh_files.append(hh_file)
91914253Sgiacomo.travaglini@arm.com    env.Command(hh_file, Value(name),
92014253Sgiacomo.travaglini@arm.com                MakeAction(createSimObjectParamStruct, Transform("SO PARAM")))
92114253Sgiacomo.travaglini@arm.com    env.Depends(hh_file, depends + extra_deps)
92214253Sgiacomo.travaglini@arm.com
92314253Sgiacomo.travaglini@arm.com# C++ parameter description files
92414253Sgiacomo.travaglini@arm.comif GetOption('with_cxx_config'):
92514253Sgiacomo.travaglini@arm.com    for name,simobj in sorted(sim_objects.iteritems()):
92614253Sgiacomo.travaglini@arm.com        py_source = PySource.modules[simobj.__module__]
92714253Sgiacomo.travaglini@arm.com        extra_deps = [ py_source.tnode ]
92814253Sgiacomo.travaglini@arm.com
92914253Sgiacomo.travaglini@arm.com        cxx_config_hh_file = File('cxx_config/%s.hh' % name)
93014253Sgiacomo.travaglini@arm.com        cxx_config_cc_file = File('cxx_config/%s.cc' % name)
93114253Sgiacomo.travaglini@arm.com        env.Command(cxx_config_hh_file, Value(name),
93214253Sgiacomo.travaglini@arm.com                    MakeAction(createSimObjectCxxConfig(True),
93314253Sgiacomo.travaglini@arm.com                    Transform("CXXCPRHH")))
93414253Sgiacomo.travaglini@arm.com        env.Command(cxx_config_cc_file, Value(name),
93514253Sgiacomo.travaglini@arm.com                    MakeAction(createSimObjectCxxConfig(False),
93614253Sgiacomo.travaglini@arm.com                    Transform("CXXCPRCC")))
93714253Sgiacomo.travaglini@arm.com        env.Depends(cxx_config_hh_file, depends + extra_deps +
93814253Sgiacomo.travaglini@arm.com                    [File('params/%s.hh' % name), File('sim/cxx_config.hh')])
93914253Sgiacomo.travaglini@arm.com        env.Depends(cxx_config_cc_file, depends + extra_deps +
94014253Sgiacomo.travaglini@arm.com                    [cxx_config_hh_file])
94114253Sgiacomo.travaglini@arm.com        Source(cxx_config_cc_file)
94214253Sgiacomo.travaglini@arm.com
94314253Sgiacomo.travaglini@arm.com    cxx_config_init_cc_file = File('cxx_config/init.cc')
94414253Sgiacomo.travaglini@arm.com
94514253Sgiacomo.travaglini@arm.com    def createCxxConfigInitCC(target, source, env):
94614253Sgiacomo.travaglini@arm.com        assert len(target) == 1 and len(source) == 1
94714253Sgiacomo.travaglini@arm.com
94814253Sgiacomo.travaglini@arm.com        code = code_formatter()
94914253Sgiacomo.travaglini@arm.com
95014253Sgiacomo.travaglini@arm.com        for name,simobj in sorted(sim_objects.iteritems()):
95114253Sgiacomo.travaglini@arm.com            if not hasattr(simobj, 'abstract') or not simobj.abstract:
95214253Sgiacomo.travaglini@arm.com                code('#include "cxx_config/${name}.hh"')
95314253Sgiacomo.travaglini@arm.com        code()
95414253Sgiacomo.travaglini@arm.com        code('void cxxConfigInit()')
95514253Sgiacomo.travaglini@arm.com        code('{')
95614253Sgiacomo.travaglini@arm.com        code.indent()
95714253Sgiacomo.travaglini@arm.com        for name,simobj in sorted(sim_objects.iteritems()):
95814253Sgiacomo.travaglini@arm.com            not_abstract = not hasattr(simobj, 'abstract') or \
95914253Sgiacomo.travaglini@arm.com                not simobj.abstract
96014253Sgiacomo.travaglini@arm.com            if not_abstract and 'type' in simobj.__dict__:
96114253Sgiacomo.travaglini@arm.com                code('cxx_config_directory["${name}"] = '
96214253Sgiacomo.travaglini@arm.com                     '${name}CxxConfigParams::makeDirectoryEntry();')
96314253Sgiacomo.travaglini@arm.com        code.dedent()
96414253Sgiacomo.travaglini@arm.com        code('}')
96514253Sgiacomo.travaglini@arm.com        code.write(target[0].abspath)
96614253Sgiacomo.travaglini@arm.com
96714253Sgiacomo.travaglini@arm.com    py_source = PySource.modules[simobj.__module__]
96814253Sgiacomo.travaglini@arm.com    extra_deps = [ py_source.tnode ]
96914253Sgiacomo.travaglini@arm.com    env.Command(cxx_config_init_cc_file, Value(name),
97014253Sgiacomo.travaglini@arm.com        MakeAction(createCxxConfigInitCC, Transform("CXXCINIT")))
97114253Sgiacomo.travaglini@arm.com    cxx_param_hh_files = ["cxx_config/%s.hh" % simobj
97214253Sgiacomo.travaglini@arm.com        for name,simobj in sorted(sim_objects.iteritems())
97314253Sgiacomo.travaglini@arm.com        if not hasattr(simobj, 'abstract') or not simobj.abstract]
97414253Sgiacomo.travaglini@arm.com    Depends(cxx_config_init_cc_file, cxx_param_hh_files +
97514253Sgiacomo.travaglini@arm.com            [File('sim/cxx_config.hh')])
97614253Sgiacomo.travaglini@arm.com    Source(cxx_config_init_cc_file)
97714253Sgiacomo.travaglini@arm.com
97814253Sgiacomo.travaglini@arm.com# Generate all enum header files
97914253Sgiacomo.travaglini@arm.comfor name,enum in sorted(all_enums.iteritems()):
98014253Sgiacomo.travaglini@arm.com    py_source = PySource.modules[enum.__module__]
98114253Sgiacomo.travaglini@arm.com    extra_deps = [ py_source.tnode ]
98214253Sgiacomo.travaglini@arm.com
98314253Sgiacomo.travaglini@arm.com    cc_file = File('enums/%s.cc' % name)
98414253Sgiacomo.travaglini@arm.com    env.Command(cc_file, [Value(name), Value(env['USE_PYTHON'])],
98514253Sgiacomo.travaglini@arm.com                MakeAction(createEnumStrings, Transform("ENUM STR")))
98614253Sgiacomo.travaglini@arm.com    env.Depends(cc_file, depends + extra_deps)
98714253Sgiacomo.travaglini@arm.com    Source(cc_file)
98813531Sjairo.balart@metempsy.com
98913531Sjairo.balart@metempsy.com    hh_file = File('enums/%s.hh' % name)
99013531Sjairo.balart@metempsy.com    env.Command(hh_file, Value(name),
99113531Sjairo.balart@metempsy.com                MakeAction(createEnumDecls, Transform("ENUMDECL")))
99213531Sjairo.balart@metempsy.com    env.Depends(hh_file, depends + extra_deps)
99313531Sjairo.balart@metempsy.com
99413531Sjairo.balart@metempsy.com# Generate SimObject Python bindings wrapper files
99513531Sjairo.balart@metempsy.comif env['USE_PYTHON']:
99613531Sjairo.balart@metempsy.com    for name,simobj in sorted(sim_objects.iteritems()):
99713531Sjairo.balart@metempsy.com        py_source = PySource.modules[simobj.__module__]
99813531Sjairo.balart@metempsy.com        extra_deps = [ py_source.tnode ]
99913531Sjairo.balart@metempsy.com        cc_file = File('python/_m5/param_%s.cc' % name)
100013531Sjairo.balart@metempsy.com        env.Command(cc_file, Value(name),
100113531Sjairo.balart@metempsy.com                    MakeAction(createSimObjectPyBindWrapper,
100214231Sgiacomo.travaglini@arm.com                               Transform("SO PyBind")))
100313531Sjairo.balart@metempsy.com        env.Depends(cc_file, depends + extra_deps)
100413531Sjairo.balart@metempsy.com        Source(cc_file)
100513531Sjairo.balart@metempsy.com
100613756Sjairo.balart@metempsy.com# Build all protocol buffers if we have got protoc and protobuf available
100713531Sjairo.balart@metempsy.comif env['HAVE_PROTOBUF']:
100813531Sjairo.balart@metempsy.com    for proto in ProtoBuf.all:
100913531Sjairo.balart@metempsy.com        # Use both the source and header as the target, and the .proto
101013531Sjairo.balart@metempsy.com        # file as the source. When executing the protoc compiler, also
101114231Sgiacomo.travaglini@arm.com        # specify the proto_path to avoid having the generated files
101214231Sgiacomo.travaglini@arm.com        # include the path.
101314231Sgiacomo.travaglini@arm.com        env.Command([proto.cc_file, proto.hh_file], proto.tnode,
101413531Sjairo.balart@metempsy.com                    MakeAction('$PROTOC --cpp_out ${TARGET.dir} '
101513531Sjairo.balart@metempsy.com                               '--proto_path ${SOURCE.dir} $SOURCE',
101614231Sgiacomo.travaglini@arm.com                               Transform("PROTOC")))
101714231Sgiacomo.travaglini@arm.com
101813531Sjairo.balart@metempsy.com        # Add the C++ source file
101914231Sgiacomo.travaglini@arm.com        Source(proto.cc_file, tags=proto.tags)
102014231Sgiacomo.travaglini@arm.comelif ProtoBuf.all:
102113531Sjairo.balart@metempsy.com    print('Got protobuf to build, but lacks support!')
102214231Sgiacomo.travaglini@arm.com    Exit(1)
102314231Sgiacomo.travaglini@arm.com
102414231Sgiacomo.travaglini@arm.com#
102514231Sgiacomo.travaglini@arm.com# Handle debug flags
102614231Sgiacomo.travaglini@arm.com#
102714231Sgiacomo.travaglini@arm.comdef makeDebugFlagCC(target, source, env):
102814231Sgiacomo.travaglini@arm.com    assert(len(target) == 1 and len(source) == 1)
102914231Sgiacomo.travaglini@arm.com
103014231Sgiacomo.travaglini@arm.com    code = code_formatter()
103114231Sgiacomo.travaglini@arm.com
103214231Sgiacomo.travaglini@arm.com    # delay definition of CompoundFlags until after all the definition
103314231Sgiacomo.travaglini@arm.com    # of all constituent SimpleFlags
103414231Sgiacomo.travaglini@arm.com    comp_code = code_formatter()
103514231Sgiacomo.travaglini@arm.com
103614231Sgiacomo.travaglini@arm.com    # file header
103714231Sgiacomo.travaglini@arm.com    code('''
103814231Sgiacomo.travaglini@arm.com/*
103914231Sgiacomo.travaglini@arm.com * DO NOT EDIT THIS FILE! Automatically generated by SCons.
104014231Sgiacomo.travaglini@arm.com */
104114231Sgiacomo.travaglini@arm.com
104214231Sgiacomo.travaglini@arm.com#include "base/debug.hh"
104314231Sgiacomo.travaglini@arm.com
104414231Sgiacomo.travaglini@arm.comnamespace Debug {
104514231Sgiacomo.travaglini@arm.com
104614231Sgiacomo.travaglini@arm.com''')
104714231Sgiacomo.travaglini@arm.com
104814231Sgiacomo.travaglini@arm.com    for name, flag in sorted(source[0].read().iteritems()):
104914231Sgiacomo.travaglini@arm.com        n, compound, desc = flag
105013531Sjairo.balart@metempsy.com        assert n == name
105113531Sjairo.balart@metempsy.com
105213531Sjairo.balart@metempsy.com        if not compound:
105313531Sjairo.balart@metempsy.com            code('SimpleFlag $name("$name", "$desc");')
105414231Sgiacomo.travaglini@arm.com        else:
105513531Sjairo.balart@metempsy.com            comp_code('CompoundFlag $name("$name", "$desc",')
105614231Sgiacomo.travaglini@arm.com            comp_code.indent()
105714231Sgiacomo.travaglini@arm.com            last = len(compound) - 1
105814259Sgiacomo.travaglini@arm.com            for i,flag in enumerate(compound):
105913531Sjairo.balart@metempsy.com                if i != last:
106013531Sjairo.balart@metempsy.com                    comp_code('&$flag,')
106113531Sjairo.balart@metempsy.com                else:
106213531Sjairo.balart@metempsy.com                    comp_code('&$flag);')
106313531Sjairo.balart@metempsy.com            comp_code.dedent()
106413531Sjairo.balart@metempsy.com
106513531Sjairo.balart@metempsy.com    code.append(comp_code)
106613756Sjairo.balart@metempsy.com    code()
106713531Sjairo.balart@metempsy.com    code('} // namespace Debug')
106813531Sjairo.balart@metempsy.com
106913531Sjairo.balart@metempsy.com    code.write(str(target[0]))
107013531Sjairo.balart@metempsy.com
107113756Sjairo.balart@metempsy.comdef makeDebugFlagHH(target, source, env):
107213531Sjairo.balart@metempsy.com    assert(len(target) == 1 and len(source) == 1)
107314231Sgiacomo.travaglini@arm.com
107414231Sgiacomo.travaglini@arm.com    val = eval(source[0].get_contents())
107513531Sjairo.balart@metempsy.com    name, compound, desc = val
107614231Sgiacomo.travaglini@arm.com
107714231Sgiacomo.travaglini@arm.com    code = code_formatter()
107813531Sjairo.balart@metempsy.com
107913531Sjairo.balart@metempsy.com    # file header boilerplate
108013756Sjairo.balart@metempsy.com    code('''\
108113756Sjairo.balart@metempsy.com/*
108214231Sgiacomo.travaglini@arm.com * DO NOT EDIT THIS FILE! Automatically generated by SCons.
108313531Sjairo.balart@metempsy.com */
108413531Sjairo.balart@metempsy.com
108513531Sjairo.balart@metempsy.com#ifndef __DEBUG_${name}_HH__
108613531Sjairo.balart@metempsy.com#define __DEBUG_${name}_HH__
108713531Sjairo.balart@metempsy.com
108813531Sjairo.balart@metempsy.comnamespace Debug {
108913531Sjairo.balart@metempsy.com''')
109014231Sgiacomo.travaglini@arm.com
109113531Sjairo.balart@metempsy.com    if compound:
109214231Sgiacomo.travaglini@arm.com        code('class CompoundFlag;')
109313531Sjairo.balart@metempsy.com    code('class SimpleFlag;')
109413531Sjairo.balart@metempsy.com
109513531Sjairo.balart@metempsy.com    if compound:
109613531Sjairo.balart@metempsy.com        code('extern CompoundFlag $name;')
109713756Sjairo.balart@metempsy.com        for flag in compound:
109813531Sjairo.balart@metempsy.com            code('extern SimpleFlag $flag;')
109913531Sjairo.balart@metempsy.com    else:
110013531Sjairo.balart@metempsy.com        code('extern SimpleFlag $name;')
110113531Sjairo.balart@metempsy.com
110213531Sjairo.balart@metempsy.com    code('''
110313531Sjairo.balart@metempsy.com}
110413531Sjairo.balart@metempsy.com
110513531Sjairo.balart@metempsy.com#endif // __DEBUG_${name}_HH__
110613531Sjairo.balart@metempsy.com''')
110713531Sjairo.balart@metempsy.com
110813531Sjairo.balart@metempsy.com    code.write(str(target[0]))
110913531Sjairo.balart@metempsy.com
111013531Sjairo.balart@metempsy.comfor name,flag in sorted(debug_flags.iteritems()):
111113531Sjairo.balart@metempsy.com    n, compound, desc = flag
111213531Sjairo.balart@metempsy.com    assert n == name
111313531Sjairo.balart@metempsy.com
111413531Sjairo.balart@metempsy.com    hh_file = 'debug/%s.hh' % name
111513531Sjairo.balart@metempsy.com    env.Command(hh_file, Value(flag),
111613756Sjairo.balart@metempsy.com                MakeAction(makeDebugFlagHH, Transform("TRACING", 0)))
111713531Sjairo.balart@metempsy.com
111813531Sjairo.balart@metempsy.comenv.Command('debug/flags.cc', Value(debug_flags),
111913531Sjairo.balart@metempsy.com            MakeAction(makeDebugFlagCC, Transform("TRACING", 0)))
112013531Sjairo.balart@metempsy.comSource('debug/flags.cc')
112113531Sjairo.balart@metempsy.com
112213531Sjairo.balart@metempsy.com# version tags
112313531Sjairo.balart@metempsy.comtags = \
112413531Sjairo.balart@metempsy.comenv.Command('sim/tags.cc', None,
112513531Sjairo.balart@metempsy.com            MakeAction('util/cpt_upgrader.py --get-cc-file > $TARGET',
112613531Sjairo.balart@metempsy.com                       Transform("VER TAGS")))
112713531Sjairo.balart@metempsy.comenv.AlwaysBuild(tags)
112813531Sjairo.balart@metempsy.com
112913531Sjairo.balart@metempsy.com# Embed python files.  All .py files that have been indicated by a
113013531Sjairo.balart@metempsy.com# PySource() call in a SConscript need to be embedded into the M5
113113531Sjairo.balart@metempsy.com# library.  To do that, we compile the file to byte code, marshal the
113213531Sjairo.balart@metempsy.com# byte code, compress it, and then generate a c++ file that
113313531Sjairo.balart@metempsy.com# inserts the result into an array.
113413531Sjairo.balart@metempsy.comdef embedPyFile(target, source, env):
113513531Sjairo.balart@metempsy.com    def c_str(string):
113613531Sjairo.balart@metempsy.com        if string is None:
113713531Sjairo.balart@metempsy.com            return "0"
113813531Sjairo.balart@metempsy.com        return '"%s"' % string
113913531Sjairo.balart@metempsy.com
114013531Sjairo.balart@metempsy.com    '''Action function to compile a .py into a code object, marshal
114113531Sjairo.balart@metempsy.com    it, compress it, and stick it into an asm file so the code appears
114213531Sjairo.balart@metempsy.com    as just bytes with a label in the data section'''
114313531Sjairo.balart@metempsy.com
114413531Sjairo.balart@metempsy.com    src = file(str(source[0]), 'r').read()
114513531Sjairo.balart@metempsy.com
114613531Sjairo.balart@metempsy.com    pysource = PySource.tnodes[source[0]]
114713531Sjairo.balart@metempsy.com    compiled = compile(src, pysource.abspath, 'exec')
114813531Sjairo.balart@metempsy.com    marshalled = marshal.dumps(compiled)
114913531Sjairo.balart@metempsy.com    compressed = zlib.compress(marshalled)
115013531Sjairo.balart@metempsy.com    data = compressed
115113531Sjairo.balart@metempsy.com    sym = pysource.symname
115213531Sjairo.balart@metempsy.com
115313531Sjairo.balart@metempsy.com    code = code_formatter()
115413531Sjairo.balart@metempsy.com    code('''\
115513531Sjairo.balart@metempsy.com#include "sim/init.hh"
115613531Sjairo.balart@metempsy.com
115713531Sjairo.balart@metempsy.comnamespace {
115813531Sjairo.balart@metempsy.com
115913531Sjairo.balart@metempsy.com''')
116013531Sjairo.balart@metempsy.com    blobToCpp(data, 'data_' + sym, code)
116113531Sjairo.balart@metempsy.com    code('''\
116213531Sjairo.balart@metempsy.com
116313531Sjairo.balart@metempsy.com
116413531Sjairo.balart@metempsy.comEmbeddedPython embedded_${sym}(
116513531Sjairo.balart@metempsy.com    ${{c_str(pysource.arcname)}},
116613531Sjairo.balart@metempsy.com    ${{c_str(pysource.abspath)}},
116713531Sjairo.balart@metempsy.com    ${{c_str(pysource.modpath)}},
116813531Sjairo.balart@metempsy.com    data_${sym},
116913531Sjairo.balart@metempsy.com    ${{len(data)}},
117013531Sjairo.balart@metempsy.com    ${{len(marshalled)}});
117113531Sjairo.balart@metempsy.com
117213531Sjairo.balart@metempsy.com} // anonymous namespace
117313531Sjairo.balart@metempsy.com''')
117413531Sjairo.balart@metempsy.com    code.write(str(target[0]))
117513531Sjairo.balart@metempsy.com
117613531Sjairo.balart@metempsy.comfor source in PySource.all:
117713531Sjairo.balart@metempsy.com    env.Command(source.cpp, source.tnode,
117813531Sjairo.balart@metempsy.com                MakeAction(embedPyFile, Transform("EMBED PY")))
117913531Sjairo.balart@metempsy.com    Source(source.cpp, tags=source.tags, add_tags='python')
118013531Sjairo.balart@metempsy.com
118113531Sjairo.balart@metempsy.com########################################################################
118213531Sjairo.balart@metempsy.com#
118313531Sjairo.balart@metempsy.com# Define binaries.  Each different build type (debug, opt, etc.) gets
118413531Sjairo.balart@metempsy.com# a slightly different build environment.
118513531Sjairo.balart@metempsy.com#
118613531Sjairo.balart@metempsy.com
118713531Sjairo.balart@metempsy.com# List of constructed environments to pass back to SConstruct
118813531Sjairo.balart@metempsy.comdate_source = Source('base/date.cc', tags=[])
118913531Sjairo.balart@metempsy.com
119013531Sjairo.balart@metempsy.comgem5_binary = Gem5('gem5')
119113531Sjairo.balart@metempsy.com
1192# Function to create a new build environment as clone of current
1193# environment 'env' with modified object suffix and optional stripped
1194# binary.  Additional keyword arguments are appended to corresponding
1195# build environment vars.
1196def makeEnv(env, label, objsfx, strip=False, disable_partial=False, **kwargs):
1197    # SCons doesn't know to append a library suffix when there is a '.' in the
1198    # name.  Use '_' instead.
1199    libname = 'gem5_' + label
1200    secondary_exename = 'm5.' + label
1201
1202    new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's')
1203    new_env.Label = label
1204    new_env.Append(**kwargs)
1205
1206    lib_sources = Source.all.with_tag('gem5 lib')
1207
1208    # Without Python, leave out all Python content from the library
1209    # builds.  The option doesn't affect gem5 built as a program
1210    if GetOption('without_python'):
1211        lib_sources = lib_sources.without_tag('python')
1212
1213    static_objs = []
1214    shared_objs = []
1215
1216    for s in lib_sources.with_tag(Source.ungrouped_tag):
1217        static_objs.append(s.static(new_env))
1218        shared_objs.append(s.shared(new_env))
1219
1220    for group in Source.source_groups:
1221        srcs = lib_sources.with_tag(Source.link_group_tag(group))
1222        if not srcs:
1223            continue
1224
1225        group_static = [ s.static(new_env) for s in srcs ]
1226        group_shared = [ s.shared(new_env) for s in srcs ]
1227
1228        # If partial linking is disabled, add these sources to the build
1229        # directly, and short circuit this loop.
1230        if disable_partial:
1231            static_objs.extend(group_static)
1232            shared_objs.extend(group_shared)
1233            continue
1234
1235        # Set up the static partially linked objects.
1236        file_name = new_env.subst("${OBJPREFIX}lib${OBJSUFFIX}.partial")
1237        target = File(joinpath(group, file_name))
1238        partial = env.PartialStatic(target=target, source=group_static)
1239        static_objs.extend(partial)
1240
1241        # Set up the shared partially linked objects.
1242        file_name = new_env.subst("${SHOBJPREFIX}lib${SHOBJSUFFIX}.partial")
1243        target = File(joinpath(group, file_name))
1244        partial = env.PartialShared(target=target, source=group_shared)
1245        shared_objs.extend(partial)
1246
1247    static_date = date_source.static(new_env)
1248    new_env.Depends(static_date, static_objs)
1249    static_objs.extend(static_date)
1250
1251    shared_date = date_source.shared(new_env)
1252    new_env.Depends(shared_date, shared_objs)
1253    shared_objs.extend(shared_date)
1254
1255    main_objs = [ s.static(new_env) for s in Source.all.with_tag('main') ]
1256
1257    # First make a library of everything but main() so other programs can
1258    # link against m5.
1259    static_lib = new_env.StaticLibrary(libname, static_objs)
1260    shared_lib = new_env.SharedLibrary(libname, shared_objs)
1261
1262    # Keep track of the object files generated so far so Executables can
1263    # include them.
1264    new_env['STATIC_OBJS'] = static_objs
1265    new_env['SHARED_OBJS'] = shared_objs
1266    new_env['MAIN_OBJS'] = main_objs
1267
1268    new_env['STATIC_LIB'] = static_lib
1269    new_env['SHARED_LIB'] = shared_lib
1270
1271    # Record some settings for building Executables.
1272    new_env['EXE_SUFFIX'] = label
1273    new_env['STRIP_EXES'] = strip
1274
1275    for cls in ExecutableMeta.all:
1276        cls.declare_all(new_env)
1277
1278    new_env.M5Binary = File(gem5_binary.path(new_env))
1279
1280    new_env.Command(secondary_exename, new_env.M5Binary,
1281            MakeAction('ln $SOURCE $TARGET', Transform("HARDLINK")))
1282
1283    # Set up regression tests.
1284    SConscript(os.path.join(env.root.abspath, 'tests', 'SConscript'),
1285               variant_dir=Dir('tests').Dir(new_env.Label),
1286               exports={ 'env' : new_env }, duplicate=False)
1287
1288# Start out with the compiler flags common to all compilers,
1289# i.e. they all use -g for opt and -g -pg for prof
1290ccflags = {'debug' : [], 'opt' : ['-g'], 'fast' : [], 'prof' : ['-g', '-pg'],
1291           'perf' : ['-g']}
1292
1293# Start out with the linker flags common to all linkers, i.e. -pg for
1294# prof, and -lprofiler for perf. The -lprofile flag is surrounded by
1295# no-as-needed and as-needed as the binutils linker is too clever and
1296# simply doesn't link to the library otherwise.
1297ldflags = {'debug' : [], 'opt' : [], 'fast' : [], 'prof' : ['-pg'],
1298           'perf' : ['-Wl,--no-as-needed', '-lprofiler', '-Wl,--as-needed']}
1299
1300# For Link Time Optimization, the optimisation flags used to compile
1301# individual files are decoupled from those used at link time
1302# (i.e. you can compile with -O3 and perform LTO with -O0), so we need
1303# to also update the linker flags based on the target.
1304if env['GCC']:
1305    if sys.platform == 'sunos5':
1306        ccflags['debug'] += ['-gstabs+']
1307    else:
1308        ccflags['debug'] += ['-ggdb3']
1309    ldflags['debug'] += ['-O0']
1310    # opt, fast, prof and perf all share the same cc flags, also add
1311    # the optimization to the ldflags as LTO defers the optimization
1312    # to link time
1313    for target in ['opt', 'fast', 'prof', 'perf']:
1314        ccflags[target] += ['-O3']
1315        ldflags[target] += ['-O3']
1316
1317    ccflags['fast'] += env['LTO_CCFLAGS']
1318    ldflags['fast'] += env['LTO_LDFLAGS']
1319elif env['CLANG']:
1320    ccflags['debug'] += ['-g', '-O0']
1321    # opt, fast, prof and perf all share the same cc flags
1322    for target in ['opt', 'fast', 'prof', 'perf']:
1323        ccflags[target] += ['-O3']
1324else:
1325    print('Unknown compiler, please fix compiler options')
1326    Exit(1)
1327
1328
1329# To speed things up, we only instantiate the build environments we
1330# need.  We try to identify the needed environment for each target; if
1331# we can't, we fall back on instantiating all the environments just to
1332# be safe.
1333target_types = ['debug', 'opt', 'fast', 'prof', 'perf']
1334obj2target = {'do': 'debug', 'o': 'opt', 'fo': 'fast', 'po': 'prof',
1335              'gpo' : 'perf'}
1336
1337def identifyTarget(t):
1338    ext = t.split('.')[-1]
1339    if ext in target_types:
1340        return ext
1341    if ext in obj2target:
1342        return obj2target[ext]
1343    match = re.search(r'/tests/([^/]+)/', t)
1344    if match and match.group(1) in target_types:
1345        return match.group(1)
1346    return 'all'
1347
1348needed_envs = [identifyTarget(target) for target in BUILD_TARGETS]
1349if 'all' in needed_envs:
1350    needed_envs += target_types
1351
1352disable_partial = False
1353if env['PLATFORM'] == 'darwin':
1354    # Up until Apple LLVM version 10.0.0 (clang-1000.11.45.5), partial
1355    # linked objects do not expose symbols that are marked with the
1356    # hidden visibility and consequently building gem5 on Mac OS
1357    # fails. As a workaround, we disable partial linking, however, we
1358    # may want to revisit in the future.
1359    disable_partial = True
1360
1361# Debug binary
1362if 'debug' in needed_envs:
1363    makeEnv(env, 'debug', '.do',
1364            CCFLAGS = Split(ccflags['debug']),
1365            CPPDEFINES = ['DEBUG', 'TRACING_ON=1'],
1366            LINKFLAGS = Split(ldflags['debug']),
1367            disable_partial=disable_partial)
1368
1369# Optimized binary
1370if 'opt' in needed_envs:
1371    makeEnv(env, 'opt', '.o',
1372            CCFLAGS = Split(ccflags['opt']),
1373            CPPDEFINES = ['TRACING_ON=1'],
1374            LINKFLAGS = Split(ldflags['opt']),
1375            disable_partial=disable_partial)
1376
1377# "Fast" binary
1378if 'fast' in needed_envs:
1379    disable_partial = disable_partial and \
1380            env.get('BROKEN_INCREMENTAL_LTO', False) and \
1381            GetOption('force_lto')
1382    makeEnv(env, 'fast', '.fo', strip = True,
1383            CCFLAGS = Split(ccflags['fast']),
1384            CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
1385            LINKFLAGS = Split(ldflags['fast']),
1386            disable_partial=disable_partial)
1387
1388# Profiled binary using gprof
1389if 'prof' in needed_envs:
1390    makeEnv(env, 'prof', '.po',
1391            CCFLAGS = Split(ccflags['prof']),
1392            CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
1393            LINKFLAGS = Split(ldflags['prof']),
1394            disable_partial=disable_partial)
1395
1396# Profiled binary using google-pprof
1397if 'perf' in needed_envs:
1398    makeEnv(env, 'perf', '.gpo',
1399            CCFLAGS = Split(ccflags['perf']),
1400            CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
1401            LINKFLAGS = Split(ldflags['perf']),
1402            disable_partial=disable_partial)
1403