diff --git a/SConstruct b/SConstruct index 396dc593b3..4e2ed47c0b 100755 --- a/SConstruct +++ b/SConstruct @@ -516,12 +516,6 @@ if main['USE_PYTHON']: if not py_version: error("Can't find a working Python installation") - marshal_env = main.Clone() - - # Bare minimum environment that only includes python - marshal_env.Append(CCFLAGS='$MARSHAL_CCFLAGS_EXTRA') - marshal_env.Append(LINKFLAGS='$MARSHAL_LDFLAGS_EXTRA') - # Found a working Python installation. Check if it meets minimum # requirements. ver_string = '.'.join(map(str, py_version)) @@ -532,6 +526,12 @@ if main['USE_PYTHON']: warning('Embedded python library too new. ' 'Python 3 expected, found %s.' % ver_string) +marshal_env = main.Clone() + +# Bare minimum environment that only includes python +marshal_env.Append(CCFLAGS='$MARSHAL_CCFLAGS_EXTRA') +marshal_env.Append(LINKFLAGS='$MARSHAL_LDFLAGS_EXTRA') + main['HAVE_PKG_CONFIG'] = main.Detect('pkg-config') with gem5_scons.Configure(main) as conf: @@ -704,9 +704,7 @@ Build variables for {dir}: env.Append(CCFLAGS='$CCFLAGS_EXTRA') env.Append(LINKFLAGS='$LDFLAGS_EXTRA') - exports=['env'] - if main['USE_PYTHON']: - exports.append('marshal_env') + exports=['env', 'marshal_env'] # The src/SConscript file sets up the build rules in 'env' according # to the configured variables. It returns a list of environments, diff --git a/src/SConscript b/src/SConscript index db11f440fe..6fc32767b3 100644 --- a/src/SConscript +++ b/src/SConscript @@ -349,6 +349,67 @@ def GdbXml(xml_id, symbol): class Source(SourceFile): pass +# Build a small helper that marshals the Python code using the same version +# of Python as gem5. This is in an unorthodox location to avoid building it +# for every variant. +py_marshal = marshal_env.Program('marshal', 'python/marshal.cc')[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 a c++ file that +# inserts the result into an array. +def embedPyFile(target, source, env): + def c_str(string): + if string is None: + return "0" + return '"%s"' % string + + '''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. The action takes two + sources: + + source[0]: Binary used to marshal Python sources + source[1]: Python script to marshal + ''' + + import subprocess + + marshalled = subprocess.check_output( + [source[0].abspath, str(source[1])], env=env['ENV']) + + compressed = zlib.compress(marshalled) + data = compressed + pysource = PySource.tnodes[source[1]] + + code = code_formatter() + code('''\ +#include "sim/init.hh" + +namespace gem5 +{ +namespace +{ + +''') + bytesToCppArray(code, 'embedded_module_data', data) + # The name of the EmbeddedPython object doesn't matter since it's in an + # anonymous namespace, and it's constructor takes care of installing it + # into a global list. + code(''' +EmbeddedPython embedded_module_info( + ${{c_str(pysource.abspath)}}, + ${{c_str(pysource.modpath)}}, + embedded_module_data, + ${{len(data)}}, + ${{len(marshalled)}}); + +} // anonymous namespace +} // namespace gem5 +''') + code.write(str(target[0])) + class PySource(SourceFile): '''Add a python source file to the named package''' modules = {} @@ -384,6 +445,9 @@ class PySource(SourceFile): PySource.modules[modpath] = self PySource.tnodes[self.tnode] = self + marshal_env.Command(self.cpp, [ py_marshal, self.tnode ], + MakeAction(embedPyFile, Transform("EMBED PY"))) + class SimObject(PySource): '''Add a SimObject python file as a python source object and add it to a list of sim object modules''' @@ -1037,7 +1101,7 @@ for name,simobj in sorted(sim_objects.items()): MakeAction(createSimObjectWrappers, Transform("SO PyB/C"))) env.Depends(cc_file, depends + extra_deps) - Source(cc_file) + Source(cc_file, add_tags='python') # # Handle debug flags @@ -1166,71 +1230,8 @@ env.Command('sim/tags.cc', None, Transform("VER TAGS"))) env.AlwaysBuild(tags) -# 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 a c++ file that -# inserts the result into an array. -def embedPyFile(target, source, env): - def c_str(string): - if string is None: - return "0" - return '"%s"' % string - - '''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. The action takes two - sources: - - source[0]: Binary used to marshal Python sources - source[1]: Python script to marshal - ''' - - import subprocess - - marshalled = subprocess.check_output( - [source[0].abspath, str(source[1])], env=env['ENV']) - - compressed = zlib.compress(marshalled) - data = compressed - pysource = PySource.tnodes[source[1]] - - code = code_formatter() - code('''\ -#include "sim/init.hh" - -namespace gem5 -{ -namespace -{ - -''') - bytesToCppArray(code, 'embedded_module_data', data) - # The name of the EmbeddedPython object doesn't matter since it's in an - # anonymous namespace, and it's constructor takes care of installing it - # into a global list. - code(''' -EmbeddedPython embedded_module_info( - ${{c_str(pysource.abspath)}}, - ${{c_str(pysource.modpath)}}, - embedded_module_data, - ${{len(data)}}, - ${{len(marshalled)}}); - -} // anonymous namespace -} // namespace gem5 -''') - code.write(str(target[0])) - if main['USE_PYTHON']: - # Build a small helper that marshals the Python code using the same - # version of Python as gem5. This is in an unorthodox location to - # avoid building it for every variant. - py_marshal = marshal_env.Program('marshal', 'python/marshal.cc')[0] - for source in PySource.all: - marshal_env.Command(source.cpp, [ py_marshal, source.tnode ], - MakeAction(embedPyFile, Transform("EMBED PY"))) Source(source.cpp, tags=source.tags, add_tags='python') ########################################################################