SConscript (5518:70caf53d9d7c) SConscript (5522:e56c3d89be79)
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

--- 14 unchanged lines hidden (view full) ---

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
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

--- 14 unchanged lines hidden (view full) ---

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
31import imp
32import imp
33import marshal
32import os
34import os
33import py_compile
35import re
34import sys
36import sys
35import zipfile
37import zlib
36
37from os.path import basename, exists, isdir, isfile, join as joinpath
38
39import SCons
40
41# This file defines how to build a particular configuration of M5
42# based on variable settings in the 'env' build environment.
43

--- 9 unchanged lines hidden (view full) ---

53 if isinstance(_list, list):
54 _list = _list[:]
55 else:
56 _list = list(_list)
57 _list.sort()
58 return _list
59
60class PySourceFile(object):
38
39from os.path import basename, exists, isdir, isfile, join as joinpath
40
41import SCons
42
43# This file defines how to build a particular configuration of M5
44# based on variable settings in the 'env' build environment.
45

--- 9 unchanged lines hidden (view full) ---

55 if isinstance(_list, list):
56 _list = _list[:]
57 else:
58 _list = list(_list)
59 _list.sort()
60 return _list
61
62class PySourceFile(object):
63 invalid_sym_char = re.compile('[^A-z0-9_]')
61 def __init__(self, package, source):
62 filename = str(source)
63 pyname = basename(filename)
64 assert pyname.endswith('.py')
65 name = pyname[:-3]
64 def __init__(self, package, source):
65 filename = str(source)
66 pyname = basename(filename)
67 assert pyname.endswith('.py')
68 name = pyname[:-3]
66 path = package.split('.')
69 if package:
70 path = package.split('.')
71 else:
72 path = []
67 modpath = path
68 if name != '__init__':
69 modpath += [name]
70 modpath = '.'.join(modpath)
71
73 modpath = path
74 if name != '__init__':
75 modpath += [name]
76 modpath = '.'.join(modpath)
77
72 arcpath = package.split('.') + [ pyname + 'c' ]
78 arcpath = path + [ pyname ]
73 arcname = joinpath(*arcpath)
74
79 arcname = joinpath(*arcpath)
80
75 self.source = source
81 self.tnode = source
82 self.snode = source.srcnode()
76 self.pyname = pyname
83 self.pyname = pyname
77 self.srcpath = source.srcnode().abspath
78 self.package = package
79 self.modpath = modpath
80 self.arcname = arcname
81 self.filename = filename
82 self.compiled = File(filename + 'c')
84 self.package = package
85 self.modpath = modpath
86 self.arcname = arcname
87 self.filename = filename
88 self.compiled = File(filename + 'c')
89 self.assembly = File(filename + '.s')
90 self.symname = "PyEMB_" + self.invalid_sym_char.sub('_', modpath)
91
83
84########################################################################
85# Code for adding source files of various types
86#
92
93########################################################################
94# Code for adding source files of various types
95#
87cc_sources = []
96cc_lib_sources = []
88def Source(source):
97def Source(source):
89 '''Add a C/C++ source file to the build'''
98 '''Add a source file to the libm5 build'''
90 if not isinstance(source, SCons.Node.FS.File):
91 source = File(source)
92
99 if not isinstance(source, SCons.Node.FS.File):
100 source = File(source)
101
93 cc_sources.append(source)
102 cc_lib_sources.append(source)
94
103
104cc_bin_sources = []
105def BinSource(source):
106 '''Add a source file to the m5 binary build'''
107 if not isinstance(source, SCons.Node.FS.File):
108 source = File(source)
109
110 cc_bin_sources.append(source)
111
95py_sources = []
96def PySource(package, source):
97 '''Add a python source file to the named package'''
98 if not isinstance(source, SCons.Node.FS.File):
99 source = File(source)
100
101 source = PySourceFile(package, source)
102 py_sources.append(source)

--- 21 unchanged lines hidden (view full) ---

124 '''Add a swig file to build'''
125 if not isinstance(source, SCons.Node.FS.File):
126 source = File(source)
127 val = source,package
128 swig_sources.append(val)
129
130# Children should have access
131Export('Source')
112py_sources = []
113def PySource(package, source):
114 '''Add a python source file to the named package'''
115 if not isinstance(source, SCons.Node.FS.File):
116 source = File(source)
117
118 source = PySourceFile(package, source)
119 py_sources.append(source)

--- 21 unchanged lines hidden (view full) ---

141 '''Add a swig file to build'''
142 if not isinstance(source, SCons.Node.FS.File):
143 source = File(source)
144 val = source,package
145 swig_sources.append(val)
146
147# Children should have access
148Export('Source')
149Export('BinSource')
132Export('PySource')
133Export('SimObject')
134Export('SwigSource')
135
136########################################################################
137#
138# Trace Flags
139#

--- 114 unchanged lines hidden (view full) ---

254 mod.__file__ = srcfile
255
256 exec file(srcfile, 'r') in mod.__dict__
257
258 return mod
259
260py_modules = {}
261for source in py_sources:
150Export('PySource')
151Export('SimObject')
152Export('SwigSource')
153
154########################################################################
155#
156# Trace Flags
157#

--- 114 unchanged lines hidden (view full) ---

272 mod.__file__ = srcfile
273
274 exec file(srcfile, 'r') in mod.__dict__
275
276 return mod
277
278py_modules = {}
279for source in py_sources:
262 py_modules[source.modpath] = source.srcpath
280 py_modules[source.modpath] = source.snode.abspath
263
264# install the python importer so we can grab stuff from the source
265# tree itself. We can't have SimObjects added after this point or
266# else we won't know about them for the rest of the stuff.
267sim_objects_fixed = True
268importer = DictImporter(py_modules)
269sys.meta_path[0:0] = [ importer ]
270

--- 275 unchanged lines hidden (view full) ---

546
547# Generate the main swig init file
548def makeSwigInit(target, source, env):
549 f = file(str(target[0]), 'w')
550 print >>f, 'extern "C" {'
551 for module in source:
552 print >>f, ' void init_%s();' % module.get_contents()
553 print >>f, '}'
281
282# install the python importer so we can grab stuff from the source
283# tree itself. We can't have SimObjects added after this point or
284# else we won't know about them for the rest of the stuff.
285sim_objects_fixed = True
286importer = DictImporter(py_modules)
287sys.meta_path[0:0] = [ importer ]
288

--- 275 unchanged lines hidden (view full) ---

564
565# Generate the main swig init file
566def makeSwigInit(target, source, env):
567 f = file(str(target[0]), 'w')
568 print >>f, 'extern "C" {'
569 for module in source:
570 print >>f, ' void init_%s();' % module.get_contents()
571 print >>f, '}'
554 print >>f, 'void init_swig() {'
572 print >>f, 'void initSwig() {'
555 for module in source:
556 print >>f, ' init_%s();' % module.get_contents()
557 print >>f, '}'
558 f.close()
559
573 for module in source:
574 print >>f, ' init_%s();' % module.get_contents()
575 print >>f, '}'
576 f.close()
577
560env.Command('swig/init.cc', swig_modules, makeSwigInit)
561Source('swig/init.cc')
578env.Command('python/swig/init.cc', swig_modules, makeSwigInit)
579Source('python/swig/init.cc')
562
563# Generate traceflags.py
564def traceFlagsPy(target, source, env):
565 assert(len(target) == 1)
566
567 f = file(str(target[0]), 'w')
568
569 allFlags = []

--- 222 unchanged lines hidden (view full) ---

792 print "in except"
793 gen_file(target, "Unknown", "Unknown", "Unknown")
794 mercurial.demandimport.disable()
795
796env.Command('base/program_info.cc',
797 Value(str(SCons.Node.FS.default_fs.SConstruct_dir)),
798 programInfo)
799
580
581# Generate traceflags.py
582def traceFlagsPy(target, source, env):
583 assert(len(target) == 1)
584
585 f = file(str(target[0]), 'w')
586
587 allFlags = []

--- 222 unchanged lines hidden (view full) ---

810 print "in except"
811 gen_file(target, "Unknown", "Unknown", "Unknown")
812 mercurial.demandimport.disable()
813
814env.Command('base/program_info.cc',
815 Value(str(SCons.Node.FS.default_fs.SConstruct_dir)),
816 programInfo)
817
800# Build the zip file
801def compilePyFile(target, source, env):
802 '''Action function to compile a .py into a .pyc'''
803 py_compile.compile(str(source[0]), str(target[0]))
818# embed python files. All .py files that have been indicated by a
819# PySource() call in a SConscript need to be embedded into the M5
820# library. To do that, we compile the file to byte code, marshal the
821# byte code, compress it, and then generate an assembly file that
822# inserts the result into the data section with symbols indicating the
823# beginning, and end (and with the size at the end)
824py_sources_tnodes = {}
825for pysource in py_sources:
826 py_sources_tnodes[pysource.tnode] = pysource
804
827
805def buildPyZip(target, source, env):
806 '''Action function to build the zip archive. Uses the
807 PyZipFile module included in the standard Python library.'''
828def objectifyPyFile(target, source, env):
829 '''Action function to compile a .py into a code object, marshal
830 it, compress it, and stick it into an asm file so the code appears
831 as just bytes with a label in the data section'''
808
832
809 py_compiled = {}
810 for s in py_sources:
811 compname = str(s.compiled)
812 assert compname not in py_compiled
813 py_compiled[compname] = s
833 src = file(str(source[0]), 'r').read()
834 dst = file(str(target[0]), 'w')
814
835
815 zf = zipfile.ZipFile(str(target[0]), 'w')
816 for s in source:
817 zipname = str(s)
818 arcname = py_compiled[zipname].arcname
819 zf.write(zipname, arcname)
820 zf.close()
836 pysource = py_sources_tnodes[source[0]]
837 compiled = compile(src, pysource.snode.path, 'exec')
838 marshalled = marshal.dumps(compiled)
839 compressed = zlib.compress(marshalled)
840 data = compressed
821
841
822py_compiled = []
823py_zip_depends = []
842 # Some C/C++ compilers prepend an underscore to global symbol
843 # names, so if they're going to do that, we need to prepend that
844 # leading underscore to globals in the assembly file.
845 if env['LEADING_UNDERSCORE']:
846 sym = '_' + pysource.symname
847 else:
848 sym = pysource.symname
849
850 step = 16
851 print >>dst, ".data"
852 print >>dst, ".globl %s_beg" % sym
853 print >>dst, ".globl %s_end" % sym
854 print >>dst, "%s_beg:" % sym
855 for i in xrange(0, len(data), step):
856 x = array.array('B', data[i:i+step])
857 print >>dst, ".byte", ','.join([str(d) for d in x])
858 print >>dst, "%s_end:" % sym
859 print >>dst, ".long %d" % len(marshalled)
860
824for source in py_sources:
861for source in py_sources:
825 env.Command(source.compiled, source.source, compilePyFile)
826 py_compiled.append(source.compiled)
862 env.Command(source.assembly, source.tnode, objectifyPyFile)
863 Source(source.assembly)
827
864
828 # make the zipfile depend on the archive name so that the archive
829 # is rebuilt if the name changes
830 py_zip_depends.append(Value(source.arcname))
865# Generate init_python.cc which creates a bunch of EmbeddedPyModule
866# structs that describe the embedded python code. One such struct
867# contains information about the importer that python uses to get at
868# the embedded files, and then there's a list of all of the rest that
869# the importer uses to load the rest on demand.
870py_sources_symbols = {}
871for pysource in py_sources:
872 py_sources_symbols[pysource.symname] = pysource
873def pythonInit(target, source, env):
874 dst = file(str(target[0]), 'w')
831
875
832# Add the zip file target to the environment.
833m5zip = File('m5py.zip')
834env.Command(m5zip, py_compiled, buildPyZip)
835env.Depends(m5zip, py_zip_depends)
876 def dump_mod(sym, endchar=','):
877 pysource = py_sources_symbols[sym]
878 print >>dst, ' { "%s",' % pysource.arcname
879 print >>dst, ' "%s",' % pysource.modpath
880 print >>dst, ' %s_beg, %s_end,' % (sym, sym)
881 print >>dst, ' %s_end - %s_beg,' % (sym, sym)
882 print >>dst, ' *(int *)%s_end }%s' % (sym, endchar)
883
884 print >>dst, '#include "sim/init.hh"'
836
885
886 for sym in source:
887 sym = sym.get_contents()
888 print >>dst, "extern const char %s_beg[], %s_end[];" % (sym, sym)
889
890 print >>dst, "const EmbeddedPyModule embeddedPyImporter = "
891 dump_mod("PyEMB_importer", endchar=';');
892 print >>dst
893
894 print >>dst, "const EmbeddedPyModule embeddedPyModules[] = {"
895 for i,sym in enumerate(source):
896 sym = sym.get_contents()
897 if sym == "PyEMB_importer":
898 # Skip the importer since we've already exported it
899 continue
900 dump_mod(sym)
901 print >>dst, " { 0, 0, 0, 0, 0, 0 }"
902 print >>dst, "};"
903
904symbols = [Value(s.symname) for s in py_sources]
905env.Command('sim/init_python.cc', symbols, pythonInit)
906Source('sim/init_python.cc')
907
837########################################################################
838#
839# Define binaries. Each different build type (debug, opt, etc.) gets
840# a slightly different build environment.
841#
842
843# List of constructed environments to pass back to SConstruct
844envList = []

--- 23 unchanged lines hidden (view full) ---

868# Function to create a new build environment as clone of current
869# environment 'env' with modified object suffix and optional stripped
870# binary. Additional keyword arguments are appended to corresponding
871# build environment vars.
872def makeEnv(label, objsfx, strip = False, **kwargs):
873 newEnv = env.Copy(OBJSUFFIX=objsfx)
874 newEnv.Label = label
875 newEnv.Append(**kwargs)
908########################################################################
909#
910# Define binaries. Each different build type (debug, opt, etc.) gets
911# a slightly different build environment.
912#
913
914# List of constructed environments to pass back to SConstruct
915envList = []

--- 23 unchanged lines hidden (view full) ---

939# Function to create a new build environment as clone of current
940# environment 'env' with modified object suffix and optional stripped
941# binary. Additional keyword arguments are appended to corresponding
942# build environment vars.
943def makeEnv(label, objsfx, strip = False, **kwargs):
944 newEnv = env.Copy(OBJSUFFIX=objsfx)
945 newEnv.Label = label
946 newEnv.Append(**kwargs)
947
948 # First make a library of everything but main() so other programs can
949 # link against m5.
950 #
951 # SCons doesn't know to append a library suffix when there is a '.' in the
952 # name. Use '_' instead.
953 m5lib = newEnv.Library('m5_' + label, make_objs(cc_lib_sources, newEnv))
954
955 # Now link a stub with main() and the library.
876 exe = 'm5.' + label # final executable
956 exe = 'm5.' + label # final executable
877 bin = exe + '.bin' # executable w/o appended Python zip archive
878 newEnv.Program(bin, make_objs(cc_sources, newEnv))
957 objects = [newEnv.Object(s) for s in cc_bin_sources] + m5lib
879 if strip:
958 if strip:
880 stripped_bin = bin + '.stripped'
959 unstripped_exe = exe + '.unstripped'
960 newEnv.Program(unstripped_exe, objects)
881 if sys.platform == 'sunos5':
882 cmd = 'cp $SOURCE $TARGET; strip $TARGET'
883 else:
884 cmd = 'strip $SOURCE -o $TARGET'
961 if sys.platform == 'sunos5':
962 cmd = 'cp $SOURCE $TARGET; strip $TARGET'
963 else:
964 cmd = 'strip $SOURCE -o $TARGET'
885 newEnv.Command(stripped_bin, bin, cmd)
886 bin = stripped_bin
887 targets = newEnv.Concat(exe, [bin, 'm5py.zip'])
965 targets = newEnv.Command(exe, unstripped_exe, cmd)
966 else:
967 targets = newEnv.Program(exe, objects)
968
888 newEnv.M5Binary = targets[0]
889 envList.append(newEnv)
890
891# Debug binary
892ccflags = {}
893if env['GCC']:
894 if sys.platform == 'sunos5':
895 ccflags['debug'] = '-gstabs+'

--- 40 unchanged lines hidden ---
969 newEnv.M5Binary = targets[0]
970 envList.append(newEnv)
971
972# Debug binary
973ccflags = {}
974if env['GCC']:
975 if sys.platform == 'sunos5':
976 ccflags['debug'] = '-gstabs+'

--- 40 unchanged lines hidden ---