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