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 |
32import imp |
33import marshal |
34import os |
35import re |
36import sys |
37import zlib |
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_]') |
64 def __init__(self, package, source): 65 filename = str(source) 66 pyname = basename(filename) 67 assert pyname.endswith('.py') 68 name = pyname[:-3] |
69 if package: 70 path = package.split('.') 71 else: 72 path = [] |
73 modpath = path 74 if name != '__init__': 75 modpath += [name] 76 modpath = '.'.join(modpath) 77 |
78 arcpath = path + [ pyname ] |
79 arcname = joinpath(*arcpath) 80 |
81 self.tnode = source 82 self.snode = source.srcnode() |
83 self.pyname = pyname |
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 |
92 93######################################################################## 94# Code for adding source files of various types 95# |
96cc_lib_sources = [] |
97def Source(source): |
98 '''Add a source file to the libm5 build''' |
99 if not isinstance(source, SCons.Node.FS.File): 100 source = File(source) 101 |
102 cc_lib_sources.append(source) |
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 |
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') |
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: |
280 py_modules[source.modpath] = source.snode.abspath |
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, '}' |
572 print >>f, 'void initSwig() {' |
573 for module in source: 574 print >>f, ' init_%s();' % module.get_contents() 575 print >>f, '}' 576 f.close() 577 |
578env.Command('python/swig/init.cc', swig_modules, makeSwigInit) 579Source('python/swig/init.cc') |
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 |
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 |
827 |
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''' |
832 |
833 src = file(str(source[0]), 'r').read() 834 dst = file(str(target[0]), 'w') |
835 |
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 |
841 |
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 |
861for source in py_sources: |
862 env.Command(source.assembly, source.tnode, objectifyPyFile) 863 Source(source.assembly) |
864 |
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') |
875 |
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"' |
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 |
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. |
956 exe = 'm5.' + label # final executable |
957 objects = [newEnv.Object(s) for s in cc_bin_sources] + m5lib |
958 if strip: |
959 unstripped_exe = exe + '.unstripped' 960 newEnv.Program(unstripped_exe, objects) |
961 if sys.platform == 'sunos5': 962 cmd = 'cp $SOURCE $TARGET; strip $TARGET' 963 else: 964 cmd = 'strip $SOURCE -o $TARGET' |
965 targets = newEnv.Command(exe, unstripped_exe, cmd) 966 else: 967 targets = newEnv.Program(exe, objects) 968 |
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 --- |