SConscript revision 8232
1# -*- mode:python -*- 2 3# Copyright (c) 2004-2005 The Regents of The University of Michigan 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are 8# met: redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer; 10# redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution; 13# neither the name of the copyright holders nor the names of its 14# contributors may be used to endorse or promote products derived from 15# this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28# 29# Authors: Nathan Binkert 30 31import array 32import bisect 33import imp 34import marshal 35import os 36import re 37import sys 38import zlib 39 40from os.path import basename, dirname, exists, isdir, isfile, join as joinpath 41 42import SCons 43 44# This file defines how to build a particular configuration of M5 45# based on variable settings in the 'env' build environment. 46 47Import('*') 48 49# Children need to see the environment 50Export('env') 51 52build_env = [(opt, env[opt]) for opt in export_vars] 53 54from m5.util import code_formatter 55 56######################################################################## 57# Code for adding source files of various types 58# 59class SourceMeta(type): 60 def __init__(cls, name, bases, dict): 61 super(SourceMeta, cls).__init__(name, bases, dict) 62 cls.all = [] 63 64 def get(cls, **kwargs): 65 for src in cls.all: 66 for attr,value in kwargs.iteritems(): 67 if getattr(src, attr) != value: 68 break 69 else: 70 yield src 71 72class SourceFile(object): 73 __metaclass__ = SourceMeta 74 def __init__(self, source): 75 tnode = source 76 if not isinstance(source, SCons.Node.FS.File): 77 tnode = File(source) 78 79 self.tnode = tnode 80 self.snode = tnode.srcnode() 81 self.filename = str(tnode) 82 self.dirname = dirname(self.filename) 83 self.basename = basename(self.filename) 84 index = self.basename.rfind('.') 85 if index <= 0: 86 # dot files aren't extensions 87 self.extname = self.basename, None 88 else: 89 self.extname = self.basename[:index], self.basename[index+1:] 90 91 for base in type(self).__mro__: 92 if issubclass(base, SourceFile): 93 base.all.append(self) 94 95 def __lt__(self, other): return self.filename < other.filename 96 def __le__(self, other): return self.filename <= other.filename 97 def __gt__(self, other): return self.filename > other.filename 98 def __ge__(self, other): return self.filename >= other.filename 99 def __eq__(self, other): return self.filename == other.filename 100 def __ne__(self, other): return self.filename != other.filename 101 102class Source(SourceFile): 103 '''Add a c/c++ source file to the build''' 104 def __init__(self, source, Werror=True, swig=False, bin_only=False, 105 skip_lib=False): 106 super(Source, self).__init__(source) 107 108 self.Werror = Werror 109 self.swig = swig 110 self.bin_only = bin_only 111 self.skip_lib = bin_only or skip_lib 112 113class PySource(SourceFile): 114 '''Add a python source file to the named package''' 115 invalid_sym_char = re.compile('[^A-z0-9_]') 116 modules = {} 117 tnodes = {} 118 symnames = {} 119 120 def __init__(self, package, source): 121 super(PySource, self).__init__(source) 122 123 modname,ext = self.extname 124 assert ext == 'py' 125 126 if package: 127 path = package.split('.') 128 else: 129 path = [] 130 131 modpath = path[:] 132 if modname != '__init__': 133 modpath += [ modname ] 134 modpath = '.'.join(modpath) 135 136 arcpath = path + [ self.basename ] 137 abspath = self.snode.abspath 138 if not exists(abspath): 139 abspath = self.tnode.abspath 140 141 self.package = package 142 self.modname = modname 143 self.modpath = modpath 144 self.arcname = joinpath(*arcpath) 145 self.abspath = abspath 146 self.compiled = File(self.filename + 'c') 147 self.cpp = File(self.filename + '.cc') 148 self.symname = PySource.invalid_sym_char.sub('_', modpath) 149 150 PySource.modules[modpath] = self 151 PySource.tnodes[self.tnode] = self 152 PySource.symnames[self.symname] = self 153 154class SimObject(PySource): 155 '''Add a SimObject python file as a python source object and add 156 it to a list of sim object modules''' 157 158 fixed = False 159 modnames = [] 160 161 def __init__(self, source): 162 super(SimObject, self).__init__('m5.objects', source) 163 if self.fixed: 164 raise AttributeError, "Too late to call SimObject now." 165 166 bisect.insort_right(SimObject.modnames, self.modname) 167 168class SwigSource(SourceFile): 169 '''Add a swig file to build''' 170 171 def __init__(self, package, source): 172 super(SwigSource, self).__init__(source) 173 174 modname,ext = self.extname 175 assert ext == 'i' 176 177 self.module = modname 178 cc_file = joinpath(self.dirname, modname + '_wrap.cc') 179 py_file = joinpath(self.dirname, modname + '.py') 180 181 self.cc_source = Source(cc_file, swig=True) 182 self.py_source = PySource(package, py_file) 183 184unit_tests = [] 185def UnitTest(target, sources): 186 if not isinstance(sources, (list, tuple)): 187 sources = [ sources ] 188 189 sources = [ Source(src, skip_lib=True) for src in sources ] 190 unit_tests.append((target, sources)) 191 192# Children should have access 193Export('Source') 194Export('PySource') 195Export('SimObject') 196Export('SwigSource') 197Export('UnitTest') 198 199######################################################################## 200# 201# Debug Flags 202# 203debug_flags = {} 204def DebugFlag(name, desc=None): 205 if name in debug_flags: 206 raise AttributeError, "Flag %s already specified" % name 207 debug_flags[name] = (name, (), desc) 208TraceFlag = DebugFlag 209 210def CompoundFlag(name, flags, desc=None): 211 if name in debug_flags: 212 raise AttributeError, "Flag %s already specified" % name 213 214 compound = tuple(flags) 215 debug_flags[name] = (name, compound, desc) 216 217Export('DebugFlag') 218Export('TraceFlag') 219Export('CompoundFlag') 220 221######################################################################## 222# 223# Set some compiler variables 224# 225 226# Include file paths are rooted in this directory. SCons will 227# automatically expand '.' to refer to both the source directory and 228# the corresponding build directory to pick up generated include 229# files. 230env.Append(CPPPATH=Dir('.')) 231 232for extra_dir in extras_dir_list: 233 env.Append(CPPPATH=Dir(extra_dir)) 234 235# Workaround for bug in SCons version > 0.97d20071212 236# Scons bug id: 2006 M5 Bug id: 308 237for root, dirs, files in os.walk(base_dir, topdown=True): 238 Dir(root[len(base_dir) + 1:]) 239 240######################################################################## 241# 242# Walk the tree and execute all SConscripts in subdirectories 243# 244 245here = Dir('.').srcnode().abspath 246for root, dirs, files in os.walk(base_dir, topdown=True): 247 if root == here: 248 # we don't want to recurse back into this SConscript 249 continue 250 251 if 'SConscript' in files: 252 build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:]) 253 SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) 254 255for extra_dir in extras_dir_list: 256 prefix_len = len(dirname(extra_dir)) + 1 257 for root, dirs, files in os.walk(extra_dir, topdown=True): 258 if 'SConscript' in files: 259 build_dir = joinpath(env['BUILDDIR'], root[prefix_len:]) 260 SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) 261 262for opt in export_vars: 263 env.ConfigFile(opt) 264 265def makeTheISA(source, target, env): 266 isas = [ src.get_contents() for src in source ] 267 target_isa = env['TARGET_ISA'] 268 def define(isa): 269 return isa.upper() + '_ISA' 270 271 def namespace(isa): 272 return isa[0].upper() + isa[1:].lower() + 'ISA' 273 274 275 code = code_formatter() 276 code('''\ 277#ifndef __CONFIG_THE_ISA_HH__ 278#define __CONFIG_THE_ISA_HH__ 279 280''') 281 282 for i,isa in enumerate(isas): 283 code('#define $0 $1', define(isa), i + 1) 284 285 code(''' 286 287#define THE_ISA ${{define(target_isa)}} 288#define TheISA ${{namespace(target_isa)}} 289 290#endif // __CONFIG_THE_ISA_HH__''') 291 292 code.write(str(target[0])) 293 294env.Command('config/the_isa.hh', map(Value, all_isa_list), 295 MakeAction(makeTheISA, Transform("CFG ISA", 0))) 296 297######################################################################## 298# 299# Prevent any SimObjects from being added after this point, they 300# should all have been added in the SConscripts above 301# 302SimObject.fixed = True 303 304class DictImporter(object): 305 '''This importer takes a dictionary of arbitrary module names that 306 map to arbitrary filenames.''' 307 def __init__(self, modules): 308 self.modules = modules 309 self.installed = set() 310 311 def __del__(self): 312 self.unload() 313 314 def unload(self): 315 import sys 316 for module in self.installed: 317 del sys.modules[module] 318 self.installed = set() 319 320 def find_module(self, fullname, path): 321 if fullname == 'm5.defines': 322 return self 323 324 if fullname == 'm5.objects': 325 return self 326 327 if fullname.startswith('m5.internal'): 328 return None 329 330 source = self.modules.get(fullname, None) 331 if source is not None and fullname.startswith('m5.objects'): 332 return self 333 334 return None 335 336 def load_module(self, fullname): 337 mod = imp.new_module(fullname) 338 sys.modules[fullname] = mod 339 self.installed.add(fullname) 340 341 mod.__loader__ = self 342 if fullname == 'm5.objects': 343 mod.__path__ = fullname.split('.') 344 return mod 345 346 if fullname == 'm5.defines': 347 mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env) 348 return mod 349 350 source = self.modules[fullname] 351 if source.modname == '__init__': 352 mod.__path__ = source.modpath 353 mod.__file__ = source.abspath 354 355 exec file(source.abspath, 'r') in mod.__dict__ 356 357 return mod 358 359import m5.SimObject 360import m5.params 361from m5.util import code_formatter 362 363m5.SimObject.clear() 364m5.params.clear() 365 366# install the python importer so we can grab stuff from the source 367# tree itself. We can't have SimObjects added after this point or 368# else we won't know about them for the rest of the stuff. 369importer = DictImporter(PySource.modules) 370sys.meta_path[0:0] = [ importer ] 371 372# import all sim objects so we can populate the all_objects list 373# make sure that we're working with a list, then let's sort it 374for modname in SimObject.modnames: 375 exec('from m5.objects import %s' % modname) 376 377# we need to unload all of the currently imported modules so that they 378# will be re-imported the next time the sconscript is run 379importer.unload() 380sys.meta_path.remove(importer) 381 382sim_objects = m5.SimObject.allClasses 383all_enums = m5.params.allEnums 384 385all_params = {} 386for name,obj in sorted(sim_objects.iteritems()): 387 for param in obj._params.local.values(): 388 # load the ptype attribute now because it depends on the 389 # current version of SimObject.allClasses, but when scons 390 # actually uses the value, all versions of 391 # SimObject.allClasses will have been loaded 392 param.ptype 393 394 if not hasattr(param, 'swig_decl'): 395 continue 396 pname = param.ptype_str 397 if pname not in all_params: 398 all_params[pname] = param 399 400######################################################################## 401# 402# calculate extra dependencies 403# 404module_depends = ["m5", "m5.SimObject", "m5.params"] 405depends = [ PySource.modules[dep].snode for dep in module_depends ] 406 407######################################################################## 408# 409# Commands for the basic automatically generated python files 410# 411 412# Generate Python file containing a dict specifying the current 413# buildEnv flags. 414def makeDefinesPyFile(target, source, env): 415 build_env = source[0].get_contents() 416 417 code = code_formatter() 418 code(""" 419import m5.internal 420import m5.util 421 422buildEnv = m5.util.SmartDict($build_env) 423 424compileDate = m5.internal.core.compileDate 425_globals = globals() 426for key,val in m5.internal.core.__dict__.iteritems(): 427 if key.startswith('flag_'): 428 flag = key[5:] 429 _globals[flag] = val 430del _globals 431""") 432 code.write(target[0].abspath) 433 434defines_info = Value(build_env) 435# Generate a file with all of the compile options in it 436env.Command('python/m5/defines.py', defines_info, 437 MakeAction(makeDefinesPyFile, Transform("DEFINES", 0))) 438PySource('m5', 'python/m5/defines.py') 439 440# Generate python file containing info about the M5 source code 441def makeInfoPyFile(target, source, env): 442 code = code_formatter() 443 for src in source: 444 data = ''.join(file(src.srcnode().abspath, 'r').xreadlines()) 445 code('$src = ${{repr(data)}}') 446 code.write(str(target[0])) 447 448# Generate a file that wraps the basic top level files 449env.Command('python/m5/info.py', 450 [ '#/AUTHORS', '#/LICENSE', '#/README', ], 451 MakeAction(makeInfoPyFile, Transform("INFO"))) 452PySource('m5', 'python/m5/info.py') 453 454######################################################################## 455# 456# Create all of the SimObject param headers and enum headers 457# 458 459def createSimObjectParam(target, source, env): 460 assert len(target) == 1 and len(source) == 1 461 462 name = str(source[0].get_contents()) 463 obj = sim_objects[name] 464 465 code = code_formatter() 466 obj.cxx_decl(code) 467 code.write(target[0].abspath) 468 469def createSwigParam(target, source, env): 470 assert len(target) == 1 and len(source) == 1 471 472 name = str(source[0].get_contents()) 473 param = all_params[name] 474 475 code = code_formatter() 476 code('%module(package="m5.internal") $0_${name}', param.file_ext) 477 param.swig_decl(code) 478 code.write(target[0].abspath) 479 480def createEnumStrings(target, source, env): 481 assert len(target) == 1 and len(source) == 1 482 483 name = str(source[0].get_contents()) 484 obj = all_enums[name] 485 486 code = code_formatter() 487 obj.cxx_def(code) 488 code.write(target[0].abspath) 489 490def createEnumParam(target, source, env): 491 assert len(target) == 1 and len(source) == 1 492 493 name = str(source[0].get_contents()) 494 obj = all_enums[name] 495 496 code = code_formatter() 497 obj.cxx_decl(code) 498 code.write(target[0].abspath) 499 500def createEnumSwig(target, source, env): 501 assert len(target) == 1 and len(source) == 1 502 503 name = str(source[0].get_contents()) 504 obj = all_enums[name] 505 506 code = code_formatter() 507 code('''\ 508%module(package="m5.internal") enum_$name 509 510%{ 511#include "enums/$name.hh" 512%} 513 514%include "enums/$name.hh" 515''') 516 code.write(target[0].abspath) 517 518# Generate all of the SimObject param struct header files 519params_hh_files = [] 520for name,simobj in sorted(sim_objects.iteritems()): 521 py_source = PySource.modules[simobj.__module__] 522 extra_deps = [ py_source.tnode ] 523 524 hh_file = File('params/%s.hh' % name) 525 params_hh_files.append(hh_file) 526 env.Command(hh_file, Value(name), 527 MakeAction(createSimObjectParam, Transform("SO PARAM"))) 528 env.Depends(hh_file, depends + extra_deps) 529 530# Generate any parameter header files needed 531params_i_files = [] 532for name,param in all_params.iteritems(): 533 i_file = File('python/m5/internal/%s_%s.i' % (param.file_ext, name)) 534 params_i_files.append(i_file) 535 env.Command(i_file, Value(name), 536 MakeAction(createSwigParam, Transform("SW PARAM"))) 537 env.Depends(i_file, depends) 538 SwigSource('m5.internal', i_file) 539 540# Generate all enum header files 541for name,enum in sorted(all_enums.iteritems()): 542 py_source = PySource.modules[enum.__module__] 543 extra_deps = [ py_source.tnode ] 544 545 cc_file = File('enums/%s.cc' % name) 546 env.Command(cc_file, Value(name), 547 MakeAction(createEnumStrings, Transform("ENUM STR"))) 548 env.Depends(cc_file, depends + extra_deps) 549 Source(cc_file) 550 551 hh_file = File('enums/%s.hh' % name) 552 env.Command(hh_file, Value(name), 553 MakeAction(createEnumParam, Transform("EN PARAM"))) 554 env.Depends(hh_file, depends + extra_deps) 555 556 i_file = File('python/m5/internal/enum_%s.i' % name) 557 env.Command(i_file, Value(name), 558 MakeAction(createEnumSwig, Transform("ENUMSWIG"))) 559 env.Depends(i_file, depends + extra_deps) 560 SwigSource('m5.internal', i_file) 561 562def buildParam(target, source, env): 563 name = source[0].get_contents() 564 obj = sim_objects[name] 565 class_path = obj.cxx_class.split('::') 566 classname = class_path[-1] 567 namespaces = class_path[:-1] 568 params = obj._params.local.values() 569 570 code = code_formatter() 571 572 code('%module(package="m5.internal") param_$name') 573 code() 574 code('%{') 575 code('#include "params/$obj.hh"') 576 for param in params: 577 param.cxx_predecls(code) 578 code('%}') 579 code() 580 581 for param in params: 582 param.swig_predecls(code) 583 584 code() 585 if obj._base: 586 code('%import "python/m5/internal/param_${{obj._base}}.i"') 587 code() 588 obj.swig_objdecls(code) 589 code() 590 591 code('%include "params/$obj.hh"') 592 593 code.write(target[0].abspath) 594 595for name in sim_objects.iterkeys(): 596 params_file = File('python/m5/internal/param_%s.i' % name) 597 env.Command(params_file, Value(name), 598 MakeAction(buildParam, Transform("BLDPARAM"))) 599 env.Depends(params_file, depends) 600 SwigSource('m5.internal', params_file) 601 602# Generate the main swig init file 603def makeEmbeddedSwigInit(target, source, env): 604 code = code_formatter() 605 module = source[0].get_contents() 606 code('''\ 607#include "sim/init.hh" 608 609extern "C" { 610 void init_${module}(); 611} 612 613EmbeddedSwig embed_swig_${module}(init_${module}); 614''') 615 code.write(str(target[0])) 616 617# Build all swig modules 618for swig in SwigSource.all: 619 env.Command([swig.cc_source.tnode, swig.py_source.tnode], swig.tnode, 620 MakeAction('$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} ' 621 '-o ${TARGETS[0]} $SOURCES', Transform("SWIG"))) 622 init_file = 'python/swig/init_%s.cc' % swig.module 623 env.Command(init_file, Value(swig.module), 624 MakeAction(makeEmbeddedSwigInit, Transform("EMBED SW"))) 625 Source(init_file) 626 627# 628# Handle debug flags 629# 630def makeDebugFlagCC(target, source, env): 631 assert(len(target) == 1 and len(source) == 1) 632 633 val = eval(source[0].get_contents()) 634 name, compound, desc = val 635 compound = list(sorted(compound)) 636 637 code = code_formatter() 638 639 # file header 640 code(''' 641/* 642 * DO NOT EDIT THIS FILE! Automatically generated 643 */ 644 645#include "base/debug.hh" 646''') 647 648 for flag in compound: 649 code('#include "debug/$flag.hh"') 650 code() 651 code('namespace Debug {') 652 code() 653 654 if not compound: 655 code('SimpleFlag $name("$name", "$desc");') 656 else: 657 code('CompoundFlag $name("$name", "$desc",') 658 code.indent() 659 last = len(compound) - 1 660 for i,flag in enumerate(compound): 661 if i != last: 662 code('$flag,') 663 else: 664 code('$flag);') 665 code.dedent() 666 667 code() 668 code('} // namespace Debug') 669 670 code.write(str(target[0])) 671 672def makeDebugFlagHH(target, source, env): 673 assert(len(target) == 1 and len(source) == 1) 674 675 val = eval(source[0].get_contents()) 676 name, compound, desc = val 677 678 code = code_formatter() 679 680 # file header boilerplate 681 code('''\ 682/* 683 * DO NOT EDIT THIS FILE! 684 * 685 * Automatically generated by SCons 686 */ 687 688#ifndef __DEBUG_${name}_HH__ 689#define __DEBUG_${name}_HH__ 690 691namespace Debug { 692''') 693 694 if compound: 695 code('class CompoundFlag;') 696 code('class SimpleFlag;') 697 698 if compound: 699 code('extern CompoundFlag $name;') 700 for flag in compound: 701 code('extern SimpleFlag $flag;') 702 else: 703 code('extern SimpleFlag $name;') 704 705 code(''' 706} 707 708#endif // __DEBUG_${name}_HH__ 709''') 710 711 code.write(str(target[0])) 712 713for name,flag in sorted(debug_flags.iteritems()): 714 n, compound, desc = flag 715 assert n == name 716 717 env.Command('debug/%s.hh' % name, Value(flag), 718 MakeAction(makeDebugFlagHH, Transform("TRACING", 0))) 719 env.Command('debug/%s.cc' % name, Value(flag), 720 MakeAction(makeDebugFlagCC, Transform("TRACING", 0))) 721 Source('debug/%s.cc' % name) 722 723# Embed python files. All .py files that have been indicated by a 724# PySource() call in a SConscript need to be embedded into the M5 725# library. To do that, we compile the file to byte code, marshal the 726# byte code, compress it, and then generate a c++ file that 727# inserts the result into an array. 728def embedPyFile(target, source, env): 729 def c_str(string): 730 if string is None: 731 return "0" 732 return '"%s"' % string 733 734 '''Action function to compile a .py into a code object, marshal 735 it, compress it, and stick it into an asm file so the code appears 736 as just bytes with a label in the data section''' 737 738 src = file(str(source[0]), 'r').read() 739 740 pysource = PySource.tnodes[source[0]] 741 compiled = compile(src, pysource.abspath, 'exec') 742 marshalled = marshal.dumps(compiled) 743 compressed = zlib.compress(marshalled) 744 data = compressed 745 sym = pysource.symname 746 747 code = code_formatter() 748 code('''\ 749#include "sim/init.hh" 750 751namespace { 752 753const char data_${sym}[] = { 754''') 755 code.indent() 756 step = 16 757 for i in xrange(0, len(data), step): 758 x = array.array('B', data[i:i+step]) 759 code(''.join('%d,' % d for d in x)) 760 code.dedent() 761 762 code('''}; 763 764EmbeddedPython embedded_${sym}( 765 ${{c_str(pysource.arcname)}}, 766 ${{c_str(pysource.abspath)}}, 767 ${{c_str(pysource.modpath)}}, 768 data_${sym}, 769 ${{len(data)}}, 770 ${{len(marshalled)}}); 771 772} // anonymous namespace 773''') 774 code.write(str(target[0])) 775 776for source in PySource.all: 777 env.Command(source.cpp, source.tnode, 778 MakeAction(embedPyFile, Transform("EMBED PY"))) 779 Source(source.cpp) 780 781######################################################################## 782# 783# Define binaries. Each different build type (debug, opt, etc.) gets 784# a slightly different build environment. 785# 786 787# List of constructed environments to pass back to SConstruct 788envList = [] 789 790date_source = Source('base/date.cc', skip_lib=True) 791 792# Function to create a new build environment as clone of current 793# environment 'env' with modified object suffix and optional stripped 794# binary. Additional keyword arguments are appended to corresponding 795# build environment vars. 796def makeEnv(label, objsfx, strip = False, **kwargs): 797 # SCons doesn't know to append a library suffix when there is a '.' in the 798 # name. Use '_' instead. 799 libname = 'm5_' + label 800 exename = 'm5.' + label 801 802 new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's') 803 new_env.Label = label 804 new_env.Append(**kwargs) 805 806 swig_env = new_env.Clone() 807 swig_env.Append(CCFLAGS='-Werror') 808 if env['GCC']: 809 swig_env.Append(CCFLAGS='-Wno-uninitialized') 810 swig_env.Append(CCFLAGS='-Wno-sign-compare') 811 swig_env.Append(CCFLAGS='-Wno-parentheses') 812 813 werror_env = new_env.Clone() 814 werror_env.Append(CCFLAGS='-Werror') 815 816 def make_obj(source, static, extra_deps = None): 817 '''This function adds the specified source to the correct 818 build environment, and returns the corresponding SCons Object 819 nodes''' 820 821 if source.swig: 822 env = swig_env 823 elif source.Werror: 824 env = werror_env 825 else: 826 env = new_env 827 828 if static: 829 obj = env.StaticObject(source.tnode) 830 else: 831 obj = env.SharedObject(source.tnode) 832 833 if extra_deps: 834 env.Depends(obj, extra_deps) 835 836 return obj 837 838 static_objs = [ make_obj(s, True) for s in Source.get(skip_lib=False)] 839 shared_objs = [ make_obj(s, False) for s in Source.get(skip_lib=False)] 840 841 static_date = make_obj(date_source, static=True, extra_deps=static_objs) 842 static_objs.append(static_date) 843 844 shared_date = make_obj(date_source, static=False, extra_deps=shared_objs) 845 shared_objs.append(shared_date) 846 847 # First make a library of everything but main() so other programs can 848 # link against m5. 849 static_lib = new_env.StaticLibrary(libname, static_objs) 850 shared_lib = new_env.SharedLibrary(libname, shared_objs) 851 852 for target, sources in unit_tests: 853 objs = [ make_obj(s, static=True) for s in sources ] 854 new_env.Program("unittest/%s.%s" % (target, label), objs + static_objs) 855 856 # Now link a stub with main() and the static library. 857 bin_objs = [make_obj(s, True) for s in Source.get(bin_only=True) ] 858 progname = exename 859 if strip: 860 progname += '.unstripped' 861 862 targets = new_env.Program(progname, bin_objs + static_objs) 863 864 if strip: 865 if sys.platform == 'sunos5': 866 cmd = 'cp $SOURCE $TARGET; strip $TARGET' 867 else: 868 cmd = 'strip $SOURCE -o $TARGET' 869 targets = new_env.Command(exename, progname, 870 MakeAction(cmd, Transform("STRIP"))) 871 872 new_env.M5Binary = targets[0] 873 envList.append(new_env) 874 875# Debug binary 876ccflags = {} 877if env['GCC']: 878 if sys.platform == 'sunos5': 879 ccflags['debug'] = '-gstabs+' 880 else: 881 ccflags['debug'] = '-ggdb3' 882 ccflags['opt'] = '-g -O3' 883 ccflags['fast'] = '-O3' 884 ccflags['prof'] = '-O3 -g -pg' 885elif env['SUNCC']: 886 ccflags['debug'] = '-g0' 887 ccflags['opt'] = '-g -O' 888 ccflags['fast'] = '-fast' 889 ccflags['prof'] = '-fast -g -pg' 890elif env['ICC']: 891 ccflags['debug'] = '-g -O0' 892 ccflags['opt'] = '-g -O' 893 ccflags['fast'] = '-fast' 894 ccflags['prof'] = '-fast -g -pg' 895else: 896 print 'Unknown compiler, please fix compiler options' 897 Exit(1) 898 899makeEnv('debug', '.do', 900 CCFLAGS = Split(ccflags['debug']), 901 CPPDEFINES = ['DEBUG', 'TRACING_ON=1']) 902 903# Optimized binary 904makeEnv('opt', '.o', 905 CCFLAGS = Split(ccflags['opt']), 906 CPPDEFINES = ['TRACING_ON=1']) 907 908# "Fast" binary 909makeEnv('fast', '.fo', strip = True, 910 CCFLAGS = Split(ccflags['fast']), 911 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0']) 912 913# Profiled binary 914makeEnv('prof', '.po', 915 CCFLAGS = Split(ccflags['prof']), 916 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 917 LINKFLAGS = '-pg') 918 919Return('envList') 920