SConscript revision 13098
1# Copyright 2018 Google, Inc. 2# 3# Redistribution and use in source and binary forms, with or without 4# modification, are permitted provided that the following conditions are 5# met: redistributions of source code must retain the above copyright 6# notice, this list of conditions and the following disclaimer; 7# redistributions in binary form must reproduce the above copyright 8# notice, this list of conditions and the following disclaimer in the 9# documentation and/or other materials provided with the distribution; 10# neither the name of the copyright holders nor the names of its 11# contributors may be used to endorse or promote products derived from 12# this software without specific prior written permission. 13# 14# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25# 26# Authors: Gabe Black 27 28from __future__ import print_function 29 30Import('*') 31 32if env['USE_SYSTEMC']: 33 34 from gem5_scons import Transform 35 36 import os.path 37 import json 38 39 src = str(Dir('.').srcdir) 40 41 class SystemCTest(object): 42 def __init__(self, dirname, name): 43 self.name = name 44 self.reldir = os.path.relpath(dirname, src) 45 self.target = os.path.join(self.reldir, name) 46 self.sources = [] 47 48 self.compile_only = False 49 50 def add_source(self, source): 51 self.sources.append(os.path.join(self.reldir, source)) 52 53 def add_sources(self, sources): 54 for source in sources: 55 self.sources.append(os.path.join(self.reldir, '..', source)) 56 57 def properties(self): 58 return { 59 'name' : self.name, 60 'path' : self.reldir, 61 'compile_only' : self.compile_only 62 } 63 64 ext_dir = Dir('..').Dir('ext') 65 test_dir = Dir('.') 66 class SystemCTestBin(Executable): 67 def __init__(self, test): 68 super(SystemCTestBin, self).__init__(test.target, *test.sources) 69 70 @classmethod 71 def declare_all(cls, env): 72 env = env.Clone() 73 74 # Turn off extra warnings and Werror for the tests. 75 to_remove = ['-Wall', '-Wundef', '-Wextra', '-Werror'] 76 env['CCFLAGS'] = \ 77 filter(lambda f: f not in to_remove, env['CCFLAGS']) 78 79 env.Append(CPPPATH=test_dir.Dir('include')) 80 env.Append(CPPPATH=ext_dir) 81 82 shared_lib_path = env['SHARED_LIB'][0].abspath 83 sl_dir, sl_base = os.path.split(shared_lib_path) 84 env.Append(LIBPATH=[sl_dir], LIBS=[sl_base]) 85 86 super(SystemCTestBin, cls).declare_all(env) 87 88 def declare(self, env): 89 env = env.Clone() 90 sources = list(self.sources) 91 for f in self.filters: 92 sources = Source.all.apply_filter(f) 93 objs = self.srcs_to_objs(env, sources) 94 objs = objs + env['MAIN_OBJS'] 95 relpath = os.path.relpath( 96 env['SHARED_LIB'][0].dir.abspath, 97 self.path(env).dir.abspath) 98 env.Append(LINKFLAGS=Split('-z origin')) 99 env.Append(RPATH=env.Literal(os.path.join('\\$$ORIGIN', relpath))) 100 return super(SystemCTestBin, self).declare(env, objs) 101 102 tests = [] 103 def new_test(dirname, name): 104 test = SystemCTest(dirname, name) 105 tests.append(test) 106 return test 107 108 109 def scan_dir_for_tests(subdir): 110 def visitor(arg, dirname, names): 111 # If there's a 'DONTRUN' file in this directory, skip it and any 112 # child directories. 113 if 'DONTRUN' in names: 114 del names[:] 115 return 116 117 endswith = lambda sfx: filter(lambda n: n.endswith(sfx), names) 118 119 cpps = endswith('.cpp') 120 if not cpps: 121 return 122 123 # If there's only one source file, then that files name is the test 124 # name, and it's the source for that test. 125 if len(cpps) == 1: 126 cpp = cpps[0] 127 128 test = new_test(dirname, os.path.splitext(cpp)[0]) 129 test.add_source(cpp) 130 131 # Otherwise, expect there to be a file that ends in .f. That files 132 # name is the test name, and it will list the source files with 133 # one preceeding path component. 134 else: 135 fs = endswith('.f') 136 if len(fs) != 1: 137 print("In %s, expected 1 *.f file, but found %d.", 138 dirname, len(fs)) 139 for f in fs: 140 print(os.path.join(dirname, f)) 141 return 142 f = fs[0] 143 144 test = new_test(dirname, os.path.splitext(f)[0]) 145 with open(os.path.join(dirname, f)) as content: 146 lines = content.readlines 147 # Get rid of leading and trailing whitespace. 148 lines = map(lambda x: x.strip(), content.readlines()) 149 # Get rid of blank lines. 150 lines = filter(lambda x: x, lines) 151 # Add all the sources to this test. 152 test.add_sources(lines) 153 154 if 'COMPILE' in names: 155 test.compile_only = True 156 157 subdir_src = Dir('.').srcdir.Dir(subdir) 158 os.path.walk(str(subdir_src), visitor, None) 159 160 scan_dir_for_tests('systemc') 161 162 163 def build_tests_json(target, source, env): 164 data = { test.target : test.properties() for test in tests } 165 with open(str(target[0]), "w") as tests_json: 166 json.dump(data, tests_json) 167 168 AlwaysBuild(env.Command(File('tests.json'), None, 169 MakeAction(build_tests_json, Transform("TESTJSON")))) 170 171 172 for test in tests: 173 SystemCTestBin(test) 174