SConscript revision 13656
15703SN/A# Copyright 2018 Google, Inc.
25703SN/A#
35703SN/A# Redistribution and use in source and binary forms, with or without
48825Snilay@cs.wisc.edu# modification, are permitted provided that the following conditions are
57935SN/A# met: redistributions of source code must retain the above copyright
67935SN/A# notice, this list of conditions and the following disclaimer;
77935SN/A# redistributions in binary form must reproduce the above copyright
85703SN/A# notice, this list of conditions and the following disclaimer in the
95703SN/A# documentation and/or other materials provided with the distribution;
105703SN/A# neither the name of the copyright holders nor the names of its
115703SN/A# contributors may be used to endorse or promote products derived from
125703SN/A# this software without specific prior written permission.
135703SN/A#
148835SAli.Saidi@ARM.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
155703SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
168835SAli.Saidi@ARM.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
177670SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
185703SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
198464SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
208721SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
218835SAli.Saidi@ARM.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
225703SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
235703SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
245703SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
255703SN/A#
267935SN/A# Authors: Gabe Black
277935SN/A
287935SN/Afrom __future__ import print_function
297935SN/A
307935SN/AImport('*')
317935SN/A
327935SN/Aif env['USE_SYSTEMC']:
338983Snate@binkert.org
345703SN/A    from gem5_scons import Transform
355703SN/A
365703SN/A    import os.path
375703SN/A    import json
385703SN/A
398721SN/A    src = str(Dir('.').srcdir)
408721SN/A
418721SN/A    class SystemCTest(object):
425703SN/A        def __init__(self, dirname, name):
438983Snate@binkert.org            self.name = name
448983Snate@binkert.org            self.reldir = os.path.relpath(dirname, src)
455703SN/A            self.target = os.path.join(self.reldir, name)
465703SN/A            self.sources = []
475703SN/A            self.deps = []
485703SN/A
495703SN/A            self.compile_only = False
505703SN/A
515703SN/A        def add_source(self, source):
525703SN/A            self.sources.append(os.path.join(self.reldir, source))
538241SN/A
548241SN/A        def add_sources(self, sources):
555703SN/A            for source in sources:
565703SN/A                self.sources.append(os.path.join(self.reldir, '..', source))
575703SN/A
585703SN/A        def properties(self):
595703SN/A            return {
605703SN/A                'name' : self.name,
615876SN/A                'path' : self.reldir,
625703SN/A                'compile_only' : self.compile_only,
635703SN/A                'deps' : self.deps
645703SN/A            }
655703SN/A
665703SN/A    test_dir = Dir('.')
675703SN/A    class SystemCTestBin(Executable):
685703SN/A        def __init__(self, test):
695703SN/A            super(SystemCTestBin, self).__init__(test.target, *test.sources)
705703SN/A            self.reldir = test.reldir
715703SN/A            self.test_deps = test.deps
725703SN/A
735703SN/A        @classmethod
745703SN/A        def declare_all(cls, env):
755703SN/A            env = env.Clone()
765703SN/A
775703SN/A            # Turn off extra warnings and Werror for the tests.
785703SN/A            to_remove = ['-Wall', '-Wundef', '-Wextra', '-Werror']
795703SN/A            env['CCFLAGS'] = \
805703SN/A                filter(lambda f: f not in to_remove, env['CCFLAGS'])
815703SN/A
825703SN/A            env.Append(CPPPATH=test_dir.Dir('include'))
835703SN/A
845703SN/A            shared_lib_path = env['SHARED_LIB'][0].abspath
855703SN/A            sl_dir, sl_base = os.path.split(shared_lib_path)
865703SN/A            env.Append(LIBPATH=[sl_dir], LIBS=[sl_base])
875703SN/A
885703SN/A            super(SystemCTestBin, cls).declare_all(env)
895703SN/A
905703SN/A        def declare(self, env):
915703SN/A            env = env.Clone()
925703SN/A            sources = list(self.sources)
935703SN/A            for f in self.filters:
945703SN/A                sources += Source.all.apply_filter(f)
955703SN/A            objs = self.srcs_to_objs(env, sources)
965703SN/A            objs = objs + env['MAIN_OBJS']
975703SN/A            relpath = os.path.relpath(
985703SN/A                    env['SHARED_LIB'][0].dir.abspath,
995703SN/A                    self.path(env).dir.abspath)
1005703SN/A            env.Append(LINKFLAGS=Split('-z origin'))
1015703SN/A            env.Append(RPATH=[
1025703SN/A                    env.Literal(os.path.join('\\$$ORIGIN', relpath))])
1035703SN/A            test_bin = super(SystemCTestBin, self).declare(env, objs)
1045703SN/A            test_dir = self.dir.Dir(self.reldir)
1055703SN/A            for dep in self.test_deps:
1065703SN/A                env.Depends(test_bin, test_dir.File(dep))
1078825Snilay@cs.wisc.edu            return test_bin
1085703SN/A
1095703SN/A    tests = []
1105703SN/A    def new_test(dirname, name):
1115703SN/A        test = SystemCTest(dirname, name)
1125703SN/A        tests.append(test)
1135703SN/A        return test
1145703SN/A
1155703SN/A
1165703SN/A    def scan_dir_for_tests(subdir):
1175703SN/A        def visitor(arg, dirname, names):
1185703SN/A            # If there's a 'DONTRUN' file in this directory, skip it and any
1195703SN/A            # child directories.
1205703SN/A            if 'DONTRUN' in names:
1215703SN/A                del names[:]
1225703SN/A                return
1235703SN/A
1245703SN/A            endswith = lambda sfx: filter(lambda n: n.endswith(sfx), names)
1255703SN/A
1265703SN/A            cpps = endswith('.cpp')
1275703SN/A            if not cpps:
1285703SN/A                return
1295703SN/A
1305703SN/A            def get_entries(fname):
1315703SN/A                with open(os.path.join(dirname, fname)) as content:
1325703SN/A                    lines = content.readlines
1338521SN/A                    # Get rid of leading and trailing whitespace.
1345703SN/A                    lines = map(lambda x: x.strip(), content.readlines())
1355703SN/A                    # Get rid of blank lines.
1365703SN/A                    lines = filter(lambda x: x, lines)
1375703SN/A                    return lines
1385703SN/A
1398825Snilay@cs.wisc.edu            # If there's only one source file, then that files name is the test
1405703SN/A            # name, and it's the source for that test.
1415703SN/A            if len(cpps) == 1:
1425703SN/A                cpp = cpps[0]
1435703SN/A
1445703SN/A                test = new_test(dirname, os.path.splitext(cpp)[0])
1458983Snate@binkert.org                test.add_source(cpp)
1465703SN/A
1475703SN/A            # Otherwise, expect there to be a file that ends in .f. That files
1486123SN/A            # name is the test name, and it will list the source files with
1495703SN/A            # one preceeding path component.
1508135SN/A            else:
1515703SN/A                fs = endswith('.f')
1525703SN/A                if len(fs) != 1:
1535703SN/A                    print("In %s, expected 1 *.f file, but found %d.",
1545876SN/A                          dirname, len(fs))
1558835SAli.Saidi@ARM.com                    for f in fs:
1565703SN/A                        print(os.path.join(dirname, f))
1575703SN/A                    return
1585703SN/A                f = fs[0]
1595703SN/A
1608835SAli.Saidi@ARM.com                test = new_test(dirname, os.path.splitext(f)[0])
1615703SN/A                # Add all the sources to this test.
1625703SN/A                test.add_sources(get_entries(f))
1635703SN/A
1645703SN/A            if 'COMPILE' in names:
1655703SN/A                test.compile_only = True
1668983Snate@binkert.org
1675703SN/A            if 'DEPS' in names:
1685703SN/A                test.deps = get_entries('DEPS')
1696024SN/A
1705703SN/A        subdir_src = Dir('.').srcdir.Dir(subdir)
1715703SN/A        os.path.walk(str(subdir_src), visitor, None)
1725703SN/A
1735703SN/A    scan_dir_for_tests('systemc')
1747761SN/A    scan_dir_for_tests('tlm')
1757761SN/A
1765703SN/A
1775703SN/A    def build_tests_json(target, source, env):
1785703SN/A        data = { test.target : test.properties() for test in tests }
1795703SN/A        with open(str(target[0]), "w") as tests_json:
1805703SN/A            json.dump(data, tests_json)
1815703SN/A
1825703SN/A    AlwaysBuild(env.Command(File('tests.json'), None,
1835703SN/A                MakeAction(build_tests_json, Transform("TESTJSON"))))
1845703SN/A
1855703SN/A
1865703SN/A    for test in tests:
1875703SN/A        SystemCTestBin(test)
1885703SN/A