3 # Copyright (c) 2004-2005 The Regents of The University of Michigan
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
9 # notice, this list of conditions and the following disclaimer;
10 # redistributions in binary form must reproduce the above copyright
11 # notice, this list of conditions and the following disclaimer in the
12 # documentation and/or other materials provided with the distribution;
13 # neither the name of the copyright holders nor the names of its
14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission.
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
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.
29 # Authors: Steve Reinhardt
35 from os.path import basename
36 from os.path import join as joinpath
40 # This file defines how to build a particular configuration of M5
41 # based on variable settings in the 'env' build environment.
45 # Children need to see the environment
48 ########################################################################
49 # Code for adding source files
53 if isinstance(source, SCons.Node.FS.File):
54 sources.append(source)
56 sources.append(File(source))
58 # Children should have access
61 ########################################################################
62 # Code for adding python objects
65 py_source_packages = {}
66 def PySource(package, source):
67 if not isinstance(source, SCons.Node.FS.File):
69 py_source_packages[source] = package
70 py_sources.append(source)
73 def SimObject(source):
74 if not isinstance(source, SCons.Node.FS.File):
76 PySource('m5.objects', source)
77 modname = basename(str(source))
78 sim_objects.append(modname)
81 swig_source_packages = {}
82 def SwigSource(package, source):
83 if not isinstance(source, SCons.Node.FS.File):
85 swig_source_packages[source] = package
86 swig_sources.append(source)
88 # Children should have access
93 ########################################################################
95 # Set some compiler variables
98 # Include file paths are rooted in this directory. SCons will
99 # automatically expand '.' to refer to both the source directory and
100 # the corresponding build directory to pick up generated include
102 env.Append(CPPPATH=Dir('.'))
104 # Add a flag defining what THE_ISA should be for all compilation
105 env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
107 ########################################################################
108 # Walk the tree and execute all SConscripts
111 srcdir = env['SRCDIR']
112 for root, dirs, files in os.walk(srcdir, topdown=True):
114 # we don't want to recurse back into this SConscript
117 if 'SConscript' in files:
118 # strip off the srcdir part since scons will try to find the
119 # script in the build directory
120 base = root[len(srcdir) + 1:]
121 SConscript(joinpath(base, 'SConscript'))
123 for opt in env.ExportOptions:
126 ########################################################################
128 # Deal with python/swig, object code. Collect .py files and
129 # generating a zip archive that is appended to the m5 binary.
132 # Generate Python file that contains a dict specifying the current
134 def MakeDefinesPyFile(target, source, env):
135 f = file(str(target[0]), 'w')
136 print >>f, "m5_build_env = ", source[0]
139 optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions])
140 env.Command('python/m5/defines.py', Value(optionDict), MakeDefinesPyFile)
141 PySource('m5', 'python/m5/defines.py')
143 def MakeInfoPyFile(target, source, env):
144 f = file(str(target[0]), 'w')
146 data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
147 print >>f, "%s = %s" % (src, repr(data))
150 env.Command('python/m5/info.py',
151 [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ],
153 PySource('m5', 'python/m5/info.py')
155 def MakeObjectsInitFile(target, source, env):
156 f = file(str(target[0]), 'w')
157 print >>f, 'from m5.SimObject import *'
158 for src_path in source:
159 src_file = basename(src_path.get_contents())
160 assert(src_file.endswith('.py'))
161 src_module = src_file[:-3]
162 print >>f, 'from %s import *' % src_module
165 env.Command('python/m5/objects/__init__.py',
166 [ Value(o) for o in sim_objects],
168 PySource('m5.objects', 'python/m5/objects/__init__.py')
171 for source in swig_sources:
172 source.rfile() # Hack to cause the symlink to the .i file to be created
173 package = swig_source_packages[source]
174 filename = str(source)
175 module = basename(filename)
177 assert(module.endswith('.i'))
179 cc_file = 'swig/%s_wrap.cc' % module
180 py_file = 'm5/internal/%s.py' % module
182 env.Command([cc_file, py_file], source,
183 '$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
184 '-o ${TARGETS[0]} $SOURCES')
185 env.Depends(py_file, source)
186 env.Depends(cc_file, source)
188 swig_modules.append(Value(module))
190 PySource(package, py_file)
192 def MakeSwigInit(target, source, env):
193 f = file(str(target[0]), 'w')
194 print >>f, 'extern "C" {'
195 for module in source:
196 print >>f, ' void init_%s();' % module.get_contents()
198 print >>f, 'void init_swig() {'
199 for module in source:
200 print >>f, ' init_%s();' % module.get_contents()
203 env.Command('python/swig/init.cc', swig_modules, MakeSwigInit)
205 def CompilePyFile(target, source, env):
207 py_compile.compile(str(source[0]), str(target[0]))
212 for source in py_sources:
213 filename = str(source)
214 package = py_source_packages[source]
215 arc_path = package.split('.') + [ basename(filename) + 'c' ]
216 zip_path = [ 'zip' ] + arc_path
217 arcname = joinpath(*arc_path)
218 zipname = joinpath(*zip_path)
221 env.Command(f, source, CompilePyFile)
222 py_compiled.append(f)
223 py_arcname[f] = arcname
225 # make the zipfile depend on the archive name so that the archive
226 # is rebuilt if the name changes
227 py_zip_depends.append(Value(arcname))
229 # Action function to build the zip archive. Uses the PyZipFile module
230 # included in the standard Python library.
231 def buildPyZip(target, source, env):
232 zf = zipfile.ZipFile(str(target[0]), 'w')
234 arcname = py_arcname[s]
236 zf.write(zipname, arcname)
239 # Add the zip file target to the environment.
240 env.Command('m5py.zip', py_compiled, buildPyZip)
241 env.Depends('m5py.zip', py_zip_depends)
243 ########################################################################
245 # Define binaries. Each different build type (debug, opt, etc.) gets
246 # a slightly different build environment.
249 # List of constructed environments to pass back to SConstruct
252 # This function adds the specified sources to the given build
253 # environment, and returns a list of all the corresponding SCons
254 # Object nodes (including an extra one for date.cc). We explicitly
255 # add the Object nodes so we can set up special dependencies for
257 def make_objs(sources, env):
258 objs = [env.Object(s) for s in sources]
259 # make date.cc depend on all other objects so it always gets
260 # recompiled whenever anything else does
261 date_obj = env.Object('base/date.cc')
262 env.Depends(date_obj, objs)
263 objs.append(date_obj)
266 # Function to create a new build environment as clone of current
267 # environment 'env' with modified object suffix and optional stripped
268 # binary. Additional keyword arguments are appended to corresponding
269 # build environment vars.
270 def makeEnv(label, objsfx, strip = False, **kwargs):
271 newEnv = env.Copy(OBJSUFFIX=objsfx)
273 newEnv.Append(**kwargs)
274 exe = 'm5.' + label # final executable
275 bin = exe + '.bin' # executable w/o appended Python zip archive
276 newEnv.Program(bin, make_objs(sources, newEnv))
278 stripped_bin = bin + '.stripped'
279 if sys.platform == 'sunos5':
280 newEnv.Command(stripped_bin, bin, 'cp $SOURCE $TARGET; strip $TARGET')
282 newEnv.Command(stripped_bin, bin, 'strip $SOURCE -o $TARGET')
284 targets = newEnv.Concat(exe, [bin, 'm5py.zip'])
285 newEnv.M5Binary = targets[0]
286 envList.append(newEnv)
291 if sys.platform == 'sunos5':
292 ccflags['debug'] = '-gstabs+'
294 ccflags['debug'] = '-ggdb3'
295 ccflags['opt'] = '-g -O3'
296 ccflags['fast'] = '-O3'
297 ccflags['prof'] = '-O3 -g -pg'
299 ccflags['debug'] = '-g0'
300 ccflags['opt'] = '-g -O'
301 ccflags['fast'] = '-fast'
302 ccflags['prof'] = '-fast -g -pg'
304 ccflags['debug'] = '-g -O0'
305 ccflags['opt'] = '-g -O'
306 ccflags['fast'] = '-fast'
307 ccflags['prof'] = '-fast -g -pg'
309 print 'Unknown compiler, please fix compiler options'
312 makeEnv('debug', '.do',
313 CCFLAGS = Split(ccflags['debug']),
314 CPPDEFINES = ['DEBUG', 'TRACING_ON=1'])
318 CCFLAGS = Split(ccflags['opt']),
319 CPPDEFINES = ['TRACING_ON=1'])
322 makeEnv('fast', '.fo', strip = True,
323 CCFLAGS = Split(ccflags['fast']),
324 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'])
327 makeEnv('prof', '.po',
328 CCFLAGS = Split(ccflags['prof']),
329 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],