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