Link in Python interpreter.
Use embedded zip archive to carry Python code instead
of homegrown embedded string/file mechanism.
Do argument parsing in Python instead of C++.
SConstruct:
Add Python interpreter include path & library.
Define two new simple builders which copy &
concatenate files, respectively, for use by
the Python embedded zipfile code.
src/SConscript:
Encapsulate environment creation in a function.
Add code to append Python zip archive to final executable.
Eliminate references to obsolete files.
src/python/SConscript:
Rewrite to generate embedded zip archive of Python code
(replacing old "embedded string" mechanism).
src/python/m5/__init__.py:
Move main arg-parsing loop here (out of C++ main()).
src/python/m5/config.py:
Minor fix (version incompatibility?).
src/sim/main.cc:
Invoke embedded Python interpreter to parse args
and generate config.ini, replacing C++ arg parsing code.
--HG--
extra : convert_revision : 72d21236b2bee139ff39ba4cf031a4a1f8560029
This commit is contained in:
@@ -27,126 +27,55 @@
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import os, os.path, re, sys
|
||||
from zipfile import PyZipFile
|
||||
|
||||
# handy function for path joins
|
||||
def join(*args):
|
||||
return os.path.normpath(os.path.join(*args))
|
||||
|
||||
Import('env')
|
||||
|
||||
import scons_helper
|
||||
# This SConscript is in charge of collecting .py files and generating a zip archive that is appended to the m5 binary.
|
||||
|
||||
def WriteEmbeddedPyFile(target, source, path, name, ext, filename):
|
||||
if isinstance(source, str):
|
||||
source = file(source, 'r')
|
||||
# Copy .py source files here (relative to src/python in the build
|
||||
# directory).
|
||||
pyzip_root = 'zip'
|
||||
|
||||
if isinstance(target, str):
|
||||
target = file(target, 'w')
|
||||
# List of files & directories to include in the zip file. To include
|
||||
# a package, list only the root directory of the package, not any
|
||||
# internal .py files (else they will get the path stripped off when
|
||||
# they are imported into the zip file).
|
||||
pyzip_files = []
|
||||
|
||||
print >>target, "AddModule(%s, %s, %s, %s, '''\\" % \
|
||||
(`path`, `name`, `ext`, `filename`)
|
||||
# List of additional files on which the zip archive depends, but which
|
||||
# are not included in pyzip_files... i.e. individual .py files within
|
||||
# a package.
|
||||
pyzip_dep_files = []
|
||||
|
||||
for line in source:
|
||||
line = line
|
||||
# escape existing backslashes
|
||||
line = line.replace('\\', '\\\\')
|
||||
# escape existing triple quotes
|
||||
line = line.replace("'''", r"\'\'\'")
|
||||
# Add the specified package to the zip archive. Adds the directory to
|
||||
# pyzip_files and all included .py files to pyzip_dep_files.
|
||||
def addPkg(pkgdir):
|
||||
pyzip_files.append(join(pyzip_root, pkgdir))
|
||||
origdir = os.getcwd()
|
||||
srcdir = join(Dir('.').srcnode().abspath, pkgdir)
|
||||
os.chdir(srcdir)
|
||||
for path, dirs, files in os.walk('.'):
|
||||
for i,dir in enumerate(dirs):
|
||||
if dir == 'SCCS':
|
||||
del dirs[i]
|
||||
break
|
||||
|
||||
print >>target, line,
|
||||
for f in files:
|
||||
if f.endswith('.py'):
|
||||
source = join(pkgdir, path, f)
|
||||
target = join(pyzip_root, source)
|
||||
pyzip_dep_files.append(target)
|
||||
env.CopyFile(target, source)
|
||||
|
||||
print >>target, "''')"
|
||||
print >>target
|
||||
|
||||
def WriteCFile(target, source, name):
|
||||
if isinstance(source, str):
|
||||
source = file(source, 'r')
|
||||
|
||||
if isinstance(target, str):
|
||||
target = file(target, 'w')
|
||||
|
||||
print >>target, 'const char %s_string[] = {' % name
|
||||
|
||||
count = 0
|
||||
from array import array
|
||||
try:
|
||||
while True:
|
||||
foo = array('B')
|
||||
foo.fromfile(source, 10000)
|
||||
l = [ str(i) for i in foo.tolist() ]
|
||||
count += len(l)
|
||||
for i in xrange(0,9999,20):
|
||||
print >>target, ','.join(l[i:i+20]) + ','
|
||||
except EOFError:
|
||||
l = [ str(i) for i in foo.tolist() ]
|
||||
count += len(l)
|
||||
for i in xrange(0,len(l),20):
|
||||
print >>target, ','.join(l[i:i+20]) + ','
|
||||
print >>target, ','.join(l[i:]) + ','
|
||||
|
||||
print >>target, '};'
|
||||
print >>target, 'const int %s_length = %d;' % (name, count)
|
||||
print >>target
|
||||
|
||||
def splitpath(path):
|
||||
dir,file = os.path.split(path)
|
||||
path = []
|
||||
assert(file)
|
||||
while dir:
|
||||
dir,base = os.path.split(dir)
|
||||
path.insert(0, base)
|
||||
return path, file
|
||||
|
||||
def MakeEmbeddedPyFile(target, source, env):
|
||||
target = file(str(target[0]), 'w')
|
||||
|
||||
tree = {}
|
||||
for src in source:
|
||||
src = str(src)
|
||||
path,pyfile = splitpath(src)
|
||||
node = tree
|
||||
for dir in path:
|
||||
if not node.has_key(dir):
|
||||
node[dir] = { }
|
||||
node = node[dir]
|
||||
|
||||
name,ext = pyfile.split('.')
|
||||
if name == '__init__':
|
||||
node['.hasinit'] = True
|
||||
node[pyfile] = (src,name,ext,src)
|
||||
|
||||
done = False
|
||||
while not done:
|
||||
done = True
|
||||
for name,entry in tree.items():
|
||||
if not isinstance(entry, dict): continue
|
||||
if entry.has_key('.hasinit'): continue
|
||||
|
||||
done = False
|
||||
del tree[name]
|
||||
for key,val in entry.iteritems():
|
||||
if tree.has_key(key):
|
||||
raise NameError, \
|
||||
"dir already has %s can't add it again" % key
|
||||
tree[key] = val
|
||||
|
||||
files = []
|
||||
def populate(node, path = []):
|
||||
names = node.keys()
|
||||
names.sort()
|
||||
for name in names:
|
||||
if name == '.hasinit':
|
||||
continue
|
||||
|
||||
entry = node[name]
|
||||
if isinstance(entry, dict):
|
||||
if not entry.has_key('.hasinit'):
|
||||
raise NameError, 'package directory missing __init__.py'
|
||||
populate(entry, path + [ name ])
|
||||
else:
|
||||
pyfile,name,ext,filename = entry
|
||||
files.append((pyfile, path, name, ext, filename))
|
||||
populate(tree)
|
||||
|
||||
for pyfile, path, name, ext, filename in files:
|
||||
WriteEmbeddedPyFile(target, pyfile, path, name, ext, filename)
|
||||
os.chdir(origdir)
|
||||
|
||||
# Generate Python file that contains a dict specifying the current
|
||||
# build_env flags.
|
||||
def MakeDefinesPyFile(target, source, env):
|
||||
f = file(str(target[0]), 'w')
|
||||
print >>f, "import __main__"
|
||||
@@ -154,54 +83,21 @@ def MakeDefinesPyFile(target, source, env):
|
||||
print >>f, source[0]
|
||||
f.close()
|
||||
|
||||
CFileCounter = 0
|
||||
def MakePythonCFile(target, source, env):
|
||||
global CFileCounter
|
||||
target = file(str(target[0]), 'w')
|
||||
|
||||
print >>target, '''\
|
||||
#include "base/embedfile.hh"
|
||||
|
||||
namespace {
|
||||
'''
|
||||
for src in source:
|
||||
src = str(src)
|
||||
fname = os.path.basename(src)
|
||||
name = 'embedded_file%d' % CFileCounter
|
||||
CFileCounter += 1
|
||||
WriteCFile(target, src, name)
|
||||
print >>target, '''\
|
||||
EmbedMap %(name)s("%(fname)s",
|
||||
%(name)s_string, %(name)s_length);
|
||||
|
||||
''' % locals()
|
||||
print >>target, '''\
|
||||
|
||||
/* namespace */ }
|
||||
'''
|
||||
|
||||
# base list of .py files to embed
|
||||
embedded_py_files = [ os.path.join(env['ROOT'], 'util/pbs/jobfile.py') ]
|
||||
# add all .py files in python/m5
|
||||
objpath = os.path.join(env['SRCDIR'], 'python', 'm5')
|
||||
for root, dirs, files in os.walk(objpath, topdown=True):
|
||||
for i,dir in enumerate(dirs):
|
||||
if dir == 'SCCS':
|
||||
del dirs[i]
|
||||
break
|
||||
|
||||
assert(root.startswith(objpath))
|
||||
for f in files:
|
||||
if f.endswith('.py'):
|
||||
embedded_py_files.append(os.path.join(root, f))
|
||||
|
||||
embedfile_hh = os.path.join(env['SRCDIR'], 'base/embedfile.hh')
|
||||
|
||||
optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions])
|
||||
env.Command('defines.py', Value(optionDict), MakeDefinesPyFile)
|
||||
|
||||
env.Command('embedded_py.py', embedded_py_files, MakeEmbeddedPyFile)
|
||||
env.Depends('embedded_py.cc', embedfile_hh)
|
||||
env.Command('embedded_py.cc',
|
||||
['string_importer.py', 'defines.py', 'embedded_py.py'],
|
||||
MakePythonCFile)
|
||||
# Now specify the packages & files for the zip archive.
|
||||
addPkg('m5')
|
||||
pyzip_files.append('defines.py')
|
||||
pyzip_files.append(join(env['ROOT'], 'util/pbs/jobfile.py'))
|
||||
|
||||
# Action function to build the zip archive. Uses the PyZipFile module
|
||||
# included in the standard Python library.
|
||||
def buildPyZip(target, source, env):
|
||||
pzf = PyZipFile(str(target[0]), 'w')
|
||||
for s in source:
|
||||
pzf.writepy(str(s))
|
||||
|
||||
# Add the zip file target to the environment.
|
||||
env.Command('m5py.zip', pyzip_files, buildPyZip)
|
||||
env.Depends('m5py.zip', pyzip_dep_files)
|
||||
|
||||
Reference in New Issue
Block a user