blob: b5aa7abadbb0b01b938eb2784aad94fe91714d5a [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001# Copyright 2008 the V8 project authors. 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
29import re
30import sys
31import os
32from os.path import join, dirname, abspath
33from types import DictType, StringTypes
34root_dir = dirname(File('SConstruct').rfile().abspath)
35sys.path.append(join(root_dir, 'tools'))
36import js2c, utils
37
38
39# ANDROID_TOP is the top of the Android checkout, fetched from the environment
40# variable 'TOP'. You will also need to set the CXX, CC, AR and RANLIB
41# environment variables to the cross-compiling tools.
42ANDROID_TOP = os.environ.get('TOP')
43if ANDROID_TOP is None:
44 ANDROID_TOP=""
45
46# TODO: Sort these issues out properly but as a temporary solution for gcc 4.4
47# on linux we need these compiler flags to avoid crashes in the v8 test suite
48# and avoid dtoa.c strict aliasing issues
49if os.environ.get('GCC_VERSION') == '44':
50 GCC_EXTRA_CCFLAGS = ['-fno-tree-vrp']
51 GCC_DTOA_EXTRA_CCFLAGS = ['-fno-strict-aliasing']
52else:
53 GCC_EXTRA_CCFLAGS = []
54 GCC_DTOA_EXTRA_CCFLAGS = []
55
56ANDROID_FLAGS = ['-march=armv5te',
57 '-mtune=xscale',
58 '-msoft-float',
59 '-fpic',
60 '-mthumb-interwork',
61 '-funwind-tables',
62 '-fstack-protector',
63 '-fno-short-enums',
64 '-fmessage-length=0',
65 '-finline-functions',
66 '-fno-inline-functions-called-once',
67 '-fgcse-after-reload',
68 '-frerun-cse-after-loop',
69 '-frename-registers',
70 '-fomit-frame-pointer',
71 '-fno-strict-aliasing',
72 '-finline-limit=64',
73 '-MD']
74
75ANDROID_INCLUDES = [ANDROID_TOP + '/bionic/libc/arch-arm/include',
76 ANDROID_TOP + '/bionic/libc/include',
77 ANDROID_TOP + '/bionic/libstdc++/include',
78 ANDROID_TOP + '/bionic/libc/kernel/common',
79 ANDROID_TOP + '/bionic/libc/kernel/arch-arm',
80 ANDROID_TOP + '/bionic/libm/include',
81 ANDROID_TOP + '/bionic/libm/include/arch/arm',
82 ANDROID_TOP + '/bionic/libthread_db/include',
83 ANDROID_TOP + '/frameworks/base/include',
84 ANDROID_TOP + '/system/core/include']
85
86ANDROID_LINKFLAGS = ['-nostdlib',
87 '-Bdynamic',
88 '-Wl,-T,' + ANDROID_TOP + '/build/core/armelf.x',
89 '-Wl,-dynamic-linker,/system/bin/linker',
90 '-Wl,--gc-sections',
91 '-Wl,-z,nocopyreloc',
92 '-Wl,-rpath-link=' + ANDROID_TOP + '/out/target/product/generic/obj/lib',
93 ANDROID_TOP + '/out/target/product/generic/obj/lib/crtbegin_dynamic.o',
94 ANDROID_TOP + '/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/lib/gcc/arm-eabi/4.2.1/interwork/libgcc.a',
95 ANDROID_TOP + '/out/target/product/generic/obj/lib/crtend_android.o'];
96
97LIBRARY_FLAGS = {
98 'all': {
99 'CPPPATH': [join(root_dir, 'src')],
100 'regexp:native': {
101 'CPPDEFINES': ['V8_NATIVE_REGEXP']
102 },
103 'mode:debug': {
104 'CPPDEFINES': ['V8_ENABLE_CHECKS']
105 },
106 'profilingsupport:on': {
107 'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING'],
108 },
109 'debuggersupport:on': {
110 'CPPDEFINES': ['ENABLE_DEBUGGER_SUPPORT'],
111 }
112 },
113 'gcc': {
114 'all': {
115 'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS'],
116 'CXXFLAGS': ['$CCFLAGS', '-fno-rtti', '-fno-exceptions'],
117 },
118 'visibility:hidden': {
119 # Use visibility=default to disable this.
120 'CXXFLAGS': ['-fvisibility=hidden']
121 },
122 'mode:debug': {
123 'CCFLAGS': ['-g', '-O0'],
124 'CPPDEFINES': ['ENABLE_DISASSEMBLER', 'DEBUG'],
125 'os:android': {
126 'CCFLAGS': ['-mthumb']
127 }
128 },
129 'mode:release': {
130 'CCFLAGS': ['-O3', '-fomit-frame-pointer', '-fdata-sections',
131 '-ffunction-sections'],
132 'os:android': {
133 'CCFLAGS': ['-mthumb', '-Os'],
134 'CPPDEFINES': ['SK_RELEASE', 'NDEBUG']
135 }
136 },
137 'os:linux': {
138 'CCFLAGS': ['-ansi'] + GCC_EXTRA_CCFLAGS,
139 'library:shared': {
140 'CPPDEFINES': ['V8_SHARED'],
141 'LIBS': ['pthread']
142 }
143 },
144 'os:macos': {
145 'CCFLAGS': ['-ansi', '-mmacosx-version-min=10.4'],
146 },
147 'os:freebsd': {
148 'CPPPATH' : ['/usr/local/include'],
149 'LIBPATH' : ['/usr/local/lib'],
150 'CCFLAGS': ['-ansi'],
151 },
152 'os:win32': {
153 'CCFLAGS': ['-DWIN32'],
154 'CXXFLAGS': ['-DWIN32'],
155 },
156 'os:android': {
157 'CPPDEFINES': ['ANDROID', '__ARM_ARCH_5__', '__ARM_ARCH_5T__',
158 '__ARM_ARCH_5E__', '__ARM_ARCH_5TE__'],
159 'CCFLAGS': ANDROID_FLAGS,
160 'WARNINGFLAGS': ['-Wall', '-Wno-unused', '-Werror=return-type',
161 '-Wstrict-aliasing=2'],
162 'CPPPATH': ANDROID_INCLUDES,
163 },
164 'arch:ia32': {
165 'CPPDEFINES': ['V8_TARGET_ARCH_IA32'],
166 'CCFLAGS': ['-m32'],
167 'LINKFLAGS': ['-m32']
168 },
169 'arch:arm': {
170 'CPPDEFINES': ['V8_TARGET_ARCH_ARM']
171 },
172 'simulator:arm': {
173 'CCFLAGS': ['-m32'],
174 'LINKFLAGS': ['-m32']
175 },
176 'arch:x64': {
177 'CPPDEFINES': ['V8_TARGET_ARCH_X64'],
178 'CCFLAGS': ['-m64'],
179 'LINKFLAGS': ['-m64'],
180 },
181 'prof:oprofile': {
182 'CPPDEFINES': ['ENABLE_OPROFILE_AGENT']
183 }
184 },
185 'msvc': {
186 'all': {
187 'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS'],
188 'CXXFLAGS': ['$CCFLAGS', '/GR-', '/Gy'],
189 'CPPDEFINES': ['WIN32'],
190 'LINKFLAGS': ['/INCREMENTAL:NO', '/NXCOMPAT', '/IGNORE:4221'],
191 'CCPDBFLAGS': ['/Zi']
192 },
193 'verbose:off': {
194 'DIALECTFLAGS': ['/nologo'],
195 'ARFLAGS': ['/NOLOGO']
196 },
197 'arch:ia32': {
198 'CPPDEFINES': ['V8_TARGET_ARCH_IA32', '_USE_32BIT_TIME_T'],
199 'LINKFLAGS': ['/MACHINE:X86'],
200 'ARFLAGS': ['/MACHINE:X86']
201 },
202 'arch:x64': {
203 'CPPDEFINES': ['V8_TARGET_ARCH_X64'],
204 'LINKFLAGS': ['/MACHINE:X64'],
205 'ARFLAGS': ['/MACHINE:X64']
206 },
207 'mode:debug': {
208 'CCFLAGS': ['/Od', '/Gm'],
209 'CPPDEFINES': ['_DEBUG', 'ENABLE_DISASSEMBLER', 'DEBUG'],
210 'LINKFLAGS': ['/DEBUG'],
211 'msvcrt:static': {
212 'CCFLAGS': ['/MTd']
213 },
214 'msvcrt:shared': {
215 'CCFLAGS': ['/MDd']
216 }
217 },
218 'mode:release': {
219 'CCFLAGS': ['/O2'],
220 'LINKFLAGS': ['/OPT:REF', '/OPT:ICF'],
221 'msvcrt:static': {
222 'CCFLAGS': ['/MT']
223 },
224 'msvcrt:shared': {
225 'CCFLAGS': ['/MD']
226 },
227 'msvcltcg:on': {
228 'CCFLAGS': ['/GL'],
229 'LINKFLAGS': ['/LTCG'],
230 'ARFLAGS': ['/LTCG'],
231 }
232 }
233 }
234}
235
236
237V8_EXTRA_FLAGS = {
238 'gcc': {
239 'all': {
240 'WARNINGFLAGS': ['-Wall',
241 '-Werror',
242 '-W',
243 '-Wno-unused-parameter',
244 '-Wnon-virtual-dtor']
245 },
246 'os:win32': {
247 'WARNINGFLAGS': ['-pedantic', '-Wno-long-long']
248 },
249 'os:linux': {
250 'WARNINGFLAGS': ['-pedantic'],
251 'library:shared': {
252 'soname:on': {
253 'LINKFLAGS': ['-Wl,-soname,${SONAME}']
254 }
255 }
256 },
257 'os:macos': {
258 'WARNINGFLAGS': ['-pedantic']
259 },
260 'disassembler:on': {
261 'CPPDEFINES': ['ENABLE_DISASSEMBLER']
262 }
263 },
264 'msvc': {
265 'all': {
266 'WARNINGFLAGS': ['/WX', '/wd4355', '/wd4800']
267 },
268 'library:shared': {
269 'CPPDEFINES': ['BUILDING_V8_SHARED'],
270 'LIBS': ['winmm', 'ws2_32']
271 },
272 'arch:ia32': {
273 'WARNINGFLAGS': ['/W3']
274 },
275 'arch:x64': {
276 'WARNINGFLAGS': ['/W2']
277 },
278 'arch:arm': {
279 'CPPDEFINES': ['V8_TARGET_ARCH_ARM'],
280 # /wd4996 is to silence the warning about sscanf
281 # used by the arm simulator.
282 'WARNINGFLAGS': ['/wd4996']
283 },
284 'disassembler:on': {
285 'CPPDEFINES': ['ENABLE_DISASSEMBLER']
286 }
287 }
288}
289
290
291MKSNAPSHOT_EXTRA_FLAGS = {
292 'gcc': {
293 'os:linux': {
294 'LIBS': ['pthread'],
295 },
296 'os:macos': {
297 'LIBS': ['pthread'],
298 },
299 'os:freebsd': {
300 'LIBS': ['execinfo', 'pthread']
301 },
302 'os:win32': {
303 'LIBS': ['winmm', 'ws2_32'],
304 },
305 },
306 'msvc': {
307 'all': {
308 'CPPDEFINES': ['_HAS_EXCEPTIONS=0'],
309 'LIBS': ['winmm', 'ws2_32']
310 }
311 }
312}
313
314
315DTOA_EXTRA_FLAGS = {
316 'gcc': {
317 'all': {
318 'WARNINGFLAGS': ['-Werror', '-Wno-uninitialized'],
319 'CCFLAGS': GCC_DTOA_EXTRA_CCFLAGS
320 }
321 },
322 'msvc': {
323 'all': {
324 'WARNINGFLAGS': ['/WX', '/wd4018', '/wd4244']
325 }
326 }
327}
328
329
330CCTEST_EXTRA_FLAGS = {
331 'all': {
332 'CPPPATH': [join(root_dir, 'src')],
333 'LIBS': ['$LIBRARY']
334 },
335 'gcc': {
336 'all': {
337 'LIBPATH': [abspath('.')]
338 },
339 'os:linux': {
340 'LIBS': ['pthread'],
341 },
342 'os:macos': {
343 'LIBS': ['pthread'],
344 },
345 'os:freebsd': {
346 'LIBS': ['execinfo', 'pthread']
347 },
348 'os:win32': {
349 'LIBS': ['winmm', 'ws2_32']
350 },
351 'os:android': {
352 'CPPDEFINES': ['ANDROID', '__ARM_ARCH_5__', '__ARM_ARCH_5T__',
353 '__ARM_ARCH_5E__', '__ARM_ARCH_5TE__'],
354 'CCFLAGS': ANDROID_FLAGS,
355 'CPPPATH': ANDROID_INCLUDES,
356 'LIBPATH': [ANDROID_TOP + '/out/target/product/generic/obj/lib'],
357 'LINKFLAGS': ANDROID_LINKFLAGS,
358 'LIBS': ['log', 'c', 'stdc++', 'm'],
359 'mode:release': {
360 'CPPDEFINES': ['SK_RELEASE', 'NDEBUG']
361 }
362 },
363 },
364 'msvc': {
365 'all': {
366 'CPPDEFINES': ['_HAS_EXCEPTIONS=0'],
367 'LIBS': ['winmm', 'ws2_32']
368 },
369 'library:shared': {
370 'CPPDEFINES': ['USING_V8_SHARED']
371 },
372 'arch:ia32': {
373 'CPPDEFINES': ['V8_TARGET_ARCH_IA32']
374 },
375 'arch:x64': {
376 'CPPDEFINES': ['V8_TARGET_ARCH_X64']
377 },
378 }
379}
380
381
382SAMPLE_FLAGS = {
383 'all': {
384 'CPPPATH': [join(abspath('.'), 'include')],
385 'LIBS': ['$LIBRARY'],
386 },
387 'gcc': {
388 'all': {
389 'LIBPATH': ['.'],
390 'CCFLAGS': ['-fno-rtti', '-fno-exceptions']
391 },
392 'os:linux': {
393 'LIBS': ['pthread'],
394 },
395 'os:macos': {
396 'LIBS': ['pthread'],
397 },
398 'os:freebsd': {
399 'LIBPATH' : ['/usr/local/lib'],
400 'LIBS': ['execinfo', 'pthread']
401 },
402 'os:win32': {
403 'LIBS': ['winmm', 'ws2_32']
404 },
405 'os:android': {
406 'CPPDEFINES': ['ANDROID', '__ARM_ARCH_5__', '__ARM_ARCH_5T__',
407 '__ARM_ARCH_5E__', '__ARM_ARCH_5TE__'],
408 'CCFLAGS': ANDROID_FLAGS,
409 'CPPPATH': ANDROID_INCLUDES,
410 'LIBPATH': [ANDROID_TOP + '/out/target/product/generic/obj/lib'],
411 'LINKFLAGS': ANDROID_LINKFLAGS,
412 'LIBS': ['log', 'c', 'stdc++', 'm'],
413 'mode:release': {
414 'CPPDEFINES': ['SK_RELEASE', 'NDEBUG']
415 }
416 },
417 'arch:ia32': {
418 'CCFLAGS': ['-m32'],
419 'LINKFLAGS': ['-m32']
420 },
421 'arch:x64': {
422 'CCFLAGS': ['-m64'],
423 'LINKFLAGS': ['-m64']
424 },
425 'simulator:arm': {
426 'CCFLAGS': ['-m32'],
427 'LINKFLAGS': ['-m32']
428 },
429 'mode:release': {
430 'CCFLAGS': ['-O2']
431 },
432 'mode:debug': {
433 'CCFLAGS': ['-g', '-O0']
434 },
435 'prof:oprofile': {
436 'LIBPATH': ['/usr/lib32', '/usr/lib32/oprofile'],
437 'LIBS': ['opagent']
438 }
439 },
440 'msvc': {
441 'all': {
442 'LIBS': ['winmm', 'ws2_32']
443 },
444 'verbose:off': {
445 'CCFLAGS': ['/nologo'],
446 'LINKFLAGS': ['/NOLOGO']
447 },
448 'verbose:on': {
449 'LINKFLAGS': ['/VERBOSE']
450 },
451 'library:shared': {
452 'CPPDEFINES': ['USING_V8_SHARED']
453 },
454 'prof:on': {
455 'LINKFLAGS': ['/MAP']
456 },
457 'mode:release': {
458 'CCFLAGS': ['/O2'],
459 'LINKFLAGS': ['/OPT:REF', '/OPT:ICF'],
460 'msvcrt:static': {
461 'CCFLAGS': ['/MT']
462 },
463 'msvcrt:shared': {
464 'CCFLAGS': ['/MD']
465 },
466 'msvcltcg:on': {
467 'CCFLAGS': ['/GL'],
468 'LINKFLAGS': ['/LTCG'],
469 }
470 },
471 'arch:ia32': {
472 'CPPDEFINES': ['V8_TARGET_ARCH_IA32'],
473 'LINKFLAGS': ['/MACHINE:X86']
474 },
475 'arch:x64': {
476 'CPPDEFINES': ['V8_TARGET_ARCH_X64'],
477 'LINKFLAGS': ['/MACHINE:X64']
478 },
479 'mode:debug': {
480 'CCFLAGS': ['/Od'],
481 'LINKFLAGS': ['/DEBUG'],
482 'msvcrt:static': {
483 'CCFLAGS': ['/MTd']
484 },
485 'msvcrt:shared': {
486 'CCFLAGS': ['/MDd']
487 }
488 }
489 }
490}
491
492
493D8_FLAGS = {
494 'gcc': {
495 'console:readline': {
496 'LIBS': ['readline']
497 },
498 'os:linux': {
499 'LIBS': ['pthread'],
500 },
501 'os:macos': {
502 'LIBS': ['pthread'],
503 },
504 'os:freebsd': {
505 'LIBS': ['pthread'],
506 },
507 'os:android': {
508 'LIBPATH': [ANDROID_TOP + '/out/target/product/generic/obj/lib'],
509 'LINKFLAGS': ANDROID_LINKFLAGS,
510 'LIBS': ['log', 'c', 'stdc++', 'm'],
511 },
512 'os:win32': {
513 'LIBS': ['winmm', 'ws2_32'],
514 },
515 },
516 'msvc': {
517 'all': {
518 'LIBS': ['winmm', 'ws2_32']
519 }
520 }
521}
522
523
524SUFFIXES = {
525 'release': '',
526 'debug': '_g'
527}
528
529
530def Abort(message):
531 print message
532 sys.exit(1)
533
534
535def GuessToolchain(os):
536 tools = Environment()['TOOLS']
537 if 'gcc' in tools:
538 return 'gcc'
539 elif 'msvc' in tools:
540 return 'msvc'
541 else:
542 return None
543
544
545OS_GUESS = utils.GuessOS()
546TOOLCHAIN_GUESS = GuessToolchain(OS_GUESS)
547ARCH_GUESS = utils.GuessArchitecture()
548
549
550SIMPLE_OPTIONS = {
551 'toolchain': {
552 'values': ['gcc', 'msvc'],
553 'default': TOOLCHAIN_GUESS,
554 'help': 'the toolchain to use (' + TOOLCHAIN_GUESS + ')'
555 },
556 'os': {
557 'values': ['freebsd', 'linux', 'macos', 'win32', 'android'],
558 'default': OS_GUESS,
559 'help': 'the os to build for (' + OS_GUESS + ')'
560 },
561 'arch': {
562 'values':['arm', 'ia32', 'x64'],
563 'default': ARCH_GUESS,
564 'help': 'the architecture to build for (' + ARCH_GUESS + ')'
565 },
566 'regexp': {
567 'values': ['native', 'interpreted'],
568 'default': 'native',
569 'help': 'Whether to use native or interpreted regexp implementation'
570 },
571 'snapshot': {
572 'values': ['on', 'off', 'nobuild'],
573 'default': 'off',
574 'help': 'build using snapshots for faster start-up'
575 },
576 'prof': {
577 'values': ['on', 'off', 'oprofile'],
578 'default': 'off',
579 'help': 'enable profiling of build target'
580 },
581 'library': {
582 'values': ['static', 'shared'],
583 'default': 'static',
584 'help': 'the type of library to produce'
585 },
586 'profilingsupport': {
587 'values': ['on', 'off'],
588 'default': 'on',
589 'help': 'enable profiling of JavaScript code'
590 },
591 'debuggersupport': {
592 'values': ['on', 'off'],
593 'default': 'on',
594 'help': 'enable debugging of JavaScript code'
595 },
596 'soname': {
597 'values': ['on', 'off'],
598 'default': 'off',
599 'help': 'turn on setting soname for Linux shared library'
600 },
601 'msvcrt': {
602 'values': ['static', 'shared'],
603 'default': 'static',
604 'help': 'the type of Microsoft Visual C++ runtime library to use'
605 },
606 'msvcltcg': {
607 'values': ['on', 'off'],
608 'default': 'on',
609 'help': 'use Microsoft Visual C++ link-time code generation'
610 },
611 'simulator': {
612 'values': ['arm', 'none'],
613 'default': 'none',
614 'help': 'build with simulator'
615 },
616 'disassembler': {
617 'values': ['on', 'off'],
618 'default': 'off',
619 'help': 'enable the disassembler to inspect generated code'
620 },
621 'sourcesignatures': {
622 'values': ['MD5', 'timestamp'],
623 'default': 'MD5',
624 'help': 'set how the build system detects file changes'
625 },
626 'console': {
627 'values': ['dumb', 'readline'],
628 'default': 'dumb',
629 'help': 'the console to use for the d8 shell'
630 },
631 'verbose': {
632 'values': ['on', 'off'],
633 'default': 'off',
634 'help': 'more output from compiler and linker'
635 },
636 'visibility': {
637 'values': ['default', 'hidden'],
638 'default': 'hidden',
639 'help': 'shared library symbol visibility'
640 }
641}
642
643
644def GetOptions():
645 result = Options()
646 result.Add('mode', 'compilation mode (debug, release)', 'release')
647 result.Add('sample', 'build sample (shell, process)', '')
648 result.Add('env', 'override environment settings (NAME0:value0,NAME1:value1,...)', '')
649 result.Add('importenv', 'import environment settings (NAME0,NAME1,...)', '')
650 for (name, option) in SIMPLE_OPTIONS.iteritems():
651 help = '%s (%s)' % (name, ", ".join(option['values']))
652 result.Add(name, help, option.get('default'))
653 return result
654
655
656def GetVersionComponents():
657 MAJOR_VERSION_PATTERN = re.compile(r"#define\s+MAJOR_VERSION\s+(.*)")
658 MINOR_VERSION_PATTERN = re.compile(r"#define\s+MINOR_VERSION\s+(.*)")
659 BUILD_NUMBER_PATTERN = re.compile(r"#define\s+BUILD_NUMBER\s+(.*)")
660 PATCH_LEVEL_PATTERN = re.compile(r"#define\s+PATCH_LEVEL\s+(.*)")
661
662 patterns = [MAJOR_VERSION_PATTERN,
663 MINOR_VERSION_PATTERN,
664 BUILD_NUMBER_PATTERN,
665 PATCH_LEVEL_PATTERN]
666
667 source = open(join(root_dir, 'src', 'version.cc')).read()
668 version_components = []
669 for pattern in patterns:
670 match = pattern.search(source)
671 if match:
672 version_components.append(match.group(1).strip())
673 else:
674 version_components.append('0')
675
676 return version_components
677
678
679def GetVersion():
680 version_components = GetVersionComponents()
681
682 if version_components[len(version_components) - 1] == '0':
683 version_components.pop()
684 return '.'.join(version_components)
685
686
687def GetSpecificSONAME():
688 SONAME_PATTERN = re.compile(r"#define\s+SONAME\s+\"(.*)\"")
689
690 source = open(join(root_dir, 'src', 'version.cc')).read()
691 match = SONAME_PATTERN.search(source)
692
693 if match:
694 return match.group(1).strip()
695 else:
696 return ''
697
698
699def SplitList(str):
700 return [ s for s in str.split(",") if len(s) > 0 ]
701
702
703def IsLegal(env, option, values):
704 str = env[option]
705 for s in SplitList(str):
706 if not s in values:
707 Abort("Illegal value for option %s '%s'." % (option, s))
708 return False
709 return True
710
711
712def VerifyOptions(env):
713 if not IsLegal(env, 'mode', ['debug', 'release']):
714 return False
715 if not IsLegal(env, 'sample', ["shell", "process"]):
716 return False
717 if not IsLegal(env, 'regexp', ["native", "interpreted"]):
718 return False
719 if env['os'] == 'win32' and env['library'] == 'shared' and env['prof'] == 'on':
720 Abort("Profiling on windows only supported for static library.")
721 if env['prof'] == 'oprofile' and env['os'] != 'linux':
722 Abort("OProfile is only supported on Linux.")
723 if env['os'] == 'win32' and env['soname'] == 'on':
724 Abort("Shared Object soname not applicable for Windows.")
725 if env['soname'] == 'on' and env['library'] == 'static':
726 Abort("Shared Object soname not applicable for static library.")
727 for (name, option) in SIMPLE_OPTIONS.iteritems():
728 if (not option.get('default')) and (name not in ARGUMENTS):
729 message = ("A value for option %s must be specified (%s)." %
730 (name, ", ".join(option['values'])))
731 Abort(message)
732 if not env[name] in option['values']:
733 message = ("Unknown %s value '%s'. Possible values are (%s)." %
734 (name, env[name], ", ".join(option['values'])))
735 Abort(message)
736
737
738class BuildContext(object):
739
740 def __init__(self, options, env_overrides, samples):
741 self.library_targets = []
742 self.mksnapshot_targets = []
743 self.cctest_targets = []
744 self.sample_targets = []
745 self.d8_targets = []
746 self.options = options
747 self.env_overrides = env_overrides
748 self.samples = samples
749 self.use_snapshot = (options['snapshot'] != 'off')
750 self.build_snapshot = (options['snapshot'] == 'on')
751 self.flags = None
752
753 def AddRelevantFlags(self, initial, flags):
754 result = initial.copy()
755 toolchain = self.options['toolchain']
756 if toolchain in flags:
757 self.AppendFlags(result, flags[toolchain].get('all'))
758 for option in sorted(self.options.keys()):
759 value = self.options[option]
760 self.AppendFlags(result, flags[toolchain].get(option + ':' + value))
761 self.AppendFlags(result, flags.get('all'))
762 return result
763
764 def AddRelevantSubFlags(self, options, flags):
765 self.AppendFlags(options, flags.get('all'))
766 for option in sorted(self.options.keys()):
767 value = self.options[option]
768 self.AppendFlags(options, flags.get(option + ':' + value))
769
770 def GetRelevantSources(self, source):
771 result = []
772 result += source.get('all', [])
773 for (name, value) in self.options.iteritems():
774 source_value = source.get(name + ':' + value, [])
775 if type(source_value) == dict:
776 result += self.GetRelevantSources(source_value)
777 else:
778 result += source_value
779 return sorted(result)
780
781 def AppendFlags(self, options, added):
782 if not added:
783 return
784 for (key, value) in added.iteritems():
785 if key.find(':') != -1:
786 self.AddRelevantSubFlags(options, { key: value })
787 else:
788 if not key in options:
789 options[key] = value
790 else:
791 prefix = options[key]
792 if isinstance(prefix, StringTypes): prefix = prefix.split()
793 options[key] = prefix + value
794
795 def ConfigureObject(self, env, input, **kw):
796 if (kw.has_key('CPPPATH') and env.has_key('CPPPATH')):
797 kw['CPPPATH'] += env['CPPPATH']
798 if self.options['library'] == 'static':
799 return env.StaticObject(input, **kw)
800 else:
801 return env.SharedObject(input, **kw)
802
803 def ApplyEnvOverrides(self, env):
804 if not self.env_overrides:
805 return
806 if type(env['ENV']) == DictType:
807 env['ENV'].update(**self.env_overrides)
808 else:
809 env['ENV'] = self.env_overrides
810
811
812def PostprocessOptions(options):
813 # Adjust architecture if the simulator option has been set
814 if (options['simulator'] != 'none') and (options['arch'] != options['simulator']):
815 if 'arch' in ARGUMENTS:
816 # Print a warning if arch has explicitly been set
817 print "Warning: forcing architecture to match simulator (%s)" % options['simulator']
818 options['arch'] = options['simulator']
819 if (options['prof'] != 'off') and (options['profilingsupport'] == 'off'):
820 # Print a warning if profiling is enabled without profiling support
821 print "Warning: forcing profilingsupport on when prof is on"
822 options['profilingsupport'] = 'on'
823
824
825def ParseEnvOverrides(arg, imports):
826 # The environment overrides are in the format NAME0:value0,NAME1:value1,...
827 # The environment imports are in the format NAME0,NAME1,...
828 overrides = {}
829 for var in imports.split(','):
830 if var in os.environ:
831 overrides[var] = os.environ[var]
832 for override in arg.split(','):
833 pos = override.find(':')
834 if pos == -1:
835 continue
836 overrides[override[:pos].strip()] = override[pos+1:].strip()
837 return overrides
838
839
840def BuildSpecific(env, mode, env_overrides):
841 options = {'mode': mode}
842 for option in SIMPLE_OPTIONS:
843 options[option] = env[option]
844 PostprocessOptions(options)
845
846 context = BuildContext(options, env_overrides, samples=SplitList(env['sample']))
847
848 # Remove variables which can't be imported from the user's external
849 # environment into a construction environment.
850 user_environ = os.environ.copy()
851 try:
852 del user_environ['ENV']
853 except KeyError:
854 pass
855
856 library_flags = context.AddRelevantFlags(user_environ, LIBRARY_FLAGS)
857 v8_flags = context.AddRelevantFlags(library_flags, V8_EXTRA_FLAGS)
858 mksnapshot_flags = context.AddRelevantFlags(library_flags, MKSNAPSHOT_EXTRA_FLAGS)
859 dtoa_flags = context.AddRelevantFlags(library_flags, DTOA_EXTRA_FLAGS)
860 cctest_flags = context.AddRelevantFlags(v8_flags, CCTEST_EXTRA_FLAGS)
861 sample_flags = context.AddRelevantFlags(user_environ, SAMPLE_FLAGS)
862 d8_flags = context.AddRelevantFlags(library_flags, D8_FLAGS)
863
864 context.flags = {
865 'v8': v8_flags,
866 'mksnapshot': mksnapshot_flags,
867 'dtoa': dtoa_flags,
868 'cctest': cctest_flags,
869 'sample': sample_flags,
870 'd8': d8_flags
871 }
872
873 # Generate library base name.
874 target_id = mode
875 suffix = SUFFIXES[target_id]
876 library_name = 'v8' + suffix
877 version = GetVersion()
878 if context.options['soname'] == 'on':
879 # When building shared object with SONAME version the library name.
880 library_name += '-' + version
881 env['LIBRARY'] = library_name
882
883 # Generate library SONAME if required by the build.
884 if context.options['soname'] == 'on':
885 soname = GetSpecificSONAME()
886 if soname == '':
887 soname = 'lib' + library_name + '.so'
888 env['SONAME'] = soname
889
890 # Build the object files by invoking SCons recursively.
891 (object_files, shell_files, mksnapshot) = env.SConscript(
892 join('src', 'SConscript'),
893 build_dir=join('obj', target_id),
894 exports='context',
895 duplicate=False
896 )
897
898 context.mksnapshot_targets.append(mksnapshot)
899
900 # Link the object files into a library.
901 env.Replace(**context.flags['v8'])
902 context.ApplyEnvOverrides(env)
903 if context.options['library'] == 'static':
904 library = env.StaticLibrary(library_name, object_files)
905 else:
906 # There seems to be a glitch in the way scons decides where to put
907 # PDB files when compiling using MSVC so we specify it manually.
908 # This should not affect any other platforms.
909 pdb_name = library_name + '.dll.pdb'
910 library = env.SharedLibrary(library_name, object_files, PDB=pdb_name)
911 context.library_targets.append(library)
912
913 d8_env = Environment()
914 d8_env.Replace(**context.flags['d8'])
915 shell = d8_env.Program('d8' + suffix, object_files + shell_files)
916 context.d8_targets.append(shell)
917
918 for sample in context.samples:
919 sample_env = Environment(LIBRARY=library_name)
920 sample_env.Replace(**context.flags['sample'])
921 context.ApplyEnvOverrides(sample_env)
922 sample_object = sample_env.SConscript(
923 join('samples', 'SConscript'),
924 build_dir=join('obj', 'sample', sample, target_id),
925 exports='sample context',
926 duplicate=False
927 )
928 sample_name = sample + suffix
929 sample_program = sample_env.Program(sample_name, sample_object)
930 sample_env.Depends(sample_program, library)
931 context.sample_targets.append(sample_program)
932
933 cctest_program = env.SConscript(
934 join('test', 'cctest', 'SConscript'),
935 build_dir=join('obj', 'test', target_id),
936 exports='context object_files',
937 duplicate=False
938 )
939 context.cctest_targets.append(cctest_program)
940
941 return context
942
943
944def Build():
945 opts = GetOptions()
946 env = Environment(options=opts)
947 Help(opts.GenerateHelpText(env))
948 VerifyOptions(env)
949 env_overrides = ParseEnvOverrides(env['env'], env['importenv'])
950
951 SourceSignatures(env['sourcesignatures'])
952
953 libraries = []
954 mksnapshots = []
955 cctests = []
956 samples = []
957 d8s = []
958 modes = SplitList(env['mode'])
959 for mode in modes:
960 context = BuildSpecific(env.Copy(), mode, env_overrides)
961 libraries += context.library_targets
962 mksnapshots += context.mksnapshot_targets
963 cctests += context.cctest_targets
964 samples += context.sample_targets
965 d8s += context.d8_targets
966
967 env.Alias('library', libraries)
968 env.Alias('mksnapshot', mksnapshots)
969 env.Alias('cctests', cctests)
970 env.Alias('sample', samples)
971 env.Alias('d8', d8s)
972
973 if env['sample']:
974 env.Default('sample')
975 else:
976 env.Default('library')
977
978
979# We disable deprecation warnings because we need to be able to use
980# env.Copy without getting warnings for compatibility with older
981# version of scons. Also, there's a bug in some revisions that
982# doesn't allow this flag to be set, so we swallow any exceptions.
983# Lovely.
984try:
985 SetOption('warn', 'no-deprecated')
986except:
987 pass
988
989
990Build()