Deleted Added
sdiff udiff text old ( 5341:4efeab4cc2a5 ) new ( 5342:c19e3a1a607c )
full compact
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
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.
16#
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.
28#
29# Authors: Nathan Binkert
30
31import imp
32import os
33import sys
34
35from os.path import basename
36from os.path import isdir, join as joinpath
37from os.path import exists
38from os.path import isdir
39from os.path import isfile
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
46Import('*')
47
48# Children need to see the environment
49Export('env')
50
51def sort_list(_list):
52 """return a sorted copy of '_list'"""
53 if isinstance(_list, list):
54 _list = _list[:]
55 else:
56 _list = list(_list)
57 _list.sort()
58 return _list
59
60class PySourceFile(object):
61 def __init__(self, package, source):
62 filename = str(source)
63 pyname = basename(filename)
64 assert pyname.endswith('.py')
65 name = pyname[:-3]
66 path = package.split('.')
67 modpath = path
68 if name != '__init__':
69 modpath += [name]
70 modpath = '.'.join(modpath)
71
72 arcpath = package.split('.') + [ pyname + 'c' ]
73 arcname = joinpath(*arcpath)
74
75 self.source = source
76 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')
83
84########################################################################
85# Code for adding source files of various types
86#
87cc_sources = []
88def Source(source):
89 '''Add a C/C++ source file to the build'''
90 if not isinstance(source, SCons.Node.FS.File):
91 source = File(source)
92
93 cc_sources.append(source)
94
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)
103
104sim_objects_fixed = False
105sim_object_modfiles = set()
106def SimObject(source):
107 '''Add a SimObject python file as a python source object and add
108 it to a list of sim object modules'''
109
110 if sim_objects_fixed:
111 raise AttributeError, "Too late to call SimObject now."
112
113 if not isinstance(source, SCons.Node.FS.File):
114 source = File(source)
115
116 PySource('m5.objects', source)
117 modfile = basename(str(source))
118 assert modfile.endswith('.py')
119 modname = modfile[:-3]
120 sim_object_modfiles.add(modname)
121
122swig_sources = []
123def SwigSource(package, source):
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')
132Export('PySource')
133Export('SimObject')
134Export('SwigSource')
135
136########################################################################
137#
138# Trace Flags
139#
140all_flags = {}
141trace_flags = []
142def TraceFlag(name, desc=''):
143 if name in all_flags:
144 raise AttributeError, "Flag %s already specified" % name
145 flag = (name, (), desc)
146 trace_flags.append(flag)
147 all_flags[name] = ()
148
149def CompoundFlag(name, flags, desc=''):
150 if name in all_flags:
151 raise AttributeError, "Flag %s already specified" % name
152
153 compound = tuple(flags)
154 for flag in compound:
155 if flag not in all_flags:
156 raise AttributeError, "Trace flag %s not found" % flag
157 if all_flags[flag]:
158 raise AttributeError, \
159 "Compound flag can't point to another compound flag"
160
161 flag = (name, compound, desc)
162 trace_flags.append(flag)
163 all_flags[name] = compound
164
165Export('TraceFlag')
166Export('CompoundFlag')
167
168########################################################################
169#
170# Set some compiler variables
171#
172
173# Include file paths are rooted in this directory. SCons will
174# automatically expand '.' to refer to both the source directory and
175# the corresponding build directory to pick up generated include
176# files.
177env.Append(CPPPATH=Dir('.'))
178
179# Add a flag defining what THE_ISA should be for all compilation
180env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
181
182########################################################################
183#
184# Walk the tree and execute all SConscripts in 'src' subdirectories
185#
186
187for base_dir in base_dir_list:
188 src_dir = joinpath(base_dir, 'src')
189 if not isdir(src_dir):
190 continue
191 here = Dir('.').srcnode().abspath
192 for root, dirs, files in os.walk(src_dir, topdown=True):
193 if root == here:
194 # we don't want to recurse back into this SConscript
195 continue
196
197 if 'SConscript' in files:
198 build_dir = joinpath(env['BUILDDIR'], root[len(src_dir) + 1:])
199 SConscript(joinpath(root, 'SConscript'), build_dir=build_dir)
200
201for opt in env.ExportOptions:
202 env.ConfigFile(opt)
203
204########################################################################
205#
206# Prevent any SimObjects from being added after this point, they
207# should all have been added in the SConscripts above
208#
209sim_objects_fixed = True
210
211########################################################################
212#
213# Manually turn python/generate.py into a python module and import it
214#
215generate_file = File('python/generate.py')
216generate_module = imp.new_module('generate')
217sys.modules['generate'] = generate_module
218exec file(generate_file.srcnode().abspath, 'r') in generate_module.__dict__
219
220########################################################################
221#
222# build a generate
223#
224from generate import Generate
225optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions])
226generate = Generate(py_sources, sim_object_modfiles, optionDict)
227m5 = generate.m5
228
229########################################################################
230#
231# calculate extra dependencies
232#
233module_depends = ["m5", "m5.SimObject", "m5.params"]
234module_depends = [ File(generate.py_modules[dep]) for dep in module_depends ]
235file_depends = [ generate_file ]
236depends = module_depends + file_depends
237
238########################################################################
239#
240# Commands for the basic automatically generated python files
241#
242
243# Generate a file with all of the compile options in it
244env.Command('python/m5/defines.py', Value(optionDict),
245 generate.makeDefinesPyFile)
246PySource('m5', 'python/m5/defines.py')
247
248# Generate a file that wraps the basic top level files
249env.Command('python/m5/info.py',
250 [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ],
251 generate.makeInfoPyFile)
252PySource('m5', 'python/m5/info.py')
253
254# Generate an __init__.py file for the objects package
255env.Command('python/m5/objects/__init__.py',
256 [ Value(o) for o in sort_list(sim_object_modfiles) ],
257 generate.makeObjectsInitFile)
258PySource('m5.objects', 'python/m5/objects/__init__.py')
259
260########################################################################
261#
262# Create all of the SimObject param headers and enum headers
263#
264
265# Generate all of the SimObject param struct header files
266params_hh_files = []
267for name,simobj in generate.sim_objects.iteritems():
268 extra_deps = [ File(generate.py_modules[simobj.__module__]) ]
269
270 hh_file = File('params/%s.hh' % name)
271 params_hh_files.append(hh_file)
272 env.Command(hh_file, Value(name), generate.createSimObjectParam)
273 env.Depends(hh_file, depends + extra_deps)
274
275# Generate any parameter header files needed
276for name,param in generate.params.iteritems():
277 if isinstance(param, m5.params.VectorParamDesc):
278 ext = 'vptype'
279 else:
280 ext = 'ptype'
281
282 i_file = File('params/%s_%s.i' % (name, ext))
283 env.Command(i_file, Value(name), generate.createSwigParam)
284 env.Depends(i_file, depends)
285
286# Generate all enum header files
287for name,enum in generate.enums.iteritems():
288 extra_deps = [ File(generate.py_modules[enum.__module__]) ]
289
290 cc_file = File('enums/%s.cc' % name)
291 env.Command(cc_file, Value(name), generate.createEnumStrings)
292 env.Depends(cc_file, depends + extra_deps)
293 Source(cc_file)
294
295 hh_file = File('enums/%s.hh' % name)
296 env.Command(hh_file, Value(name), generate.createEnumParam)
297 env.Depends(hh_file, depends + extra_deps)
298
299# Build the big monolithic swigged params module (wraps all SimObject
300# param structs and enum structs)
301params_file = File('params/params.i')
302names = sort_list(generate.sim_objects.keys())
303env.Command(params_file, [ Value(v) for v in names ],
304 generate.buildParams)
305env.Depends(params_file, params_hh_files + depends)
306SwigSource('m5.objects', params_file)
307
308# Build all swig modules
309swig_modules = []
310for source,package in swig_sources:
311 filename = str(source)
312 assert filename.endswith('.i')
313
314 base = '.'.join(filename.split('.')[:-1])
315 module = basename(base)
316 cc_file = base + '_wrap.cc'
317 py_file = base + '.py'
318
319 env.Command([cc_file, py_file], source,
320 '$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
321 '-o ${TARGETS[0]} $SOURCES')
322 env.Depends(py_file, source)
323 env.Depends(cc_file, source)
324
325 swig_modules.append(Value(module))
326 Source(cc_file)
327 PySource(package, py_file)
328
329# Generate the main swig init file
330env.Command('swig/init.cc', swig_modules, generate.makeSwigInit)
331Source('swig/init.cc')
332
333# Generate traceflags.py
334flags = [ Value(f) for f in trace_flags ]
335env.Command('base/traceflags.py', flags, generate.traceFlagsPy)
336PySource('m5', 'base/traceflags.py')
337
338env.Command('base/traceflags.hh', flags, generate.traceFlagsHH)
339env.Command('base/traceflags.cc', flags, generate.traceFlagsCC)
340Source('base/traceflags.cc')
341
342# Build the zip file
343py_compiled = []
344py_zip_depends = []
345for source in py_sources:
346 env.Command(source.compiled, source.source, generate.compilePyFile)
347 py_compiled.append(source.compiled)
348
349 # make the zipfile depend on the archive name so that the archive
350 # is rebuilt if the name changes
351 py_zip_depends.append(Value(source.arcname))
352
353# Add the zip file target to the environment.
354m5zip = File('m5py.zip')
355env.Command(m5zip, py_compiled, generate.buildPyZip)
356env.Depends(m5zip, py_zip_depends)
357
358########################################################################
359#
360# Define binaries. Each different build type (debug, opt, etc.) gets
361# a slightly different build environment.
362#
363
364# List of constructed environments to pass back to SConstruct
365envList = []
366
367# This function adds the specified sources to the given build
368# environment, and returns a list of all the corresponding SCons
369# Object nodes (including an extra one for date.cc). We explicitly
370# add the Object nodes so we can set up special dependencies for
371# date.cc.
372def make_objs(sources, env):
373 objs = [env.Object(s) for s in sources]
374 # make date.cc depend on all other objects so it always gets
375 # recompiled whenever anything else does
376 date_obj = env.Object('base/date.cc')
377 env.Depends(date_obj, objs)
378 objs.append(date_obj)
379 return objs
380
381# Function to create a new build environment as clone of current
382# environment 'env' with modified object suffix and optional stripped
383# binary. Additional keyword arguments are appended to corresponding
384# build environment vars.
385def makeEnv(label, objsfx, strip = False, **kwargs):
386 newEnv = env.Copy(OBJSUFFIX=objsfx)
387 newEnv.Label = label
388 newEnv.Append(**kwargs)
389 exe = 'm5.' + label # final executable
390 bin = exe + '.bin' # executable w/o appended Python zip archive
391 newEnv.Program(bin, make_objs(cc_sources, newEnv))
392 if strip:
393 stripped_bin = bin + '.stripped'
394 if sys.platform == 'sunos5':
395 cmd = 'cp $SOURCE $TARGET; strip $TARGET'
396 else:
397 cmd = 'strip $SOURCE -o $TARGET'
398 newEnv.Command(stripped_bin, bin, cmd)
399 bin = stripped_bin
400 targets = newEnv.Concat(exe, [bin, 'm5py.zip'])
401 newEnv.M5Binary = targets[0]
402 envList.append(newEnv)
403
404# Debug binary
405ccflags = {}
406if env['GCC']:
407 if sys.platform == 'sunos5':
408 ccflags['debug'] = '-gstabs+'
409 else:
410 ccflags['debug'] = '-ggdb3'
411 ccflags['opt'] = '-g -O3'
412 ccflags['fast'] = '-O3'
413 ccflags['prof'] = '-O3 -g -pg'
414elif env['SUNCC']:
415 ccflags['debug'] = '-g0'
416 ccflags['opt'] = '-g -O'
417 ccflags['fast'] = '-fast'
418 ccflags['prof'] = '-fast -g -pg'
419elif env['ICC']:
420 ccflags['debug'] = '-g -O0'
421 ccflags['opt'] = '-g -O'
422 ccflags['fast'] = '-fast'
423 ccflags['prof'] = '-fast -g -pg'
424else:
425 print 'Unknown compiler, please fix compiler options'
426 Exit(1)
427
428makeEnv('debug', '.do',
429 CCFLAGS = Split(ccflags['debug']),
430 CPPDEFINES = ['DEBUG', 'TRACING_ON=1'])
431
432# Optimized binary
433makeEnv('opt', '.o',
434 CCFLAGS = Split(ccflags['opt']),
435 CPPDEFINES = ['TRACING_ON=1'])
436
437# "Fast" binary
438makeEnv('fast', '.fo', strip = True,
439 CCFLAGS = Split(ccflags['fast']),
440 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'])
441
442# Profiled binary
443makeEnv('prof', '.po',
444 CCFLAGS = Split(ccflags['prof']),
445 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
446 LINKFLAGS = '-pg')
447
448Return('envList')