SConscript revision 11330
16019Shines@cs.fsu.edu# -*- mode:python -*- 26019Shines@cs.fsu.edu 313759Sgiacomo.gabrielli@arm.com# Copyright (c) 2004-2005 The Regents of The University of Michigan 47100Sgblack@eecs.umich.edu# All rights reserved. 57100Sgblack@eecs.umich.edu# 67100Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 77100Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are 87100Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright 97100Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 107100Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 117100Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 127100Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution; 137100Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its 147100Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from 156019Shines@cs.fsu.edu# this software without specific prior written permission. 166019Shines@cs.fsu.edu# 176019Shines@cs.fsu.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 186019Shines@cs.fsu.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 196019Shines@cs.fsu.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 206019Shines@cs.fsu.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 216019Shines@cs.fsu.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 226019Shines@cs.fsu.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 236019Shines@cs.fsu.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 246019Shines@cs.fsu.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 256019Shines@cs.fsu.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 266019Shines@cs.fsu.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 276019Shines@cs.fsu.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286019Shines@cs.fsu.edu# 296019Shines@cs.fsu.edu# Authors: Nathan Binkert 306019Shines@cs.fsu.edu 316019Shines@cs.fsu.eduimport array 326019Shines@cs.fsu.eduimport bisect 336019Shines@cs.fsu.eduimport imp 346019Shines@cs.fsu.eduimport marshal 356019Shines@cs.fsu.eduimport os 366019Shines@cs.fsu.eduimport re 376019Shines@cs.fsu.eduimport sys 386019Shines@cs.fsu.eduimport zlib 396019Shines@cs.fsu.edu 406019Shines@cs.fsu.edufrom os.path import basename, dirname, exists, isdir, isfile, join as joinpath 416019Shines@cs.fsu.edu 426757SAli.Saidi@ARM.comimport SCons 436019Shines@cs.fsu.edu 446019Shines@cs.fsu.edu# This file defines how to build a particular configuration of gem5 456019Shines@cs.fsu.edu# based on variable settings in the 'env' build environment. 466019Shines@cs.fsu.edu 476019Shines@cs.fsu.eduImport('*') 4811320Ssteve.reinhardt@amd.com 496019Shines@cs.fsu.edu# Children need to see the environment 509022Sgblack@eecs.umich.eduExport('env') 516019Shines@cs.fsu.edu 5212640Sgiacomo.travaglini@arm.combuild_env = [(opt, env[opt]) for opt in export_vars] 5310037SARM gem5 Developers 5410037SARM gem5 Developersfrom m5.util import code_formatter, compareVersions 557170Sgblack@eecs.umich.edu 566253Sgblack@eecs.umich.edu######################################################################## 5710037SARM gem5 Developers# Code for adding source files of various types 587202Sgblack@eecs.umich.edu# 5910037SARM gem5 Developers# When specifying a source file of some type, a set of guards can be 606253Sgblack@eecs.umich.edu# specified for that file. When get() is used to find the files, if 6110611SAndreas.Sandberg@ARM.com# get specifies a set of filters, only files that match those filters 626253Sgblack@eecs.umich.edu# will be accepted (unspecified filters on files are assumed to be 6313759Sgiacomo.gabrielli@arm.com# false). Current filters are: 647396Sgblack@eecs.umich.edu# main -- specifies the gem5 main() function 6510037SARM gem5 Developers# skip_lib -- do not put this file into the gem5 library 6613168Smatt.horsnell@arm.com# skip_no_python -- do not put this file into a no_python library 678745Sgblack@eecs.umich.edu# as it embeds compiled Python 687405SAli.Saidi@ARM.com# <unittest> -- unit tests use filters based on the unit test name 6910461SAndreas.Sandberg@ARM.com# 708782Sgblack@eecs.umich.edu# A parent can now be specified for a source file and default filter 718782Sgblack@eecs.umich.edu# values will be retrieved recursively from parents (children override 728782Sgblack@eecs.umich.edu# parents). 7310810Sbr@bsdpad.com# 7410810Sbr@bsdpad.comclass SourceMeta(type): 7510810Sbr@bsdpad.com '''Meta class for source files that keeps track of all files of a 767259Sgblack@eecs.umich.edu particular type and has a get function for finding all functions 778757Sgblack@eecs.umich.edu of a certain type that match a set of guards''' 7810461SAndreas.Sandberg@ARM.com def __init__(cls, name, bases, dict): 798782Sgblack@eecs.umich.edu super(SourceMeta, cls).__init__(name, bases, dict) 808757Sgblack@eecs.umich.edu cls.all = [] 8112531Sandreas.sandberg@arm.com 828777Sgblack@eecs.umich.edu def get(cls, **guards): 838782Sgblack@eecs.umich.edu '''Find all files that match the specified guards. If a source 848756Sgblack@eecs.umich.edu file does not specify a flag, the default is False''' 8510037SARM gem5 Developers for src in cls.all: 8610037SARM gem5 Developers for flag,value in guards.iteritems(): 876019Shines@cs.fsu.edu # if the flag is found and has a different value, skip 8812605Sgiacomo.travaglini@arm.com # this file 896757SAli.Saidi@ARM.com if src.all_guards.get(flag, False) != value: 908757Sgblack@eecs.umich.edu break 916019Shines@cs.fsu.edu else: 928745Sgblack@eecs.umich.edu yield src 939384SAndreas.Sandberg@arm.com 946397Sgblack@eecs.umich.educlass SourceFile(object): 9512531Sandreas.sandberg@arm.com '''Base object that encapsulates the notion of a source file. 968782Sgblack@eecs.umich.edu This includes, the source node, target node, various manipulations 976019Shines@cs.fsu.edu of those. A source file also specifies a set of guards which 9810461SAndreas.Sandberg@ARM.com describing which builds the source file applies to. A parent can 996397Sgblack@eecs.umich.edu also be specified to get default guards from''' 1008335Snate@binkert.org __metaclass__ = SourceMeta 10112531Sandreas.sandberg@arm.com def __init__(self, source, parent=None, **guards): 1029023Sgblack@eecs.umich.edu self.guards = guards 1039023Sgblack@eecs.umich.edu self.parent = parent 10410461SAndreas.Sandberg@ARM.com 1058335Snate@binkert.org tnode = source 1066019Shines@cs.fsu.edu if not isinstance(source, SCons.Node.FS.File): 10710196SCurtis.Dunham@arm.com tnode = File(source) 10812222Sgabeblack@google.com 10913579Sciro.santilli@arm.com self.tnode = tnode 11013579Sciro.santilli@arm.com self.snode = tnode.srcnode() 11113579Sciro.santilli@arm.com 11213579Sciro.santilli@arm.com for base in type(self).__mro__: 11313579Sciro.santilli@arm.com if issubclass(base, SourceFile): 11413579Sciro.santilli@arm.com base.all.append(self) 11513579Sciro.santilli@arm.com 116 @property 117 def filename(self): 118 return str(self.tnode) 119 120 @property 121 def dirname(self): 122 return dirname(self.filename) 123 124 @property 125 def basename(self): 126 return basename(self.filename) 127 128 @property 129 def extname(self): 130 index = self.basename.rfind('.') 131 if index <= 0: 132 # dot files aren't extensions 133 return self.basename, None 134 135 return self.basename[:index], self.basename[index+1:] 136 137 @property 138 def all_guards(self): 139 '''find all guards for this object getting default values 140 recursively from its parents''' 141 guards = {} 142 if self.parent: 143 guards.update(self.parent.guards) 144 guards.update(self.guards) 145 return guards 146 147 def __lt__(self, other): return self.filename < other.filename 148 def __le__(self, other): return self.filename <= other.filename 149 def __gt__(self, other): return self.filename > other.filename 150 def __ge__(self, other): return self.filename >= other.filename 151 def __eq__(self, other): return self.filename == other.filename 152 def __ne__(self, other): return self.filename != other.filename 153 154 @staticmethod 155 def done(): 156 def disabled(cls, name, *ignored): 157 raise RuntimeError("Additional SourceFile '%s'" % name,\ 158 "declared, but targets deps are already fixed.") 159 SourceFile.__init__ = disabled 160 161 162class Source(SourceFile): 163 '''Add a c/c++ source file to the build''' 164 def __init__(self, source, Werror=True, swig=False, **guards): 165 '''specify the source file, and any guards''' 166 super(Source, self).__init__(source, **guards) 167 168 self.Werror = Werror 169 self.swig = swig 170 171class PySource(SourceFile): 172 '''Add a python source file to the named package''' 173 invalid_sym_char = re.compile('[^A-z0-9_]') 174 modules = {} 175 tnodes = {} 176 symnames = {} 177 178 def __init__(self, package, source, **guards): 179 '''specify the python package, the source file, and any guards''' 180 super(PySource, self).__init__(source, **guards) 181 182 modname,ext = self.extname 183 assert ext == 'py' 184 185 if package: 186 path = package.split('.') 187 else: 188 path = [] 189 190 modpath = path[:] 191 if modname != '__init__': 192 modpath += [ modname ] 193 modpath = '.'.join(modpath) 194 195 arcpath = path + [ self.basename ] 196 abspath = self.snode.abspath 197 if not exists(abspath): 198 abspath = self.tnode.abspath 199 200 self.package = package 201 self.modname = modname 202 self.modpath = modpath 203 self.arcname = joinpath(*arcpath) 204 self.abspath = abspath 205 self.compiled = File(self.filename + 'c') 206 self.cpp = File(self.filename + '.cc') 207 self.symname = PySource.invalid_sym_char.sub('_', modpath) 208 209 PySource.modules[modpath] = self 210 PySource.tnodes[self.tnode] = self 211 PySource.symnames[self.symname] = self 212 213class SimObject(PySource): 214 '''Add a SimObject python file as a python source object and add 215 it to a list of sim object modules''' 216 217 fixed = False 218 modnames = [] 219 220 def __init__(self, source, **guards): 221 '''Specify the source file and any guards (automatically in 222 the m5.objects package)''' 223 super(SimObject, self).__init__('m5.objects', source, **guards) 224 if self.fixed: 225 raise AttributeError, "Too late to call SimObject now." 226 227 bisect.insort_right(SimObject.modnames, self.modname) 228 229class SwigSource(SourceFile): 230 '''Add a swig file to build''' 231 232 def __init__(self, package, source, **guards): 233 '''Specify the python package, the source file, and any guards''' 234 super(SwigSource, self).__init__(source, skip_no_python=True, **guards) 235 236 modname,ext = self.extname 237 assert ext == 'i' 238 239 self.module = modname 240 cc_file = joinpath(self.dirname, modname + '_wrap.cc') 241 py_file = joinpath(self.dirname, modname + '.py') 242 243 self.cc_source = Source(cc_file, swig=True, parent=self, **guards) 244 self.py_source = PySource(package, py_file, parent=self, **guards) 245 246class ProtoBuf(SourceFile): 247 '''Add a Protocol Buffer to build''' 248 249 def __init__(self, source, **guards): 250 '''Specify the source file, and any guards''' 251 super(ProtoBuf, self).__init__(source, **guards) 252 253 # Get the file name and the extension 254 modname,ext = self.extname 255 assert ext == 'proto' 256 257 # Currently, we stick to generating the C++ headers, so we 258 # only need to track the source and header. 259 self.cc_file = File(modname + '.pb.cc') 260 self.hh_file = File(modname + '.pb.h') 261 262class UnitTest(object): 263 '''Create a UnitTest''' 264 265 all = [] 266 def __init__(self, target, *sources, **kwargs): 267 '''Specify the target name and any sources. Sources that are 268 not SourceFiles are evalued with Source(). All files are 269 guarded with a guard of the same name as the UnitTest 270 target.''' 271 272 srcs = [] 273 for src in sources: 274 if not isinstance(src, SourceFile): 275 src = Source(src, skip_lib=True) 276 src.guards[target] = True 277 srcs.append(src) 278 279 self.sources = srcs 280 self.target = target 281 self.main = kwargs.get('main', False) 282 UnitTest.all.append(self) 283 284# Children should have access 285Export('Source') 286Export('PySource') 287Export('SimObject') 288Export('SwigSource') 289Export('ProtoBuf') 290Export('UnitTest') 291 292######################################################################## 293# 294# Debug Flags 295# 296debug_flags = {} 297def DebugFlag(name, desc=None): 298 if name in debug_flags: 299 raise AttributeError, "Flag %s already specified" % name 300 debug_flags[name] = (name, (), desc) 301 302def CompoundFlag(name, flags, desc=None): 303 if name in debug_flags: 304 raise AttributeError, "Flag %s already specified" % name 305 306 compound = tuple(flags) 307 debug_flags[name] = (name, compound, desc) 308 309Export('DebugFlag') 310Export('CompoundFlag') 311 312######################################################################## 313# 314# Set some compiler variables 315# 316 317# Include file paths are rooted in this directory. SCons will 318# automatically expand '.' to refer to both the source directory and 319# the corresponding build directory to pick up generated include 320# files. 321env.Append(CPPPATH=Dir('.')) 322 323for extra_dir in extras_dir_list: 324 env.Append(CPPPATH=Dir(extra_dir)) 325 326# Workaround for bug in SCons version > 0.97d20071212 327# Scons bug id: 2006 gem5 Bug id: 308 328for root, dirs, files in os.walk(base_dir, topdown=True): 329 Dir(root[len(base_dir) + 1:]) 330 331######################################################################## 332# 333# Walk the tree and execute all SConscripts in subdirectories 334# 335 336here = Dir('.').srcnode().abspath 337for root, dirs, files in os.walk(base_dir, topdown=True): 338 if root == here: 339 # we don't want to recurse back into this SConscript 340 continue 341 342 if 'SConscript' in files: 343 build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:]) 344 SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) 345 346for extra_dir in extras_dir_list: 347 prefix_len = len(dirname(extra_dir)) + 1 348 349 # Also add the corresponding build directory to pick up generated 350 # include files. 351 env.Append(CPPPATH=Dir(joinpath(env['BUILDDIR'], extra_dir[prefix_len:]))) 352 353 for root, dirs, files in os.walk(extra_dir, topdown=True): 354 # if build lives in the extras directory, don't walk down it 355 if 'build' in dirs: 356 dirs.remove('build') 357 358 if 'SConscript' in files: 359 build_dir = joinpath(env['BUILDDIR'], root[prefix_len:]) 360 SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) 361 362for opt in export_vars: 363 env.ConfigFile(opt) 364 365def makeTheISA(source, target, env): 366 isas = [ src.get_contents() for src in source ] 367 target_isa = env['TARGET_ISA'] 368 def define(isa): 369 return isa.upper() + '_ISA' 370 371 def namespace(isa): 372 return isa[0].upper() + isa[1:].lower() + 'ISA' 373 374 375 code = code_formatter() 376 code('''\ 377#ifndef __CONFIG_THE_ISA_HH__ 378#define __CONFIG_THE_ISA_HH__ 379 380''') 381 382 # create defines for the preprocessing and compile-time determination 383 for i,isa in enumerate(isas): 384 code('#define $0 $1', define(isa), i + 1) 385 code() 386 387 # create an enum for any run-time determination of the ISA, we 388 # reuse the same name as the namespaces 389 code('enum class Arch {') 390 for i,isa in enumerate(isas): 391 if i + 1 == len(isas): 392 code(' $0 = $1', namespace(isa), define(isa)) 393 else: 394 code(' $0 = $1,', namespace(isa), define(isa)) 395 code('};') 396 397 code(''' 398 399#define THE_ISA ${{define(target_isa)}} 400#define TheISA ${{namespace(target_isa)}} 401#define THE_ISA_STR "${{target_isa}}" 402 403#endif // __CONFIG_THE_ISA_HH__''') 404 405 code.write(str(target[0])) 406 407env.Command('config/the_isa.hh', map(Value, all_isa_list), 408 MakeAction(makeTheISA, Transform("CFG ISA", 0))) 409 410def makeTheGPUISA(source, target, env): 411 isas = [ src.get_contents() for src in source ] 412 target_gpu_isa = env['TARGET_GPU_ISA'] 413 def define(isa): 414 return isa.upper() + '_ISA' 415 416 def namespace(isa): 417 return isa[0].upper() + isa[1:].lower() + 'ISA' 418 419 420 code = code_formatter() 421 code('''\ 422#ifndef __CONFIG_THE_GPU_ISA_HH__ 423#define __CONFIG_THE_GPU_ISA_HH__ 424 425''') 426 427 # create defines for the preprocessing and compile-time determination 428 for i,isa in enumerate(isas): 429 code('#define $0 $1', define(isa), i + 1) 430 code() 431 432 # create an enum for any run-time determination of the ISA, we 433 # reuse the same name as the namespaces 434 code('enum class GPUArch {') 435 for i,isa in enumerate(isas): 436 if i + 1 == len(isas): 437 code(' $0 = $1', namespace(isa), define(isa)) 438 else: 439 code(' $0 = $1,', namespace(isa), define(isa)) 440 code('};') 441 442 code(''' 443 444#define THE_GPU_ISA ${{define(target_gpu_isa)}} 445#define TheGpuISA ${{namespace(target_gpu_isa)}} 446#define THE_GPU_ISA_STR "${{target_gpu_isa}}" 447 448#endif // __CONFIG_THE_GPU_ISA_HH__''') 449 450 code.write(str(target[0])) 451 452env.Command('config/the_gpu_isa.hh', map(Value, all_gpu_isa_list), 453 MakeAction(makeTheGPUISA, Transform("CFG ISA", 0))) 454 455######################################################################## 456# 457# Prevent any SimObjects from being added after this point, they 458# should all have been added in the SConscripts above 459# 460SimObject.fixed = True 461 462class DictImporter(object): 463 '''This importer takes a dictionary of arbitrary module names that 464 map to arbitrary filenames.''' 465 def __init__(self, modules): 466 self.modules = modules 467 self.installed = set() 468 469 def __del__(self): 470 self.unload() 471 472 def unload(self): 473 import sys 474 for module in self.installed: 475 del sys.modules[module] 476 self.installed = set() 477 478 def find_module(self, fullname, path): 479 if fullname == 'm5.defines': 480 return self 481 482 if fullname == 'm5.objects': 483 return self 484 485 if fullname.startswith('m5.internal'): 486 return None 487 488 source = self.modules.get(fullname, None) 489 if source is not None and fullname.startswith('m5.objects'): 490 return self 491 492 return None 493 494 def load_module(self, fullname): 495 mod = imp.new_module(fullname) 496 sys.modules[fullname] = mod 497 self.installed.add(fullname) 498 499 mod.__loader__ = self 500 if fullname == 'm5.objects': 501 mod.__path__ = fullname.split('.') 502 return mod 503 504 if fullname == 'm5.defines': 505 mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env) 506 return mod 507 508 source = self.modules[fullname] 509 if source.modname == '__init__': 510 mod.__path__ = source.modpath 511 mod.__file__ = source.abspath 512 513 exec file(source.abspath, 'r') in mod.__dict__ 514 515 return mod 516 517import m5.SimObject 518import m5.params 519from m5.util import code_formatter 520 521m5.SimObject.clear() 522m5.params.clear() 523 524# install the python importer so we can grab stuff from the source 525# tree itself. We can't have SimObjects added after this point or 526# else we won't know about them for the rest of the stuff. 527importer = DictImporter(PySource.modules) 528sys.meta_path[0:0] = [ importer ] 529 530# import all sim objects so we can populate the all_objects list 531# make sure that we're working with a list, then let's sort it 532for modname in SimObject.modnames: 533 exec('from m5.objects import %s' % modname) 534 535# we need to unload all of the currently imported modules so that they 536# will be re-imported the next time the sconscript is run 537importer.unload() 538sys.meta_path.remove(importer) 539 540sim_objects = m5.SimObject.allClasses 541all_enums = m5.params.allEnums 542 543if m5.SimObject.noCxxHeader: 544 print >> sys.stderr, \ 545 "warning: At least one SimObject lacks a header specification. " \ 546 "This can cause unexpected results in the generated SWIG " \ 547 "wrappers." 548 549# Find param types that need to be explicitly wrapped with swig. 550# These will be recognized because the ParamDesc will have a 551# swig_decl() method. Most param types are based on types that don't 552# need this, either because they're based on native types (like Int) 553# or because they're SimObjects (which get swigged independently). 554# For now the only things handled here are VectorParam types. 555params_to_swig = {} 556for name,obj in sorted(sim_objects.iteritems()): 557 for param in obj._params.local.values(): 558 # load the ptype attribute now because it depends on the 559 # current version of SimObject.allClasses, but when scons 560 # actually uses the value, all versions of 561 # SimObject.allClasses will have been loaded 562 param.ptype 563 564 if not hasattr(param, 'swig_decl'): 565 continue 566 pname = param.ptype_str 567 if pname not in params_to_swig: 568 params_to_swig[pname] = param 569 570######################################################################## 571# 572# calculate extra dependencies 573# 574module_depends = ["m5", "m5.SimObject", "m5.params"] 575depends = [ PySource.modules[dep].snode for dep in module_depends ] 576depends.sort(key = lambda x: x.name) 577 578######################################################################## 579# 580# Commands for the basic automatically generated python files 581# 582 583# Generate Python file containing a dict specifying the current 584# buildEnv flags. 585def makeDefinesPyFile(target, source, env): 586 build_env = source[0].get_contents() 587 588 code = code_formatter() 589 code(""" 590import m5.internal 591import m5.util 592 593buildEnv = m5.util.SmartDict($build_env) 594 595compileDate = m5.internal.core.compileDate 596_globals = globals() 597for key,val in m5.internal.core.__dict__.iteritems(): 598 if key.startswith('flag_'): 599 flag = key[5:] 600 _globals[flag] = val 601del _globals 602""") 603 code.write(target[0].abspath) 604 605defines_info = Value(build_env) 606# Generate a file with all of the compile options in it 607env.Command('python/m5/defines.py', defines_info, 608 MakeAction(makeDefinesPyFile, Transform("DEFINES", 0))) 609PySource('m5', 'python/m5/defines.py') 610 611# Generate python file containing info about the M5 source code 612def makeInfoPyFile(target, source, env): 613 code = code_formatter() 614 for src in source: 615 data = ''.join(file(src.srcnode().abspath, 'r').xreadlines()) 616 code('$src = ${{repr(data)}}') 617 code.write(str(target[0])) 618 619# Generate a file that wraps the basic top level files 620env.Command('python/m5/info.py', 621 [ '#/COPYING', '#/LICENSE', '#/README', ], 622 MakeAction(makeInfoPyFile, Transform("INFO"))) 623PySource('m5', 'python/m5/info.py') 624 625######################################################################## 626# 627# Create all of the SimObject param headers and enum headers 628# 629 630def createSimObjectParamStruct(target, source, env): 631 assert len(target) == 1 and len(source) == 1 632 633 name = str(source[0].get_contents()) 634 obj = sim_objects[name] 635 636 code = code_formatter() 637 obj.cxx_param_decl(code) 638 code.write(target[0].abspath) 639 640def createSimObjectCxxConfig(is_header): 641 def body(target, source, env): 642 assert len(target) == 1 and len(source) == 1 643 644 name = str(source[0].get_contents()) 645 obj = sim_objects[name] 646 647 code = code_formatter() 648 obj.cxx_config_param_file(code, is_header) 649 code.write(target[0].abspath) 650 return body 651 652def createParamSwigWrapper(target, source, env): 653 assert len(target) == 1 and len(source) == 1 654 655 name = str(source[0].get_contents()) 656 param = params_to_swig[name] 657 658 code = code_formatter() 659 param.swig_decl(code) 660 code.write(target[0].abspath) 661 662def createEnumStrings(target, source, env): 663 assert len(target) == 1 and len(source) == 1 664 665 name = str(source[0].get_contents()) 666 obj = all_enums[name] 667 668 code = code_formatter() 669 obj.cxx_def(code) 670 code.write(target[0].abspath) 671 672def createEnumDecls(target, source, env): 673 assert len(target) == 1 and len(source) == 1 674 675 name = str(source[0].get_contents()) 676 obj = all_enums[name] 677 678 code = code_formatter() 679 obj.cxx_decl(code) 680 code.write(target[0].abspath) 681 682def createEnumSwigWrapper(target, source, env): 683 assert len(target) == 1 and len(source) == 1 684 685 name = str(source[0].get_contents()) 686 obj = all_enums[name] 687 688 code = code_formatter() 689 obj.swig_decl(code) 690 code.write(target[0].abspath) 691 692def createSimObjectSwigWrapper(target, source, env): 693 name = source[0].get_contents() 694 obj = sim_objects[name] 695 696 code = code_formatter() 697 obj.swig_decl(code) 698 code.write(target[0].abspath) 699 700# dummy target for generated code 701# we start out with all the Source files so they get copied to build/*/ also. 702SWIG = env.Dummy('swig', [s.tnode for s in Source.get()]) 703 704# Generate all of the SimObject param C++ struct header files 705params_hh_files = [] 706for name,simobj in sorted(sim_objects.iteritems()): 707 py_source = PySource.modules[simobj.__module__] 708 extra_deps = [ py_source.tnode ] 709 710 hh_file = File('params/%s.hh' % name) 711 params_hh_files.append(hh_file) 712 env.Command(hh_file, Value(name), 713 MakeAction(createSimObjectParamStruct, Transform("SO PARAM"))) 714 env.Depends(hh_file, depends + extra_deps) 715 env.Depends(SWIG, hh_file) 716 717# C++ parameter description files 718if GetOption('with_cxx_config'): 719 for name,simobj in sorted(sim_objects.iteritems()): 720 py_source = PySource.modules[simobj.__module__] 721 extra_deps = [ py_source.tnode ] 722 723 cxx_config_hh_file = File('cxx_config/%s.hh' % name) 724 cxx_config_cc_file = File('cxx_config/%s.cc' % name) 725 env.Command(cxx_config_hh_file, Value(name), 726 MakeAction(createSimObjectCxxConfig(True), 727 Transform("CXXCPRHH"))) 728 env.Command(cxx_config_cc_file, Value(name), 729 MakeAction(createSimObjectCxxConfig(False), 730 Transform("CXXCPRCC"))) 731 env.Depends(cxx_config_hh_file, depends + extra_deps + 732 [File('params/%s.hh' % name), File('sim/cxx_config.hh')]) 733 env.Depends(cxx_config_cc_file, depends + extra_deps + 734 [cxx_config_hh_file]) 735 Source(cxx_config_cc_file) 736 737 cxx_config_init_cc_file = File('cxx_config/init.cc') 738 739 def createCxxConfigInitCC(target, source, env): 740 assert len(target) == 1 and len(source) == 1 741 742 code = code_formatter() 743 744 for name,simobj in sorted(sim_objects.iteritems()): 745 if not hasattr(simobj, 'abstract') or not simobj.abstract: 746 code('#include "cxx_config/${name}.hh"') 747 code() 748 code('void cxxConfigInit()') 749 code('{') 750 code.indent() 751 for name,simobj in sorted(sim_objects.iteritems()): 752 not_abstract = not hasattr(simobj, 'abstract') or \ 753 not simobj.abstract 754 if not_abstract and 'type' in simobj.__dict__: 755 code('cxx_config_directory["${name}"] = ' 756 '${name}CxxConfigParams::makeDirectoryEntry();') 757 code.dedent() 758 code('}') 759 code.write(target[0].abspath) 760 761 py_source = PySource.modules[simobj.__module__] 762 extra_deps = [ py_source.tnode ] 763 env.Command(cxx_config_init_cc_file, Value(name), 764 MakeAction(createCxxConfigInitCC, Transform("CXXCINIT"))) 765 cxx_param_hh_files = ["cxx_config/%s.hh" % simobj 766 for name,simobj in sorted(sim_objects.iteritems()) 767 if not hasattr(simobj, 'abstract') or not simobj.abstract] 768 Depends(cxx_config_init_cc_file, cxx_param_hh_files + 769 [File('sim/cxx_config.hh')]) 770 Source(cxx_config_init_cc_file) 771 772# Generate any needed param SWIG wrapper files 773params_i_files = [] 774for name,param in sorted(params_to_swig.iteritems()): 775 i_file = File('python/m5/internal/%s.i' % (param.swig_module_name())) 776 params_i_files.append(i_file) 777 env.Command(i_file, Value(name), 778 MakeAction(createParamSwigWrapper, Transform("SW PARAM"))) 779 env.Depends(i_file, depends) 780 env.Depends(SWIG, i_file) 781 SwigSource('m5.internal', i_file) 782 783# Generate all enum header files 784for name,enum in sorted(all_enums.iteritems()): 785 py_source = PySource.modules[enum.__module__] 786 extra_deps = [ py_source.tnode ] 787 788 cc_file = File('enums/%s.cc' % name) 789 env.Command(cc_file, Value(name), 790 MakeAction(createEnumStrings, Transform("ENUM STR"))) 791 env.Depends(cc_file, depends + extra_deps) 792 env.Depends(SWIG, cc_file) 793 Source(cc_file) 794 795 hh_file = File('enums/%s.hh' % name) 796 env.Command(hh_file, Value(name), 797 MakeAction(createEnumDecls, Transform("ENUMDECL"))) 798 env.Depends(hh_file, depends + extra_deps) 799 env.Depends(SWIG, hh_file) 800 801 i_file = File('python/m5/internal/enum_%s.i' % name) 802 env.Command(i_file, Value(name), 803 MakeAction(createEnumSwigWrapper, Transform("ENUMSWIG"))) 804 env.Depends(i_file, depends + extra_deps) 805 env.Depends(SWIG, i_file) 806 SwigSource('m5.internal', i_file) 807 808# Generate SimObject SWIG wrapper files 809for name,simobj in sorted(sim_objects.iteritems()): 810 py_source = PySource.modules[simobj.__module__] 811 extra_deps = [ py_source.tnode ] 812 i_file = File('python/m5/internal/param_%s.i' % name) 813 env.Command(i_file, Value(name), 814 MakeAction(createSimObjectSwigWrapper, Transform("SO SWIG"))) 815 env.Depends(i_file, depends + extra_deps) 816 SwigSource('m5.internal', i_file) 817 818# Generate the main swig init file 819def makeEmbeddedSwigInit(target, source, env): 820 code = code_formatter() 821 module = source[0].get_contents() 822 code('''\ 823#include "sim/init.hh" 824 825extern "C" { 826 void init_${module}(); 827} 828 829EmbeddedSwig embed_swig_${module}(init_${module}); 830''') 831 code.write(str(target[0])) 832 833# Build all swig modules 834for swig in SwigSource.all: 835 env.Command([swig.cc_source.tnode, swig.py_source.tnode], swig.tnode, 836 MakeAction('$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} ' 837 '-o ${TARGETS[0]} $SOURCES', Transform("SWIG"))) 838 cc_file = str(swig.tnode) 839 init_file = '%s/%s_init.cc' % (dirname(cc_file), basename(cc_file)) 840 env.Command(init_file, Value(swig.module), 841 MakeAction(makeEmbeddedSwigInit, Transform("EMBED SW"))) 842 env.Depends(SWIG, init_file) 843 Source(init_file, **swig.guards) 844 845# Build all protocol buffers if we have got protoc and protobuf available 846if env['HAVE_PROTOBUF']: 847 for proto in ProtoBuf.all: 848 # Use both the source and header as the target, and the .proto 849 # file as the source. When executing the protoc compiler, also 850 # specify the proto_path to avoid having the generated files 851 # include the path. 852 env.Command([proto.cc_file, proto.hh_file], proto.tnode, 853 MakeAction('$PROTOC --cpp_out ${TARGET.dir} ' 854 '--proto_path ${SOURCE.dir} $SOURCE', 855 Transform("PROTOC"))) 856 857 env.Depends(SWIG, [proto.cc_file, proto.hh_file]) 858 # Add the C++ source file 859 Source(proto.cc_file, **proto.guards) 860elif ProtoBuf.all: 861 print 'Got protobuf to build, but lacks support!' 862 Exit(1) 863 864# 865# Handle debug flags 866# 867def makeDebugFlagCC(target, source, env): 868 assert(len(target) == 1 and len(source) == 1) 869 870 code = code_formatter() 871 872 # delay definition of CompoundFlags until after all the definition 873 # of all constituent SimpleFlags 874 comp_code = code_formatter() 875 876 # file header 877 code(''' 878/* 879 * DO NOT EDIT THIS FILE! Automatically generated by SCons. 880 */ 881 882#include "base/debug.hh" 883 884namespace Debug { 885 886''') 887 888 for name, flag in sorted(source[0].read().iteritems()): 889 n, compound, desc = flag 890 assert n == name 891 892 if not compound: 893 code('SimpleFlag $name("$name", "$desc");') 894 else: 895 comp_code('CompoundFlag $name("$name", "$desc",') 896 comp_code.indent() 897 last = len(compound) - 1 898 for i,flag in enumerate(compound): 899 if i != last: 900 comp_code('&$flag,') 901 else: 902 comp_code('&$flag);') 903 comp_code.dedent() 904 905 code.append(comp_code) 906 code() 907 code('} // namespace Debug') 908 909 code.write(str(target[0])) 910 911def makeDebugFlagHH(target, source, env): 912 assert(len(target) == 1 and len(source) == 1) 913 914 val = eval(source[0].get_contents()) 915 name, compound, desc = val 916 917 code = code_formatter() 918 919 # file header boilerplate 920 code('''\ 921/* 922 * DO NOT EDIT THIS FILE! Automatically generated by SCons. 923 */ 924 925#ifndef __DEBUG_${name}_HH__ 926#define __DEBUG_${name}_HH__ 927 928namespace Debug { 929''') 930 931 if compound: 932 code('class CompoundFlag;') 933 code('class SimpleFlag;') 934 935 if compound: 936 code('extern CompoundFlag $name;') 937 for flag in compound: 938 code('extern SimpleFlag $flag;') 939 else: 940 code('extern SimpleFlag $name;') 941 942 code(''' 943} 944 945#endif // __DEBUG_${name}_HH__ 946''') 947 948 code.write(str(target[0])) 949 950for name,flag in sorted(debug_flags.iteritems()): 951 n, compound, desc = flag 952 assert n == name 953 954 hh_file = 'debug/%s.hh' % name 955 env.Command(hh_file, Value(flag), 956 MakeAction(makeDebugFlagHH, Transform("TRACING", 0))) 957 env.Depends(SWIG, hh_file) 958 959env.Command('debug/flags.cc', Value(debug_flags), 960 MakeAction(makeDebugFlagCC, Transform("TRACING", 0))) 961env.Depends(SWIG, 'debug/flags.cc') 962Source('debug/flags.cc') 963 964# version tags 965tags = \ 966env.Command('sim/tags.cc', None, 967 MakeAction('util/cpt_upgrader.py --get-cc-file > $TARGET', 968 Transform("VER TAGS"))) 969env.AlwaysBuild(tags) 970 971# Embed python files. All .py files that have been indicated by a 972# PySource() call in a SConscript need to be embedded into the M5 973# library. To do that, we compile the file to byte code, marshal the 974# byte code, compress it, and then generate a c++ file that 975# inserts the result into an array. 976def embedPyFile(target, source, env): 977 def c_str(string): 978 if string is None: 979 return "0" 980 return '"%s"' % string 981 982 '''Action function to compile a .py into a code object, marshal 983 it, compress it, and stick it into an asm file so the code appears 984 as just bytes with a label in the data section''' 985 986 src = file(str(source[0]), 'r').read() 987 988 pysource = PySource.tnodes[source[0]] 989 compiled = compile(src, pysource.abspath, 'exec') 990 marshalled = marshal.dumps(compiled) 991 compressed = zlib.compress(marshalled) 992 data = compressed 993 sym = pysource.symname 994 995 code = code_formatter() 996 code('''\ 997#include "sim/init.hh" 998 999namespace { 1000 1001const uint8_t data_${sym}[] = { 1002''') 1003 code.indent() 1004 step = 16 1005 for i in xrange(0, len(data), step): 1006 x = array.array('B', data[i:i+step]) 1007 code(''.join('%d,' % d for d in x)) 1008 code.dedent() 1009 1010 code('''}; 1011 1012EmbeddedPython embedded_${sym}( 1013 ${{c_str(pysource.arcname)}}, 1014 ${{c_str(pysource.abspath)}}, 1015 ${{c_str(pysource.modpath)}}, 1016 data_${sym}, 1017 ${{len(data)}}, 1018 ${{len(marshalled)}}); 1019 1020} // anonymous namespace 1021''') 1022 code.write(str(target[0])) 1023 1024for source in PySource.all: 1025 env.Command(source.cpp, source.tnode, 1026 MakeAction(embedPyFile, Transform("EMBED PY"))) 1027 env.Depends(SWIG, source.cpp) 1028 Source(source.cpp, skip_no_python=True) 1029 1030######################################################################## 1031# 1032# Define binaries. Each different build type (debug, opt, etc.) gets 1033# a slightly different build environment. 1034# 1035 1036# List of constructed environments to pass back to SConstruct 1037date_source = Source('base/date.cc', skip_lib=True) 1038 1039# Capture this directory for the closure makeEnv, otherwise when it is 1040# called, it won't know what directory it should use. 1041variant_dir = Dir('.').path 1042def variant(*path): 1043 return os.path.join(variant_dir, *path) 1044def variantd(*path): 1045 return variant(*path)+'/' 1046 1047# Function to create a new build environment as clone of current 1048# environment 'env' with modified object suffix and optional stripped 1049# binary. Additional keyword arguments are appended to corresponding 1050# build environment vars. 1051def makeEnv(env, label, objsfx, strip = False, **kwargs): 1052 # SCons doesn't know to append a library suffix when there is a '.' in the 1053 # name. Use '_' instead. 1054 libname = variant('gem5_' + label) 1055 exename = variant('gem5.' + label) 1056 secondary_exename = variant('m5.' + label) 1057 1058 new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's') 1059 new_env.Label = label 1060 new_env.Append(**kwargs) 1061 1062 swig_env = new_env.Clone() 1063 1064 # Both gcc and clang have issues with unused labels and values in 1065 # the SWIG generated code 1066 swig_env.Append(CCFLAGS=['-Wno-unused-label', '-Wno-unused-value']) 1067 1068 if env['GCC']: 1069 # Depending on the SWIG version, we also need to supress 1070 # warnings about uninitialized variables and missing field 1071 # initializers. 1072 swig_env.Append(CCFLAGS=['-Wno-uninitialized', 1073 '-Wno-missing-field-initializers', 1074 '-Wno-unused-but-set-variable', 1075 '-Wno-maybe-uninitialized', 1076 '-Wno-type-limits']) 1077 1078 # Only gcc >= 4.9 supports UBSan, so check both the version 1079 # and the command-line option before adding the compiler and 1080 # linker flags. 1081 if GetOption('with_ubsan') and \ 1082 compareVersions(env['GCC_VERSION'], '4.9') >= 0: 1083 new_env.Append(CCFLAGS='-fsanitize=undefined') 1084 new_env.Append(LINKFLAGS='-fsanitize=undefined') 1085 1086 if env['CLANG']: 1087 swig_env.Append(CCFLAGS=['-Wno-sometimes-uninitialized', 1088 '-Wno-deprecated-register', 1089 '-Wno-tautological-compare']) 1090 1091 # All supported clang versions have support for UBSan, so if 1092 # asked to use it, append the compiler and linker flags. 1093 if GetOption('with_ubsan'): 1094 new_env.Append(CCFLAGS='-fsanitize=undefined') 1095 new_env.Append(LINKFLAGS='-fsanitize=undefined') 1096 1097 werror_env = new_env.Clone() 1098 # Treat warnings as errors but white list some warnings that we 1099 # want to allow (e.g., deprecation warnings). 1100 werror_env.Append(CCFLAGS=['-Werror', 1101 '-Wno-error=deprecated-declarations', 1102 '-Wno-error=deprecated', 1103 ]) 1104 1105 def make_obj(source, static, extra_deps = None): 1106 '''This function adds the specified source to the correct 1107 build environment, and returns the corresponding SCons Object 1108 nodes''' 1109 1110 if source.swig: 1111 env = swig_env 1112 elif source.Werror: 1113 env = werror_env 1114 else: 1115 env = new_env 1116 1117 if static: 1118 obj = env.StaticObject(source.tnode) 1119 else: 1120 obj = env.SharedObject(source.tnode) 1121 1122 if extra_deps: 1123 env.Depends(obj, extra_deps) 1124 1125 return obj 1126 1127 lib_guards = {'main': False, 'skip_lib': False} 1128 1129 # Without Python, leave out all SWIG and Python content from the 1130 # library builds. The option doesn't affect gem5 built as a program 1131 if GetOption('without_python'): 1132 lib_guards['skip_no_python'] = False 1133 1134 static_objs = [ make_obj(s, True) for s in Source.get(**lib_guards) ] 1135 shared_objs = [ make_obj(s, False) for s in Source.get(**lib_guards) ] 1136 1137 static_date = make_obj(date_source, static=True, extra_deps=static_objs) 1138 static_objs.append(static_date) 1139 1140 shared_date = make_obj(date_source, static=False, extra_deps=shared_objs) 1141 shared_objs.append(shared_date) 1142 1143 # First make a library of everything but main() so other programs can 1144 # link against m5. 1145 static_lib = new_env.StaticLibrary(libname, static_objs) 1146 shared_lib = new_env.SharedLibrary(libname, shared_objs) 1147 1148 # Now link a stub with main() and the static library. 1149 main_objs = [ make_obj(s, True) for s in Source.get(main=True) ] 1150 1151 for test in UnitTest.all: 1152 flags = { test.target : True } 1153 test_sources = Source.get(**flags) 1154 test_objs = [ make_obj(s, static=True) for s in test_sources ] 1155 if test.main: 1156 test_objs += main_objs 1157 path = variant('unittest/%s.%s' % (test.target, label)) 1158 new_env.Program(path, test_objs + static_objs) 1159 1160 progname = exename 1161 if strip: 1162 progname += '.unstripped' 1163 1164 targets = new_env.Program(progname, main_objs + static_objs) 1165 1166 if strip: 1167 if sys.platform == 'sunos5': 1168 cmd = 'cp $SOURCE $TARGET; strip $TARGET' 1169 else: 1170 cmd = 'strip $SOURCE -o $TARGET' 1171 targets = new_env.Command(exename, progname, 1172 MakeAction(cmd, Transform("STRIP"))) 1173 1174 new_env.Command(secondary_exename, exename, 1175 MakeAction('ln $SOURCE $TARGET', Transform("HARDLINK"))) 1176 1177 new_env.M5Binary = targets[0] 1178 return new_env 1179 1180# Start out with the compiler flags common to all compilers, 1181# i.e. they all use -g for opt and -g -pg for prof 1182ccflags = {'debug' : [], 'opt' : ['-g'], 'fast' : [], 'prof' : ['-g', '-pg'], 1183 'perf' : ['-g']} 1184 1185# Start out with the linker flags common to all linkers, i.e. -pg for 1186# prof, and -lprofiler for perf. The -lprofile flag is surrounded by 1187# no-as-needed and as-needed as the binutils linker is too clever and 1188# simply doesn't link to the library otherwise. 1189ldflags = {'debug' : [], 'opt' : [], 'fast' : [], 'prof' : ['-pg'], 1190 'perf' : ['-Wl,--no-as-needed', '-lprofiler', '-Wl,--as-needed']} 1191 1192# For Link Time Optimization, the optimisation flags used to compile 1193# individual files are decoupled from those used at link time 1194# (i.e. you can compile with -O3 and perform LTO with -O0), so we need 1195# to also update the linker flags based on the target. 1196if env['GCC']: 1197 if sys.platform == 'sunos5': 1198 ccflags['debug'] += ['-gstabs+'] 1199 else: 1200 ccflags['debug'] += ['-ggdb3'] 1201 ldflags['debug'] += ['-O0'] 1202 # opt, fast, prof and perf all share the same cc flags, also add 1203 # the optimization to the ldflags as LTO defers the optimization 1204 # to link time 1205 for target in ['opt', 'fast', 'prof', 'perf']: 1206 ccflags[target] += ['-O3'] 1207 ldflags[target] += ['-O3'] 1208 1209 ccflags['fast'] += env['LTO_CCFLAGS'] 1210 ldflags['fast'] += env['LTO_LDFLAGS'] 1211elif env['CLANG']: 1212 ccflags['debug'] += ['-g', '-O0'] 1213 # opt, fast, prof and perf all share the same cc flags 1214 for target in ['opt', 'fast', 'prof', 'perf']: 1215 ccflags[target] += ['-O3'] 1216else: 1217 print 'Unknown compiler, please fix compiler options' 1218 Exit(1) 1219 1220 1221# To speed things up, we only instantiate the build environments we 1222# need. We try to identify the needed environment for each target; if 1223# we can't, we fall back on instantiating all the environments just to 1224# be safe. 1225target_types = ['debug', 'opt', 'fast', 'prof', 'perf'] 1226obj2target = {'do': 'debug', 'o': 'opt', 'fo': 'fast', 'po': 'prof', 1227 'gpo' : 'perf'} 1228 1229def identifyTarget(t): 1230 ext = t.split('.')[-1] 1231 if ext in target_types: 1232 return ext 1233 if obj2target.has_key(ext): 1234 return obj2target[ext] 1235 match = re.search(r'/tests/([^/]+)/', t) 1236 if match and match.group(1) in target_types: 1237 return match.group(1) 1238 return 'all' 1239 1240needed_envs = [identifyTarget(target) for target in BUILD_TARGETS] 1241if 'all' in needed_envs: 1242 needed_envs += target_types 1243 1244gem5_root = Dir('.').up().up().abspath 1245def makeEnvirons(target, source, env): 1246 # cause any later Source() calls to be fatal, as a diagnostic. 1247 Source.done() 1248 1249 envList = [] 1250 1251 # Debug binary 1252 if 'debug' in needed_envs: 1253 envList.append( 1254 makeEnv(env, 'debug', '.do', 1255 CCFLAGS = Split(ccflags['debug']), 1256 CPPDEFINES = ['DEBUG', 'TRACING_ON=1'], 1257 LINKFLAGS = Split(ldflags['debug']))) 1258 1259 # Optimized binary 1260 if 'opt' in needed_envs: 1261 envList.append( 1262 makeEnv(env, 'opt', '.o', 1263 CCFLAGS = Split(ccflags['opt']), 1264 CPPDEFINES = ['TRACING_ON=1'], 1265 LINKFLAGS = Split(ldflags['opt']))) 1266 1267 # "Fast" binary 1268 if 'fast' in needed_envs: 1269 envList.append( 1270 makeEnv(env, 'fast', '.fo', strip = True, 1271 CCFLAGS = Split(ccflags['fast']), 1272 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1273 LINKFLAGS = Split(ldflags['fast']))) 1274 1275 # Profiled binary using gprof 1276 if 'prof' in needed_envs: 1277 envList.append( 1278 makeEnv(env, 'prof', '.po', 1279 CCFLAGS = Split(ccflags['prof']), 1280 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1281 LINKFLAGS = Split(ldflags['prof']))) 1282 1283 # Profiled binary using google-pprof 1284 if 'perf' in needed_envs: 1285 envList.append( 1286 makeEnv(env, 'perf', '.gpo', 1287 CCFLAGS = Split(ccflags['perf']), 1288 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1289 LINKFLAGS = Split(ldflags['perf']))) 1290 1291 # Set up the regression tests for each build. 1292 for e in envList: 1293 SConscript(os.path.join(gem5_root, 'tests', 'SConscript'), 1294 variant_dir = variantd('tests', e.Label), 1295 exports = { 'env' : e }, duplicate = False) 1296 1297# The MakeEnvirons Builder defers the full dependency collection until 1298# after processing the ISA definition (due to dynamically generated 1299# source files). Add this dependency to all targets so they will wait 1300# until the environments are completely set up. Otherwise, a second 1301# process (e.g. -j2 or higher) will try to compile the requested target, 1302# not know how, and fail. 1303env.Append(BUILDERS = {'MakeEnvirons' : 1304 Builder(action=MakeAction(makeEnvirons, 1305 Transform("ENVIRONS", 1)))}) 1306 1307isa_target = env['PHONY_BASE'] + '-deps' 1308environs = env['PHONY_BASE'] + '-environs' 1309env.Depends('#all-deps', isa_target) 1310env.Depends('#all-environs', environs) 1311env.ScanISA(isa_target, File('arch/%s/generated/inc.d' % env['TARGET_ISA'])) 1312envSetup = env.MakeEnvirons(environs, isa_target) 1313 1314# make sure no -deps targets occur before all ISAs are complete 1315env.Depends(isa_target, '#all-isas') 1316# likewise for -environs targets and all the -deps targets 1317env.Depends(environs, '#all-deps') 1318