Home | History | Annotate | Download | only in v8
      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 
     28 import platform
     29 import re
     30 import sys
     31 import os
     32 from os.path import join, dirname, abspath
     33 from types import DictType, StringTypes
     34 root_dir = dirname(File('SConstruct').rfile().abspath)
     35 sys.path.append(join(root_dir, 'tools'))
     36 import 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.
     41 ANDROID_TOP = os.environ.get('TOP')
     42 if 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
     48 if os.environ.get('GCC_VERSION') == '44':
     49     GCC_EXTRA_CCFLAGS = ['-fno-tree-vrp']
     50     GCC_DTOA_EXTRA_CCFLAGS = ['-fno-strict-aliasing']
     51 else:
     52     GCC_EXTRA_CCFLAGS = []
     53     GCC_DTOA_EXTRA_CCFLAGS = []
     54 
     55 ANDROID_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 
     74 ANDROID_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 
     85 ANDROID_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 
     96 LIBRARY_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 
    266 V8_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 
    317 MKSNAPSHOT_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 
    348 DTOA_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 
    363 CCTEST_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 
    423 SAMPLE_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 
    555 D8_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 
    593 SUFFIXES = {
    594   'release': '',
    595   'debug': '_g'
    596 }
    597 
    598 
    599 def Abort(message):
    600   print message
    601   sys.exit(1)
    602 
    603 
    604 def 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 
    614 OS_GUESS = utils.GuessOS()
    615 TOOLCHAIN_GUESS = GuessToolchain(OS_GUESS)
    616 ARCH_GUESS = utils.GuessArchitecture()
    617 
    618 
    619 SIMPLE_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 
    718 def 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 
    730 def 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 
    753 def 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 
    761 def 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 
    773 def SplitList(str):
    774   return [ s for s in str.split(",") if len(s) > 0 ]
    775 
    776 
    777 def 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 
    786 def 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 
    812 class 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 
    886 def 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 
    908 def 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 
    923 def 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 
   1029 def 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.
   1069 try:
   1070   SetOption('warn', 'no-deprecated')
   1071 except:
   1072   pass
   1073 
   1074 
   1075 Build()
   1076