blob: 94fbd3dea046dc62d1bab77a7378c1f4bae9b024 [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'))
35import js2c
36
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'],
66 'CXXFLAGS': ['$CCFLAGS', '/GS-', '/GR-', '/Gy'],
67 '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'],
82 'LINKFLAGS': ['/OPT:REF']
83 }
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': {
173 'CPPPATH': [join(abspath('.'), 'public')],
174 '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 GuessArchitecture():
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000227 id = platform.machine()
228 if id.startswith('arm'):
229 return 'arm'
kasper.lund212ac232008-07-16 07:07:30 +0000230 elif (not id) or (not re.match('(x|i[3-6])86', id) is None):
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000231 return 'ia32'
232 else:
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000233 return None
234
235
236def GuessWordsize():
237 if '64' in platform.machine():
238 return '64'
239 else:
240 return '32'
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000241
242
243def GuessToolchain(os):
244 tools = Environment()['TOOLS']
245 if 'gcc' in tools:
kasper.lund7276f142008-07-30 08:49:36 +0000246 return 'gcc'
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000247 elif 'msvc' in tools:
248 return 'msvc'
249 else:
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000250 return None
251
252
253OS_GUESS = GuessOS()
254TOOLCHAIN_GUESS = GuessToolchain(OS_GUESS)
255ARCH_GUESS = GuessArchitecture()
256WORDSIZE_GUESS = GuessWordsize()
257
258
259SIMPLE_OPTIONS = {
260 'toolchain': {
261 'values': ['gcc', 'msvc'],
262 'default': TOOLCHAIN_GUESS,
263 'help': 'the toolchain to use'
264 },
265 'os': {
266 'values': ['linux', 'macos', 'win32'],
267 'default': OS_GUESS,
268 'help': 'the os to build for'
269 },
270 'arch': {
271 'values':['arm', 'ia32'],
272 'default': ARCH_GUESS,
273 'help': 'the architecture to build for'
274 },
275 'snapshot': {
276 'values': ['on', 'off'],
277 'default': 'off',
278 'help': 'build using snapshots for faster start-up'
279 },
280 'library': {
281 'values': ['static', 'shared'],
282 'default': 'static',
283 'help': 'the type of library to produce'
284 },
285 'wordsize': {
286 'values': ['64', '32'],
287 'default': WORDSIZE_GUESS,
288 'help': 'the word size'
289 },
290 'simulator': {
291 'values': ['arm', 'none'],
292 'default': 'none',
293 'help': 'build with simulator'
294 }
295}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000296
297
298def GetOptions():
299 result = Options()
kasper.lund7276f142008-07-30 08:49:36 +0000300 result.Add('mode', 'compilation mode (debug, release)', 'release')
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000301 result.Add('sample', 'build sample (shell, process)', '')
302 for (name, option) in SIMPLE_OPTIONS.items():
303 help = '%s (%s)' % (name, ", ".join(option['values']))
304 result.Add(name, help, option.get('default'))
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305 return result
306
307
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000308def SplitList(str):
309 return [ s for s in str.split(",") if len(s) > 0 ]
310
311
312def IsLegal(env, option, values):
313 str = env[option]
314 for s in SplitList(str):
315 if not s in values:
316 Abort("Illegal value for option %s '%s'." % (option, s))
317 return False
318 return True
319
320
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000321def VerifyOptions(env):
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000322 if not IsLegal(env, 'mode', ['debug', 'release']):
323 return False
324 if not IsLegal(env, 'sample', ["shell", "process"]):
325 return False
326 for (name, option) in SIMPLE_OPTIONS.items():
327 if (not option.get('default')) and (name not in ARGUMENTS):
328 message = ("A value for option %s must be specified (%s)." %
329 (name, ", ".join(option['values'])))
330 Abort(message)
331 if not env[name] in option['values']:
332 message = ("Unknown %s value '%s'. Possible values are (%s)." %
333 (name, env[name], ", ".join(option['values'])))
334 Abort(message)
335
336
337class BuildContext(object):
338
339 def __init__(self, options, samples):
340 self.library_targets = []
341 self.cctest_targets = []
342 self.sample_targets = []
343 self.options = options
344 self.samples = samples
345 self.use_snapshot = (options['snapshot'] == 'on')
346 self.flags = None
347
348 def AddRelevantFlags(self, initial, flags):
349 result = initial.copy()
350 self.AppendFlags(result, flags.get('all'))
351 toolchain = self.options['toolchain']
352 self.AppendFlags(result, flags[toolchain].get('all'))
353 for option in sorted(self.options.keys()):
354 value = self.options[option]
355 self.AppendFlags(result, flags[toolchain].get(option + ':' + value))
356 return result
357
358 def GetRelevantSources(self, source):
359 result = []
360 result += source.get('all', [])
361 for (name, value) in self.options.items():
362 result += source.get(name + ':' + value, [])
363 return sorted(result)
364
365 def AppendFlags(self, options, added):
366 if not added:
367 return
368 for (key, value) in added.items():
369 if not key in options:
370 options[key] = value
371 else:
372 options[key] = options[key] + value
373
374 def ConfigureObject(self, env, input, **kw):
375 if self.options['library'] == 'static':
376 return env.StaticObject(input, **kw)
377 else:
378 return env.SharedObject(input, **kw)
379
380
381def PostprocessOptions(options):
382 # Adjust architecture if the simulator option has been set
383 if (options['simulator'] != 'none') and (options['arch'] != options['simulator']):
384 if 'arch' in ARGUMENTS:
385 # Print a warning if arch has explicitly been set
386 print "Warning: forcing architecture to match simulator (%s)" % options['simulator']
387 options['arch'] = options['simulator']
388
389
390def BuildSpecific(env, mode):
391 options = {'mode': mode}
392 for option in SIMPLE_OPTIONS:
393 options[option] = env[option]
394 PostprocessOptions(options)
395
396 context = BuildContext(options, samples=SplitList(env['sample']))
397
398 library_flags = context.AddRelevantFlags(os.environ, LIBRARY_FLAGS)
399 v8_flags = context.AddRelevantFlags(library_flags, V8_EXTRA_FLAGS)
400 jscre_flags = context.AddRelevantFlags(library_flags, JSCRE_EXTRA_FLAGS)
401 dtoa_flags = context.AddRelevantFlags(library_flags, DTOA_EXTRA_FLAGS)
402 cctest_flags = context.AddRelevantFlags(v8_flags, CCTEST_EXTRA_FLAGS)
403 sample_flags = context.AddRelevantFlags(os.environ, SAMPLE_FLAGS)
404
405 context.flags = {
406 'v8': v8_flags,
407 'jscre': jscre_flags,
408 'dtoa': dtoa_flags,
409 'cctest': cctest_flags,
410 'sample': sample_flags
411 }
412
413 target_id = mode
414 suffix = SUFFIXES[target_id]
415 library_name = 'v8' + suffix
416 env['LIBRARY'] = library_name
417
418 # Build the object files by invoking SCons recursively.
419 object_files = env.SConscript(
420 join('src', 'SConscript'),
421 build_dir=join('obj', target_id),
422 exports='context',
423 duplicate=False
424 )
425
426 # Link the object files into a library.
427 if context.options['library'] == 'static':
428 library = env.StaticLibrary(library_name, object_files)
429 else:
430 # There seems to be a glitch in the way scons decides where to put
431 # PDB files when compiling using MSVC so we specify it manually.
432 # This should not affect any other platforms.
433 pdb_name = library_name + '.dll.pdb'
434 library = env.SharedLibrary(library_name, object_files, PDB=pdb_name)
435 context.library_targets.append(library)
436
437 for sample in context.samples:
438 sample_env = Environment(LIBRARY=library_name)
439 sample_env.Replace(**context.flags['sample'])
440 sample_object = sample_env.SConscript(
441 join('samples', 'SConscript'),
442 build_dir=join('obj', 'sample', sample, target_id),
443 exports='sample context',
444 duplicate=False
445 )
446 sample_name = sample + suffix
447 sample_program = sample_env.Program(sample_name, sample_object)
448 sample_env.Depends(sample_program, library)
449 context.sample_targets.append(sample_program)
450
451 cctest_program = env.SConscript(
452 join('test', 'cctest', 'SConscript'),
453 build_dir=join('obj', 'test', target_id),
454 exports='context object_files',
455 duplicate=False
456 )
457 context.cctest_targets.append(cctest_program)
458
459 return context
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000460
461
kasper.lund7276f142008-07-30 08:49:36 +0000462def Build():
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000463 opts = GetOptions()
464 env = Environment(options=opts)
465 Help(opts.GenerateHelpText(env))
466 VerifyOptions(env)
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000467
468 libraries = []
469 cctests = []
470 samples = []
471 modes = SplitList(env['mode'])
472 for mode in modes:
473 context = BuildSpecific(env.Copy(), mode)
474 libraries += context.library_targets
475 cctests += context.cctest_targets
476 samples += context.sample_targets
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000477
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000478 env.Alias('library', libraries)
479 env.Alias('cctests', cctests)
480 env.Alias('sample', samples)
481
482 if env['sample']:
483 env.Default('sample')
kasper.lund7276f142008-07-30 08:49:36 +0000484 else:
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000485 env.Default('library')
kasper.lund7276f142008-07-30 08:49:36 +0000486
487
488Build()