30a31
> import array
31a33
> import marshal
33c35
< import py_compile
---
> import re
35c37
< import zipfile
---
> import zlib
60a63
> invalid_sym_char = re.compile('[^A-z0-9_]')
66c69,72
< path = package.split('.')
---
> if package:
> path = package.split('.')
> else:
> path = []
72c78
< arcpath = package.split('.') + [ pyname + 'c' ]
---
> arcpath = path + [ pyname ]
75c81,82
< self.source = source
---
> self.tnode = source
> self.snode = source.srcnode()
77d83
< self.srcpath = source.srcnode().abspath
82a89,91
> self.assembly = File(filename + '.s')
> self.symname = "PyEMB_" + self.invalid_sym_char.sub('_', modpath)
>
87c96
< cc_sources = []
---
> cc_lib_sources = []
89c98
< '''Add a C/C++ source file to the build'''
---
> '''Add a source file to the libm5 build'''
93c102
< cc_sources.append(source)
---
> cc_lib_sources.append(source)
94a104,111
> cc_bin_sources = []
> def BinSource(source):
> '''Add a source file to the m5 binary build'''
> if not isinstance(source, SCons.Node.FS.File):
> source = File(source)
>
> cc_bin_sources.append(source)
>
131a149
> Export('BinSource')
262c280
< py_modules[source.modpath] = source.srcpath
---
> py_modules[source.modpath] = source.snode.abspath
554c572
< print >>f, 'void init_swig() {'
---
> print >>f, 'void initSwig() {'
560,561c578,579
< env.Command('swig/init.cc', swig_modules, makeSwigInit)
< Source('swig/init.cc')
---
> env.Command('python/swig/init.cc', swig_modules, makeSwigInit)
> Source('python/swig/init.cc')
800,803c818,826
< # Build the zip file
< def compilePyFile(target, source, env):
< '''Action function to compile a .py into a .pyc'''
< py_compile.compile(str(source[0]), str(target[0]))
---
> # embed python files. All .py files that have been indicated by a
> # PySource() call in a SConscript need to be embedded into the M5
> # library. To do that, we compile the file to byte code, marshal the
> # byte code, compress it, and then generate an assembly file that
> # inserts the result into the data section with symbols indicating the
> # beginning, and end (and with the size at the end)
> py_sources_tnodes = {}
> for pysource in py_sources:
> py_sources_tnodes[pysource.tnode] = pysource
805,807c828,831
< def buildPyZip(target, source, env):
< '''Action function to build the zip archive. Uses the
< PyZipFile module included in the standard Python library.'''
---
> def objectifyPyFile(target, source, env):
> '''Action function to compile a .py into a code object, marshal
> it, compress it, and stick it into an asm file so the code appears
> as just bytes with a label in the data section'''
809,813c833,834
< py_compiled = {}
< for s in py_sources:
< compname = str(s.compiled)
< assert compname not in py_compiled
< py_compiled[compname] = s
---
> src = file(str(source[0]), 'r').read()
> dst = file(str(target[0]), 'w')
815,820c836,840
< zf = zipfile.ZipFile(str(target[0]), 'w')
< for s in source:
< zipname = str(s)
< arcname = py_compiled[zipname].arcname
< zf.write(zipname, arcname)
< zf.close()
---
> pysource = py_sources_tnodes[source[0]]
> compiled = compile(src, pysource.snode.path, 'exec')
> marshalled = marshal.dumps(compiled)
> compressed = zlib.compress(marshalled)
> data = compressed
822,823c842,860
< py_compiled = []
< py_zip_depends = []
---
> # Some C/C++ compilers prepend an underscore to global symbol
> # names, so if they're going to do that, we need to prepend that
> # leading underscore to globals in the assembly file.
> if env['LEADING_UNDERSCORE']:
> sym = '_' + pysource.symname
> else:
> sym = pysource.symname
>
> step = 16
> print >>dst, ".data"
> print >>dst, ".globl %s_beg" % sym
> print >>dst, ".globl %s_end" % sym
> print >>dst, "%s_beg:" % sym
> for i in xrange(0, len(data), step):
> x = array.array('B', data[i:i+step])
> print >>dst, ".byte", ','.join([str(d) for d in x])
> print >>dst, "%s_end:" % sym
> print >>dst, ".long %d" % len(marshalled)
>
825,826c862,863
< env.Command(source.compiled, source.source, compilePyFile)
< py_compiled.append(source.compiled)
---
> env.Command(source.assembly, source.tnode, objectifyPyFile)
> Source(source.assembly)
828,830c865,874
< # make the zipfile depend on the archive name so that the archive
< # is rebuilt if the name changes
< py_zip_depends.append(Value(source.arcname))
---
> # Generate init_python.cc which creates a bunch of EmbeddedPyModule
> # structs that describe the embedded python code. One such struct
> # contains information about the importer that python uses to get at
> # the embedded files, and then there's a list of all of the rest that
> # the importer uses to load the rest on demand.
> py_sources_symbols = {}
> for pysource in py_sources:
> py_sources_symbols[pysource.symname] = pysource
> def pythonInit(target, source, env):
> dst = file(str(target[0]), 'w')
832,835c876,884
< # Add the zip file target to the environment.
< m5zip = File('m5py.zip')
< env.Command(m5zip, py_compiled, buildPyZip)
< env.Depends(m5zip, py_zip_depends)
---
> def dump_mod(sym, endchar=','):
> pysource = py_sources_symbols[sym]
> print >>dst, ' { "%s",' % pysource.arcname
> print >>dst, ' "%s",' % pysource.modpath
> print >>dst, ' %s_beg, %s_end,' % (sym, sym)
> print >>dst, ' %s_end - %s_beg,' % (sym, sym)
> print >>dst, ' *(int *)%s_end }%s' % (sym, endchar)
>
> print >>dst, '#include "sim/init.hh"'
836a886,907
> for sym in source:
> sym = sym.get_contents()
> print >>dst, "extern const char %s_beg[], %s_end[];" % (sym, sym)
>
> print >>dst, "const EmbeddedPyModule embeddedPyImporter = "
> dump_mod("PyEMB_importer", endchar=';');
> print >>dst
>
> print >>dst, "const EmbeddedPyModule embeddedPyModules[] = {"
> for i,sym in enumerate(source):
> sym = sym.get_contents()
> if sym == "PyEMB_importer":
> # Skip the importer since we've already exported it
> continue
> dump_mod(sym)
> print >>dst, " { 0, 0, 0, 0, 0, 0 }"
> print >>dst, "};"
>
> symbols = [Value(s.symname) for s in py_sources]
> env.Command('sim/init_python.cc', symbols, pythonInit)
> Source('sim/init_python.cc')
>
875a947,955
>
> # First make a library of everything but main() so other programs can
> # link against m5.
> #
> # SCons doesn't know to append a library suffix when there is a '.' in the
> # name. Use '_' instead.
> m5lib = newEnv.Library('m5_' + label, make_objs(cc_lib_sources, newEnv))
>
> # Now link a stub with main() and the library.
877,878c957
< bin = exe + '.bin' # executable w/o appended Python zip archive
< newEnv.Program(bin, make_objs(cc_sources, newEnv))
---
> objects = [newEnv.Object(s) for s in cc_bin_sources] + m5lib
880c959,960
< stripped_bin = bin + '.stripped'
---
> unstripped_exe = exe + '.unstripped'
> newEnv.Program(unstripped_exe, objects)
885,887c965,968
< newEnv.Command(stripped_bin, bin, cmd)
< bin = stripped_bin
< targets = newEnv.Concat(exe, [bin, 'm5py.zip'])
---
> targets = newEnv.Command(exe, unstripped_exe, cmd)
> else:
> targets = newEnv.Program(exe, objects)
>