Make the "name" function const.
[gem5.git] / src / SConscript
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: Steve Reinhardt
30
31 import os
32 import sys
33 import zipfile
34
35 from os.path import basename
36 from os.path import join as joinpath
37
38 import SCons
39
40 # This file defines how to build a particular configuration of M5
41 # based on variable settings in the 'env' build environment.
42
43 Import('*')
44
45 # Children need to see the environment
46 Export('env')
47
48 ########################################################################
49 # Code for adding source files
50 #
51 sources = []
52 def Source(source):
53 if isinstance(source, SCons.Node.FS.File):
54 sources.append(source)
55 else:
56 sources.append(File(source))
57
58 # Children should have access
59 Export('Source')
60
61 ########################################################################
62 # Code for adding python objects
63 #
64 py_sources = []
65 py_source_packages = {}
66 def PySource(package, source):
67 if not isinstance(source, SCons.Node.FS.File):
68 source = File(source)
69 py_source_packages[source] = package
70 py_sources.append(source)
71
72 sim_objects = []
73 def SimObject(source):
74 if not isinstance(source, SCons.Node.FS.File):
75 source = File(source)
76 PySource('m5.objects', source)
77 modname = basename(str(source))
78 sim_objects.append(modname)
79
80 swig_sources = []
81 swig_source_packages = {}
82 def SwigSource(package, source):
83 if not isinstance(source, SCons.Node.FS.File):
84 source = File(source)
85 swig_source_packages[source] = package
86 swig_sources.append(source)
87
88 # Children should have access
89 Export('PySource')
90 Export('SimObject')
91 Export('SwigSource')
92
93 ########################################################################
94 #
95 # Set some compiler variables
96 #
97
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
101 # files.
102 env.Append(CPPPATH=Dir('.'))
103
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())])
106
107 ########################################################################
108 # Walk the tree and execute all SConscripts
109 #
110 scripts = []
111 srcdir = env['SRCDIR']
112 for root, dirs, files in os.walk(srcdir, topdown=True):
113 if root == srcdir:
114 # we don't want to recurse back into this SConscript
115 continue
116
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'))
122
123 for opt in env.ExportOptions:
124 env.ConfigFile(opt)
125
126 ########################################################################
127 #
128 # Deal with python/swig, object code. Collect .py files and
129 # generating a zip archive that is appended to the m5 binary.
130 #
131
132 # Generate Python file that contains a dict specifying the current
133 # build_env flags.
134 def MakeDefinesPyFile(target, source, env):
135 f = file(str(target[0]), 'w')
136 print >>f, "m5_build_env = ", source[0]
137 f.close()
138
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')
142
143 def MakeInfoPyFile(target, source, env):
144 f = file(str(target[0]), 'w')
145 for src in source:
146 data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
147 print >>f, "%s = %s" % (src, repr(data))
148 f.close()
149
150 env.Command('python/m5/info.py',
151 [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ],
152 MakeInfoPyFile)
153 PySource('m5', 'python/m5/info.py')
154
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
163 f.close()
164
165 env.Command('python/m5/objects/__init__.py',
166 [ Value(o) for o in sim_objects],
167 MakeObjectsInitFile)
168 PySource('m5.objects', 'python/m5/objects/__init__.py')
169
170 swig_modules = []
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)
176
177 assert(module.endswith('.i'))
178 module = module[:-2]
179 cc_file = 'swig/%s_wrap.cc' % module
180 py_file = 'm5/internal/%s.py' % module
181
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)
187
188 swig_modules.append(Value(module))
189 Source(cc_file)
190 PySource(package, py_file)
191
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()
197 print >>f, '}'
198 print >>f, 'void init_swig() {'
199 for module in source:
200 print >>f, ' init_%s();' % module.get_contents()
201 print >>f, '}'
202 f.close()
203 env.Command('python/swig/init.cc', swig_modules, MakeSwigInit)
204
205 def CompilePyFile(target, source, env):
206 import py_compile
207 py_compile.compile(str(source[0]), str(target[0]))
208
209 py_compiled = []
210 py_arcname = {}
211 py_zip_depends = []
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)
219 f = File(zipname)
220
221 env.Command(f, source, CompilePyFile)
222 py_compiled.append(f)
223 py_arcname[f] = arcname
224
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))
228
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')
233 for s in source:
234 arcname = py_arcname[s]
235 zipname = str(s)
236 zf.write(zipname, arcname)
237 zf.close()
238
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)
242
243 ########################################################################
244 #
245 # Define binaries. Each different build type (debug, opt, etc.) gets
246 # a slightly different build environment.
247 #
248
249 # List of constructed environments to pass back to SConstruct
250 envList = []
251
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
256 # date.cc.
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)
264 return objs
265
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)
272 newEnv.Label = label
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))
277 if strip:
278 stripped_bin = bin + '.stripped'
279 if sys.platform == 'sunos5':
280 cmd = 'cp $SOURCE $TARGET; strip $TARGET'
281 else:
282 cmd = 'strip $SOURCE -o $TARGET'
283 newEnv.Command(stripped_bin, bin, cmd)
284 bin = stripped_bin
285 targets = newEnv.Concat(exe, [bin, 'm5py.zip'])
286 newEnv.M5Binary = targets[0]
287 envList.append(newEnv)
288
289 # Debug binary
290 ccflags = {}
291 if env['GCC']:
292 if sys.platform == 'sunos5':
293 ccflags['debug'] = '-gstabs+'
294 else:
295 ccflags['debug'] = '-ggdb3'
296 ccflags['opt'] = '-g -O3'
297 ccflags['fast'] = '-O3'
298 ccflags['prof'] = '-O3 -g -pg'
299 elif env['SUNCC']:
300 ccflags['debug'] = '-g0'
301 ccflags['opt'] = '-g -O'
302 ccflags['fast'] = '-fast'
303 ccflags['prof'] = '-fast -g -pg'
304 elif env['ICC']:
305 ccflags['debug'] = '-g -O0'
306 ccflags['opt'] = '-g -O'
307 ccflags['fast'] = '-fast'
308 ccflags['prof'] = '-fast -g -pg'
309 else:
310 print 'Unknown compiler, please fix compiler options'
311 Exit(1)
312
313 makeEnv('debug', '.do',
314 CCFLAGS = Split(ccflags['debug']),
315 CPPDEFINES = ['DEBUG', 'TRACING_ON=1'])
316
317 # Optimized binary
318 makeEnv('opt', '.o',
319 CCFLAGS = Split(ccflags['opt']),
320 CPPDEFINES = ['TRACING_ON=1'])
321
322 # "Fast" binary
323 makeEnv('fast', '.fo', strip = True,
324 CCFLAGS = Split(ccflags['fast']),
325 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'])
326
327 # Profiled binary
328 makeEnv('prof', '.po',
329 CCFLAGS = Split(ccflags['prof']),
330 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
331 LINKFLAGS = '-pg')
332
333 Return('envList')