3 # Copyright (c) 2004-2005 The Regents of The University of Michigan
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.
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.
29 # Authors: Nathan Binkert
40 from os.path import basename, dirname, exists, isdir, isfile, join as joinpath
44 # This file defines how to build a particular configuration of gem5
45 # based on variable settings in the 'env' build environment.
49 # Children need to see the environment
52 build_env = [(opt, env[opt]) for opt in export_vars]
54 from m5.util import code_formatter, compareVersions
56 ########################################################################
57 # Code for adding source files of various types
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 gem5 main() function
65 # skip_lib -- do not put this file into the gem5 library
66 # <unittest> -- unit tests use filters based on the unit test name
68 # A parent can now be specified for a source file and default filter
69 # values will be retrieved recursively from parents (children override
72 class 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)
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'''
84 for flag,value in guards.iteritems():
85 # if the flag is found and has a different value, skip
87 if src.all_guards.get(flag, False) != value:
92 class 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):
104 if not isinstance(source, SCons.Node.FS.File):
108 self.snode = tnode.srcnode()
110 for base in type(self).__mro__:
111 if issubclass(base, SourceFile):
112 base.all.append(self)
116 return str(self.tnode)
120 return dirname(self.filename)
124 return basename(self.filename)
128 index = self.basename.rfind('.')
130 # dot files aren't extensions
131 return self.basename, None
133 return self.basename[:index], self.basename[index+1:]
136 def all_guards(self):
137 '''find all guards for this object getting default values
138 recursively from its parents'''
141 guards.update(self.parent.guards)
142 guards.update(self.guards)
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
152 class 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)
161 class PySource(SourceFile):
162 '''Add a python source file to the named package'''
163 invalid_sym_char = re.compile('[^A-z0-9_]')
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)
172 modname,ext = self.extname
176 path = package.split('.')
181 if modname != '__init__':
182 modpath += [ modname ]
183 modpath = '.'.join(modpath)
185 arcpath = path + [ self.basename ]
186 abspath = self.snode.abspath
187 if not exists(abspath):
188 abspath = self.tnode.abspath
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)
199 PySource.modules[modpath] = self
200 PySource.tnodes[self.tnode] = self
201 PySource.symnames[self.symname] = self
203 class SimObject(PySource):
204 '''Add a SimObject python file as a python source object and add
205 it to a list of sim object modules'''
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)
215 raise AttributeError, "Too late to call SimObject now."
217 bisect.insort_right(SimObject.modnames, self.modname)
219 class SwigSource(SourceFile):
220 '''Add a swig file to build'''
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)
226 modname,ext = self.extname
229 self.module = modname
230 cc_file = joinpath(self.dirname, modname + '_wrap.cc')
231 py_file = joinpath(self.dirname, modname + '.py')
233 self.cc_source = Source(cc_file, swig=True, parent=self)
234 self.py_source = PySource(package, py_file, parent=self)
236 class UnitTest(object):
237 '''Create a UnitTest'''
240 def __init__(self, target, *sources):
241 '''Specify the target name and any sources. Sources that are
242 not SourceFiles are evalued with Source(). All files are
243 guarded with a guard of the same name as the UnitTest
248 if not isinstance(src, SourceFile):
249 src = Source(src, skip_lib=True)
250 src.guards[target] = True
255 UnitTest.all.append(self)
257 # Children should have access
264 ########################################################################
269 def DebugFlag(name, desc=None):
270 if name in debug_flags:
271 raise AttributeError, "Flag %s already specified" % name
272 debug_flags[name] = (name, (), desc)
274 def CompoundFlag(name, flags, desc=None):
275 if name in debug_flags:
276 raise AttributeError, "Flag %s already specified" % name
278 compound = tuple(flags)
279 debug_flags[name] = (name, compound, desc)
282 Export('CompoundFlag')
284 ########################################################################
286 # Set some compiler variables
289 # Include file paths are rooted in this directory. SCons will
290 # automatically expand '.' to refer to both the source directory and
291 # the corresponding build directory to pick up generated include
293 env.Append(CPPPATH=Dir('.'))
295 for extra_dir in extras_dir_list:
296 env.Append(CPPPATH=Dir(extra_dir))
298 # Workaround for bug in SCons version > 0.97d20071212
299 # Scons bug id: 2006 gem5 Bug id: 308
300 for root, dirs, files in os.walk(base_dir, topdown=True):
301 Dir(root[len(base_dir) + 1:])
303 ########################################################################
305 # Walk the tree and execute all SConscripts in subdirectories
308 here = Dir('.').srcnode().abspath
309 for root, dirs, files in os.walk(base_dir, topdown=True):
311 # we don't want to recurse back into this SConscript
314 if 'SConscript' in files:
315 build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:])
316 SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir)
318 for extra_dir in extras_dir_list:
319 prefix_len = len(dirname(extra_dir)) + 1
320 for root, dirs, files in os.walk(extra_dir, topdown=True):
321 # if build lives in the extras directory, don't walk down it
325 if 'SConscript' in files:
326 build_dir = joinpath(env['BUILDDIR'], root[prefix_len:])
327 SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir)
329 for opt in export_vars:
332 def makeTheISA(source, target, env):
333 isas = [ src.get_contents() for src in source ]
334 target_isa = env['TARGET_ISA']
336 return isa.upper() + '_ISA'
339 return isa[0].upper() + isa[1:].lower() + 'ISA'
342 code = code_formatter()
344 #ifndef __CONFIG_THE_ISA_HH__
345 #define __CONFIG_THE_ISA_HH__
349 for i,isa in enumerate(isas):
350 code('#define $0 $1', define(isa), i + 1)
354 #define THE_ISA ${{define(target_isa)}}
355 #define TheISA ${{namespace(target_isa)}}
357 #endif // __CONFIG_THE_ISA_HH__''')
359 code.write(str(target[0]))
361 env.Command('config/the_isa.hh', map(Value, all_isa_list),
362 MakeAction(makeTheISA, Transform("CFG ISA", 0)))
364 ########################################################################
366 # Prevent any SimObjects from being added after this point, they
367 # should all have been added in the SConscripts above
369 SimObject.fixed = True
371 class DictImporter(object):
372 '''This importer takes a dictionary of arbitrary module names that
373 map to arbitrary filenames.'''
374 def __init__(self, modules):
375 self.modules = modules
376 self.installed = set()
383 for module in self.installed:
384 del sys.modules[module]
385 self.installed = set()
387 def find_module(self, fullname, path):
388 if fullname == 'm5.defines':
391 if fullname == 'm5.objects':
394 if fullname.startswith('m5.internal'):
397 source = self.modules.get(fullname, None)
398 if source is not None and fullname.startswith('m5.objects'):
403 def load_module(self, fullname):
404 mod = imp.new_module(fullname)
405 sys.modules[fullname] = mod
406 self.installed.add(fullname)
408 mod.__loader__ = self
409 if fullname == 'm5.objects':
410 mod.__path__ = fullname.split('.')
413 if fullname == 'm5.defines':
414 mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env)
417 source = self.modules[fullname]
418 if source.modname == '__init__':
419 mod.__path__ = source.modpath
420 mod.__file__ = source.abspath
422 exec file(source.abspath, 'r') in mod.__dict__
428 from m5.util import code_formatter
433 # install the python importer so we can grab stuff from the source
434 # tree itself. We can't have SimObjects added after this point or
435 # else we won't know about them for the rest of the stuff.
436 importer = DictImporter(PySource.modules)
437 sys.meta_path[0:0] = [ importer ]
439 # import all sim objects so we can populate the all_objects list
440 # make sure that we're working with a list, then let's sort it
441 for modname in SimObject.modnames:
442 exec('from m5.objects import %s' % modname)
444 # we need to unload all of the currently imported modules so that they
445 # will be re-imported the next time the sconscript is run
447 sys.meta_path.remove(importer)
449 sim_objects = m5.SimObject.allClasses
450 all_enums = m5.params.allEnums
452 # Find param types that need to be explicitly wrapped with swig.
453 # These will be recognized because the ParamDesc will have a
454 # swig_decl() method. Most param types are based on types that don't
455 # need this, either because they're based on native types (like Int)
456 # or because they're SimObjects (which get swigged independently).
457 # For now the only things handled here are VectorParam types.
459 for name,obj in sorted(sim_objects.iteritems()):
460 for param in obj._params.local.values():
461 # load the ptype attribute now because it depends on the
462 # current version of SimObject.allClasses, but when scons
463 # actually uses the value, all versions of
464 # SimObject.allClasses will have been loaded
467 if not hasattr(param, 'swig_decl'):
469 pname = param.ptype_str
470 if pname not in params_to_swig:
471 params_to_swig[pname] = param
473 ########################################################################
475 # calculate extra dependencies
477 module_depends = ["m5", "m5.SimObject", "m5.params"]
478 depends = [ PySource.modules[dep].snode for dep in module_depends ]
480 ########################################################################
482 # Commands for the basic automatically generated python files
485 # Generate Python file containing a dict specifying the current
487 def makeDefinesPyFile(target, source, env):
488 build_env = source[0].get_contents()
490 code = code_formatter()
495 buildEnv = m5.util.SmartDict($build_env)
497 compileDate = m5.internal.core.compileDate
499 for key,val in m5.internal.core.__dict__.iteritems():
500 if key.startswith('flag_'):
505 code.write(target[0].abspath)
507 defines_info = Value(build_env)
508 # Generate a file with all of the compile options in it
509 env.Command('python/m5/defines.py', defines_info,
510 MakeAction(makeDefinesPyFile, Transform("DEFINES", 0)))
511 PySource('m5', 'python/m5/defines.py')
513 # Generate python file containing info about the M5 source code
514 def makeInfoPyFile(target, source, env):
515 code = code_formatter()
517 data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
518 code('$src = ${{repr(data)}}')
519 code.write(str(target[0]))
521 # Generate a file that wraps the basic top level files
522 env.Command('python/m5/info.py',
523 [ '#/COPYING', '#/LICENSE', '#/README', ],
524 MakeAction(makeInfoPyFile, Transform("INFO")))
525 PySource('m5', 'python/m5/info.py')
527 ########################################################################
529 # Create all of the SimObject param headers and enum headers
532 def createSimObjectParamStruct(target, source, env):
533 assert len(target) == 1 and len(source) == 1
535 name = str(source[0].get_contents())
536 obj = sim_objects[name]
538 code = code_formatter()
539 obj.cxx_param_decl(code)
540 code.write(target[0].abspath)
542 def createParamSwigWrapper(target, source, env):
543 assert len(target) == 1 and len(source) == 1
545 name = str(source[0].get_contents())
546 param = params_to_swig[name]
548 code = code_formatter()
549 param.swig_decl(code)
550 code.write(target[0].abspath)
552 def createEnumStrings(target, source, env):
553 assert len(target) == 1 and len(source) == 1
555 name = str(source[0].get_contents())
556 obj = all_enums[name]
558 code = code_formatter()
560 code.write(target[0].abspath)
562 def createEnumDecls(target, source, env):
563 assert len(target) == 1 and len(source) == 1
565 name = str(source[0].get_contents())
566 obj = all_enums[name]
568 code = code_formatter()
570 code.write(target[0].abspath)
572 def createEnumSwigWrapper(target, source, env):
573 assert len(target) == 1 and len(source) == 1
575 name = str(source[0].get_contents())
576 obj = all_enums[name]
578 code = code_formatter()
580 code.write(target[0].abspath)
582 def createSimObjectSwigWrapper(target, source, env):
583 name = source[0].get_contents()
584 obj = sim_objects[name]
586 code = code_formatter()
588 code.write(target[0].abspath)
590 # Generate all of the SimObject param C++ struct header files
592 for name,simobj in sorted(sim_objects.iteritems()):
593 py_source = PySource.modules[simobj.__module__]
594 extra_deps = [ py_source.tnode ]
596 hh_file = File('params/%s.hh' % name)
597 params_hh_files.append(hh_file)
598 env.Command(hh_file, Value(name),
599 MakeAction(createSimObjectParamStruct, Transform("SO PARAM")))
600 env.Depends(hh_file, depends + extra_deps)
602 # Generate any needed param SWIG wrapper files
604 for name,param in params_to_swig.iteritems():
605 i_file = File('python/m5/internal/%s.i' % (param.swig_module_name()))
606 params_i_files.append(i_file)
607 env.Command(i_file, Value(name),
608 MakeAction(createParamSwigWrapper, Transform("SW PARAM")))
609 env.Depends(i_file, depends)
610 SwigSource('m5.internal', i_file)
612 # Generate all enum header files
613 for name,enum in sorted(all_enums.iteritems()):
614 py_source = PySource.modules[enum.__module__]
615 extra_deps = [ py_source.tnode ]
617 cc_file = File('enums/%s.cc' % name)
618 env.Command(cc_file, Value(name),
619 MakeAction(createEnumStrings, Transform("ENUM STR")))
620 env.Depends(cc_file, depends + extra_deps)
623 hh_file = File('enums/%s.hh' % name)
624 env.Command(hh_file, Value(name),
625 MakeAction(createEnumDecls, Transform("ENUMDECL")))
626 env.Depends(hh_file, depends + extra_deps)
628 i_file = File('python/m5/internal/enum_%s.i' % name)
629 env.Command(i_file, Value(name),
630 MakeAction(createEnumSwigWrapper, Transform("ENUMSWIG")))
631 env.Depends(i_file, depends + extra_deps)
632 SwigSource('m5.internal', i_file)
634 # Generate SimObject SWIG wrapper files
635 for name in sim_objects.iterkeys():
636 i_file = File('python/m5/internal/param_%s.i' % name)
637 env.Command(i_file, Value(name),
638 MakeAction(createSimObjectSwigWrapper, Transform("SO SWIG")))
639 env.Depends(i_file, depends)
640 SwigSource('m5.internal', i_file)
642 # Generate the main swig init file
643 def makeEmbeddedSwigInit(target, source, env):
644 code = code_formatter()
645 module = source[0].get_contents()
647 #include "sim/init.hh"
650 void init_${module}();
653 EmbeddedSwig embed_swig_${module}(init_${module});
655 code.write(str(target[0]))
657 # Build all swig modules
658 for swig in SwigSource.all:
659 env.Command([swig.cc_source.tnode, swig.py_source.tnode], swig.tnode,
660 MakeAction('$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
661 '-o ${TARGETS[0]} $SOURCES', Transform("SWIG")))
662 cc_file = str(swig.tnode)
663 init_file = '%s/%s_init.cc' % (dirname(cc_file), basename(cc_file))
664 env.Command(init_file, Value(swig.module),
665 MakeAction(makeEmbeddedSwigInit, Transform("EMBED SW")))
666 Source(init_file, **swig.guards)
671 def makeDebugFlagCC(target, source, env):
672 assert(len(target) == 1 and len(source) == 1)
674 val = eval(source[0].get_contents())
675 name, compound, desc = val
676 compound = list(sorted(compound))
678 code = code_formatter()
683 * DO NOT EDIT THIS FILE! Automatically generated
686 #include "base/debug.hh"
689 for flag in compound:
690 code('#include "debug/$flag.hh"')
692 code('namespace Debug {')
696 code('SimpleFlag $name("$name", "$desc");')
698 code('CompoundFlag $name("$name", "$desc",')
700 last = len(compound) - 1
701 for i,flag in enumerate(compound):
709 code('} // namespace Debug')
711 code.write(str(target[0]))
713 def makeDebugFlagHH(target, source, env):
714 assert(len(target) == 1 and len(source) == 1)
716 val = eval(source[0].get_contents())
717 name, compound, desc = val
719 code = code_formatter()
721 # file header boilerplate
724 * DO NOT EDIT THIS FILE!
726 * Automatically generated by SCons
729 #ifndef __DEBUG_${name}_HH__
730 #define __DEBUG_${name}_HH__
736 code('class CompoundFlag;')
737 code('class SimpleFlag;')
740 code('extern CompoundFlag $name;')
741 for flag in compound:
742 code('extern SimpleFlag $flag;')
744 code('extern SimpleFlag $name;')
749 #endif // __DEBUG_${name}_HH__
752 code.write(str(target[0]))
754 for name,flag in sorted(debug_flags.iteritems()):
755 n, compound, desc = flag
758 env.Command('debug/%s.hh' % name, Value(flag),
759 MakeAction(makeDebugFlagHH, Transform("TRACING", 0)))
760 env.Command('debug/%s.cc' % name, Value(flag),
761 MakeAction(makeDebugFlagCC, Transform("TRACING", 0)))
762 Source('debug/%s.cc' % name)
764 # Embed python files. All .py files that have been indicated by a
765 # PySource() call in a SConscript need to be embedded into the M5
766 # library. To do that, we compile the file to byte code, marshal the
767 # byte code, compress it, and then generate a c++ file that
768 # inserts the result into an array.
769 def embedPyFile(target, source, env):
773 return '"%s"' % string
775 '''Action function to compile a .py into a code object, marshal
776 it, compress it, and stick it into an asm file so the code appears
777 as just bytes with a label in the data section'''
779 src = file(str(source[0]), 'r').read()
781 pysource = PySource.tnodes[source[0]]
782 compiled = compile(src, pysource.abspath, 'exec')
783 marshalled = marshal.dumps(compiled)
784 compressed = zlib.compress(marshalled)
786 sym = pysource.symname
788 code = code_formatter()
790 #include "sim/init.hh"
794 const char data_${sym}[] = {
798 for i in xrange(0, len(data), step):
799 x = array.array('B', data[i:i+step])
800 code(''.join('%d,' % d for d in x))
805 EmbeddedPython embedded_${sym}(
806 ${{c_str(pysource.arcname)}},
807 ${{c_str(pysource.abspath)}},
808 ${{c_str(pysource.modpath)}},
811 ${{len(marshalled)}});
813 } // anonymous namespace
815 code.write(str(target[0]))
817 for source in PySource.all:
818 env.Command(source.cpp, source.tnode,
819 MakeAction(embedPyFile, Transform("EMBED PY")))
822 ########################################################################
824 # Define binaries. Each different build type (debug, opt, etc.) gets
825 # a slightly different build environment.
828 # List of constructed environments to pass back to SConstruct
831 date_source = Source('base/date.cc', skip_lib=True)
833 # Function to create a new build environment as clone of current
834 # environment 'env' with modified object suffix and optional stripped
835 # binary. Additional keyword arguments are appended to corresponding
836 # build environment vars.
837 def makeEnv(label, objsfx, strip = False, **kwargs):
838 # SCons doesn't know to append a library suffix when there is a '.' in the
839 # name. Use '_' instead.
840 libname = 'gem5_' + label
841 exename = 'gem5.' + label
842 secondary_exename = 'm5.' + label
844 new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's')
845 new_env.Label = label
846 new_env.Append(**kwargs)
848 swig_env = new_env.Clone()
849 swig_env.Append(CCFLAGS='-Werror')
851 swig_env.Append(CCFLAGS='-Wno-uninitialized')
852 swig_env.Append(CCFLAGS='-Wno-sign-compare')
853 swig_env.Append(CCFLAGS='-Wno-parentheses')
854 swig_env.Append(CCFLAGS='-Wno-unused-label')
855 if compareVersions(env['GCC_VERSION'], '4.6.0') != -1:
856 swig_env.Append(CCFLAGS='-Wno-unused-but-set-variable')
858 werror_env = new_env.Clone()
859 werror_env.Append(CCFLAGS='-Werror')
861 def make_obj(source, static, extra_deps = None):
862 '''This function adds the specified source to the correct
863 build environment, and returns the corresponding SCons Object
874 obj = env.StaticObject(source.tnode)
876 obj = env.SharedObject(source.tnode)
879 env.Depends(obj, extra_deps)
884 [ make_obj(s, True) for s in Source.get(main=False, skip_lib=False) ]
886 [ make_obj(s, False) for s in Source.get(main=False, skip_lib=False) ]
888 static_date = make_obj(date_source, static=True, extra_deps=static_objs)
889 static_objs.append(static_date)
891 shared_date = make_obj(date_source, static=False, extra_deps=shared_objs)
892 shared_objs.append(shared_date)
894 # First make a library of everything but main() so other programs can
896 static_lib = new_env.StaticLibrary(libname, static_objs)
897 shared_lib = new_env.SharedLibrary(libname, shared_objs)
899 # Now link a stub with main() and the static library.
900 main_objs = [ make_obj(s, True) for s in Source.get(main=True) ]
902 for test in UnitTest.all:
903 flags = { test.target : True }
904 test_sources = Source.get(**flags)
905 test_objs = [ make_obj(s, static=True) for s in test_sources ]
906 testname = "unittest/%s.%s" % (test.target, label)
907 new_env.Program(testname, main_objs + test_objs + static_objs)
911 progname += '.unstripped'
913 targets = new_env.Program(progname, main_objs + static_objs)
916 if sys.platform == 'sunos5':
917 cmd = 'cp $SOURCE $TARGET; strip $TARGET'
919 cmd = 'strip $SOURCE -o $TARGET'
920 targets = new_env.Command(exename, progname,
921 MakeAction(cmd, Transform("STRIP")))
923 new_env.Command(secondary_exename, exename,
924 MakeAction('ln $SOURCE $TARGET', Transform("HARDLINK")))
926 new_env.M5Binary = targets[0]
927 envList.append(new_env)
932 if sys.platform == 'sunos5':
933 ccflags['debug'] = '-gstabs+'
935 ccflags['debug'] = '-ggdb3'
936 ccflags['opt'] = '-g -O3'
937 ccflags['fast'] = '-O3'
938 ccflags['prof'] = '-O3 -g -pg'
940 ccflags['debug'] = '-g0'
941 ccflags['opt'] = '-g -O'
942 ccflags['fast'] = '-fast'
943 ccflags['prof'] = '-fast -g -pg'
945 ccflags['debug'] = '-g -O0'
946 ccflags['opt'] = '-g -O'
947 ccflags['fast'] = '-fast'
948 ccflags['prof'] = '-fast -g -pg'
950 print 'Unknown compiler, please fix compiler options'
953 makeEnv('debug', '.do',
954 CCFLAGS = Split(ccflags['debug']),
955 CPPDEFINES = ['DEBUG', 'TRACING_ON=1'])
959 CCFLAGS = Split(ccflags['opt']),
960 CPPDEFINES = ['TRACING_ON=1'])
963 makeEnv('fast', '.fo', strip = True,
964 CCFLAGS = Split(ccflags['fast']),
965 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'])
968 makeEnv('prof', '.po',
969 CCFLAGS = Split(ccflags['prof']),
970 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],