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