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