blob: 34f20d340ac733c67b54634de3816280530afcbd [file] [log] [blame]
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001# Copyright 2008 Google Inc. All rights reserved.
2# Redistribution and use in source and binary forms, with or without
3# modification, are permitted provided that the following conditions are
4# met:
5#
6# * Redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer.
8# * Redistributions in binary form must reproduce the above
9# copyright notice, this list of conditions and the following
10# disclaimer in the documentation and/or other materials provided
11# with the distribution.
12# * Neither the name of Google Inc. nor the names of its
13# contributors may be used to endorse or promote products derived
14# from this software without specific prior written permission.
15#
16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28import platform
kasper.lund212ac232008-07-16 07:07:30 +000029import re
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000030import sys
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000031import os
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000032from os.path import join, dirname, abspath
33root_dir = dirname(File('SConstruct').rfile().abspath)
34sys.path.append(join(root_dir, 'tools'))
ager@chromium.orgc27e4e72008-09-04 13:52:27 +000035import js2c, utils
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036
37
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000038LIBRARY_FLAGS = {
39 'all': {
40 'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING']
41 },
42 'gcc': {
43 'all': {
44 'DIALECTFLAGS': ['-ansi'],
45 'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS',
46 '-fno-strict-aliasing'],
47 'CXXFLAGS': ['$CCFLAGS', '-fno-rtti', '-fno-exceptions'],
48 'LIBS': ['pthread']
49 },
50 'mode:debug': {
51 'CCFLAGS': ['-g', '-O0'],
52 'CPPDEFINES': ['ENABLE_DISASSEMBLER', 'DEBUG']
53 },
54 'mode:release': {
55 'CCFLAGS': ['-O2']
56 },
57 'wordsize:64': {
58 'CCFLAGS': ['-m32']
59 },
60 },
61 'msvc': {
62 'all': {
63 'DIALECTFLAGS': ['/nologo'],
64 'WARNINGFLAGS': ['/W3', '/WX', '/wd4355', '/wd4800'],
65 'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS'],
v8.team.kasperl727e9952008-09-02 14:56:44 +000066 'CXXFLAGS': ['$CCFLAGS', '/GR-', '/Gy'],
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000067 'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE',
68 '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T',
69 'PCRE_STATIC'],
70 'LINKFLAGS': ['/NOLOGO', '/MACHINE:X86', '/INCREMENTAL:NO',
71 '/NXCOMPAT', '/IGNORE:4221'],
72 'ARFLAGS': ['/NOLOGO'],
73 'CCPDBFLAGS': ['/Zi']
74 },
75 'mode:debug': {
76 'CCFLAGS': ['/Od', '/Gm', '/MTd'],
77 'CPPDEFINES': ['_DEBUG', 'ENABLE_DISASSEMBLER', 'DEBUG'],
78 'LINKFLAGS': ['/DEBUG']
79 },
80 'mode:release': {
81 'CCFLAGS': ['/Ox', '/MT', '/Ob2', '/Oi', '/Oy'],
v8.team.kasperl727e9952008-09-02 14:56:44 +000082 'LINKFLAGS': ['/OPT:REF', '/OPT:ICF']
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000083 }
84 }
85}
86
87
88V8_EXTRA_FLAGS = {
89 'gcc': {
90 'all': {
91 'CXXFLAGS': [], #['-fvisibility=hidden'],
92 'WARNINGFLAGS': ['-pedantic', '-Wall', '-Werror', '-W',
93 '-Wno-unused-parameter']
94 },
95 'arch:arm': {
96 'CPPDEFINES': ['ARM']
97 },
98 },
99 'msvc': {
100 'all': {
101 'WARNINGFLAGS': ['/W3', '/WX', '/wd4355', '/wd4800']
102 },
103 'library:shared': {
104 'CPPDEFINES': ['BUILDING_V8_SHARED']
105 },
106 'arch:arm': {
107 'CPPDEFINES': ['ARM']
108 },
109 }
110}
111
112
113JSCRE_EXTRA_FLAGS = {
114 'gcc': {
115 'all': {
116 'CPPDEFINES': ['SUPPORT_UTF8', 'NO_RECURSE', 'SUPPORT_UCP'],
117 'WARNINGFLAGS': ['-w']
118 },
119 },
120 'msvc': {
121 'all': {
122 'CPPDEFINES': ['SUPPORT_UTF8', 'NO_RECURSE', 'SUPPORT_UCP'],
123 'WARNINGFLAGS': ['/W3', '/WX', '/wd4355', '/wd4800']
124 },
125 'library:shared': {
126 'CPPDEFINES': ['BUILDING_V8_SHARED']
127 }
128 }
129}
130
131
132DTOA_EXTRA_FLAGS = {
133 'gcc': {
134 'all': {
135 'WARNINGFLAGS': ['-Werror']
136 }
137 },
138 'msvc': {
139 'all': {
140 'WARNINGFLAGS': ['/WX', '/wd4018', '/wd4244']
141 }
142 }
143}
144
145
146CCTEST_EXTRA_FLAGS = {
147 'all': {
148 'CPPPATH': [join(root_dir, 'src')],
149 'LIBS': ['$LIBRARY']
150 },
151 'gcc': {
152 'all': {
153 'LIBPATH': [abspath('.')]
154 },
155 'wordsize:64': {
156 'CCFLAGS': ['-m32'],
157 'LINKFLAGS': ['-m32']
158 },
159 },
160 'msvc': {
161 'all': {
162 'CPPDEFINES': ['_HAS_EXCEPTIONS=0']
163 },
164 'library:shared': {
165 'CPPDEFINES': ['USING_V8_SHARED']
166 }
167 }
168}
169
170
171SAMPLE_FLAGS = {
172 'all': {
v8.team.kasperl727e9952008-09-02 14:56:44 +0000173 'CPPPATH': [join(abspath('.'), 'include')],
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000174 'LIBS': ['$LIBRARY'],
175 },
176 'gcc': {
177 'all': {
178 'LIBS': ['pthread'],
179 'LIBPATH': ['.']
180 },
181 'wordsize:64': {
182 'CCFLAGS': ['-m32'],
183 'LINKFLAGS': ['-m32']
184 },
185 },
186 'msvc': {
187 'all': {
188 'CCFLAGS': ['/nologo'],
189 },
190 'library:shared': {
191 'CPPDEFINES': ['USING_V8_SHARED']
192 },
193 'mode:release': {
194 'CCFLAGS': ['/MT'],
195 },
196 'mode:debug': {
197 'CCFLAGS': ['/MTd']
198 }
199 }
200}
201
202
203SUFFIXES = {
204 'release': '',
205 'debug': '_g'
206}
207
208
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000209def Abort(message):
210 print message
211 sys.exit(1)
212
213
214def GuessOS():
215 id = platform.system()
216 if id == 'Linux':
217 return 'linux'
218 elif id == 'Darwin':
219 return 'macos'
220 elif id == 'Windows':
221 return 'win32'
222 else:
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000223 return None
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000224
225
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000226def GuessWordsize():
227 if '64' in platform.machine():
228 return '64'
229 else:
230 return '32'
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000231
232
233def GuessToolchain(os):
234 tools = Environment()['TOOLS']
235 if 'gcc' in tools:
kasper.lund7276f142008-07-30 08:49:36 +0000236 return 'gcc'
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000237 elif 'msvc' in tools:
238 return 'msvc'
239 else:
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000240 return None
241
242
243OS_GUESS = GuessOS()
244TOOLCHAIN_GUESS = GuessToolchain(OS_GUESS)
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000245ARCH_GUESS = utils.GuessArchitecture()
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000246WORDSIZE_GUESS = GuessWordsize()
247
248
249SIMPLE_OPTIONS = {
250 'toolchain': {
251 'values': ['gcc', 'msvc'],
252 'default': TOOLCHAIN_GUESS,
253 'help': 'the toolchain to use'
254 },
255 'os': {
256 'values': ['linux', 'macos', 'win32'],
257 'default': OS_GUESS,
258 'help': 'the os to build for'
259 },
260 'arch': {
261 'values':['arm', 'ia32'],
262 'default': ARCH_GUESS,
263 'help': 'the architecture to build for'
264 },
265 'snapshot': {
266 'values': ['on', 'off'],
267 'default': 'off',
268 'help': 'build using snapshots for faster start-up'
269 },
270 'library': {
271 'values': ['static', 'shared'],
272 'default': 'static',
273 'help': 'the type of library to produce'
274 },
275 'wordsize': {
276 'values': ['64', '32'],
277 'default': WORDSIZE_GUESS,
278 'help': 'the word size'
279 },
280 'simulator': {
281 'values': ['arm', 'none'],
282 'default': 'none',
283 'help': 'build with simulator'
284 }
285}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000286
287
288def GetOptions():
289 result = Options()
kasper.lund7276f142008-07-30 08:49:36 +0000290 result.Add('mode', 'compilation mode (debug, release)', 'release')
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000291 result.Add('sample', 'build sample (shell, process)', '')
v8.team.kasperl727e9952008-09-02 14:56:44 +0000292 result.Add('env', 'override environment settings (NAME1:value1,NAME2:value2)', '')
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000293 for (name, option) in SIMPLE_OPTIONS.items():
294 help = '%s (%s)' % (name, ", ".join(option['values']))
295 result.Add(name, help, option.get('default'))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000296 return result
297
298
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000299def SplitList(str):
300 return [ s for s in str.split(",") if len(s) > 0 ]
301
302
303def IsLegal(env, option, values):
304 str = env[option]
305 for s in SplitList(str):
306 if not s in values:
307 Abort("Illegal value for option %s '%s'." % (option, s))
308 return False
309 return True
310
311
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000312def VerifyOptions(env):
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000313 if not IsLegal(env, 'mode', ['debug', 'release']):
314 return False
315 if not IsLegal(env, 'sample', ["shell", "process"]):
316 return False
317 for (name, option) in SIMPLE_OPTIONS.items():
318 if (not option.get('default')) and (name not in ARGUMENTS):
319 message = ("A value for option %s must be specified (%s)." %
320 (name, ", ".join(option['values'])))
321 Abort(message)
322 if not env[name] in option['values']:
323 message = ("Unknown %s value '%s'. Possible values are (%s)." %
324 (name, env[name], ", ".join(option['values'])))
325 Abort(message)
326
327
328class BuildContext(object):
329
v8.team.kasperl727e9952008-09-02 14:56:44 +0000330 def __init__(self, options, env_overrides, samples):
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000331 self.library_targets = []
332 self.cctest_targets = []
333 self.sample_targets = []
334 self.options = options
v8.team.kasperl727e9952008-09-02 14:56:44 +0000335 self.env_overrides = env_overrides
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000336 self.samples = samples
337 self.use_snapshot = (options['snapshot'] == 'on')
338 self.flags = None
339
340 def AddRelevantFlags(self, initial, flags):
341 result = initial.copy()
342 self.AppendFlags(result, flags.get('all'))
343 toolchain = self.options['toolchain']
344 self.AppendFlags(result, flags[toolchain].get('all'))
345 for option in sorted(self.options.keys()):
346 value = self.options[option]
347 self.AppendFlags(result, flags[toolchain].get(option + ':' + value))
348 return result
349
350 def GetRelevantSources(self, source):
351 result = []
352 result += source.get('all', [])
353 for (name, value) in self.options.items():
354 result += source.get(name + ':' + value, [])
355 return sorted(result)
356
357 def AppendFlags(self, options, added):
358 if not added:
359 return
360 for (key, value) in added.items():
361 if not key in options:
362 options[key] = value
363 else:
364 options[key] = options[key] + value
365
366 def ConfigureObject(self, env, input, **kw):
367 if self.options['library'] == 'static':
368 return env.StaticObject(input, **kw)
369 else:
370 return env.SharedObject(input, **kw)
371
372
373def PostprocessOptions(options):
374 # Adjust architecture if the simulator option has been set
375 if (options['simulator'] != 'none') and (options['arch'] != options['simulator']):
376 if 'arch' in ARGUMENTS:
377 # Print a warning if arch has explicitly been set
378 print "Warning: forcing architecture to match simulator (%s)" % options['simulator']
379 options['arch'] = options['simulator']
380
381
v8.team.kasperl727e9952008-09-02 14:56:44 +0000382def ParseEnvOverrides(arg):
383 # The environment overrides are in the format NAME1:value1,NAME2:value2
384 overrides = {}
385 for override in arg.split(','):
386 pos = override.find(':')
387 if pos == -1:
388 continue
389 overrides[override[:pos].strip()] = override[pos+1:].strip()
390 return overrides
391
392
393def BuildSpecific(env, mode, env_overrides):
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000394 options = {'mode': mode}
395 for option in SIMPLE_OPTIONS:
396 options[option] = env[option]
397 PostprocessOptions(options)
398
v8.team.kasperl727e9952008-09-02 14:56:44 +0000399 context = BuildContext(options, env_overrides, samples=SplitList(env['sample']))
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000400
401 library_flags = context.AddRelevantFlags(os.environ, LIBRARY_FLAGS)
402 v8_flags = context.AddRelevantFlags(library_flags, V8_EXTRA_FLAGS)
403 jscre_flags = context.AddRelevantFlags(library_flags, JSCRE_EXTRA_FLAGS)
404 dtoa_flags = context.AddRelevantFlags(library_flags, DTOA_EXTRA_FLAGS)
405 cctest_flags = context.AddRelevantFlags(v8_flags, CCTEST_EXTRA_FLAGS)
406 sample_flags = context.AddRelevantFlags(os.environ, SAMPLE_FLAGS)
407
408 context.flags = {
409 'v8': v8_flags,
410 'jscre': jscre_flags,
411 'dtoa': dtoa_flags,
412 'cctest': cctest_flags,
413 'sample': sample_flags
414 }
415
416 target_id = mode
417 suffix = SUFFIXES[target_id]
418 library_name = 'v8' + suffix
419 env['LIBRARY'] = library_name
420
421 # Build the object files by invoking SCons recursively.
422 object_files = env.SConscript(
423 join('src', 'SConscript'),
424 build_dir=join('obj', target_id),
425 exports='context',
426 duplicate=False
427 )
428
429 # Link the object files into a library.
430 if context.options['library'] == 'static':
431 library = env.StaticLibrary(library_name, object_files)
432 else:
433 # There seems to be a glitch in the way scons decides where to put
434 # PDB files when compiling using MSVC so we specify it manually.
435 # This should not affect any other platforms.
436 pdb_name = library_name + '.dll.pdb'
437 library = env.SharedLibrary(library_name, object_files, PDB=pdb_name)
438 context.library_targets.append(library)
439
440 for sample in context.samples:
441 sample_env = Environment(LIBRARY=library_name)
442 sample_env.Replace(**context.flags['sample'])
v8.team.kasperl727e9952008-09-02 14:56:44 +0000443 sample_env['ENV'].update(**context.env_overrides)
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000444 sample_object = sample_env.SConscript(
445 join('samples', 'SConscript'),
446 build_dir=join('obj', 'sample', sample, target_id),
447 exports='sample context',
448 duplicate=False
449 )
450 sample_name = sample + suffix
451 sample_program = sample_env.Program(sample_name, sample_object)
452 sample_env.Depends(sample_program, library)
453 context.sample_targets.append(sample_program)
454
455 cctest_program = env.SConscript(
456 join('test', 'cctest', 'SConscript'),
457 build_dir=join('obj', 'test', target_id),
458 exports='context object_files',
459 duplicate=False
460 )
461 context.cctest_targets.append(cctest_program)
462
463 return context
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000464
465
kasper.lund7276f142008-07-30 08:49:36 +0000466def Build():
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000467 opts = GetOptions()
468 env = Environment(options=opts)
469 Help(opts.GenerateHelpText(env))
470 VerifyOptions(env)
v8.team.kasperl727e9952008-09-02 14:56:44 +0000471 env_overrides = ParseEnvOverrides(env['env'])
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000472
473 libraries = []
474 cctests = []
475 samples = []
476 modes = SplitList(env['mode'])
477 for mode in modes:
v8.team.kasperl727e9952008-09-02 14:56:44 +0000478 context = BuildSpecific(env.Copy(), mode, env_overrides)
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000479 libraries += context.library_targets
480 cctests += context.cctest_targets
481 samples += context.sample_targets
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000482
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000483 env.Alias('library', libraries)
484 env.Alias('cctests', cctests)
485 env.Alias('sample', samples)
486
487 if env['sample']:
488 env.Default('sample')
kasper.lund7276f142008-07-30 08:49:36 +0000489 else:
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000490 env.Default('library')
kasper.lund7276f142008-07-30 08:49:36 +0000491
492
v8.team.kasperl727e9952008-09-02 14:56:44 +0000493# We disable deprecation warnings because we need to be able to use
494# env.Copy without getting warnings for compatibility with older
495# version of scons. Also, there's a bug in some revisions that
496# doesn't allow this flag to be set, so we swallow any exceptions.
497# Lovely.
498try:
499 SetOption('warn', 'no-deprecated')
500except:
501 pass
502
503
kasper.lund7276f142008-07-30 08:49:36 +0000504Build()