# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # /!\ Use js_option() instead of option() in this file. /!\ # ========================================================= @depends(build_project) def building_js(build_project): return build_project == 'js' # Exception to the rule above: JS_STANDALONE is a special option that doesn't # want the js_option treatment. When we're done merging js/src/configure and # top-level configure, it can go away, although the JS_STANDALONE config # will still need to be set depending on building_js above. option(env='JS_STANDALONE', default=building_js, help='Reserved for internal use') # Branding # ============================================================== js_option('--with-app-name', env='MOZ_APP_NAME', nargs=1, help='Used for e.g. the binary program file name. If not set, ' 'defaults to a lowercase form of MOZ_APP_BASENAME.') @depends('--with-app-name', 'JS_STANDALONE', moz_app_basename) def moz_app_name(value, js_standalone, moz_app_basename): if value: return value[0] if js_standalone: return 'js' return moz_app_basename.lower() set_config('MOZ_APP_NAME', moz_app_name) # SmooshMonkey (new frontend) # ================================================== # Define here in order to use the option from bindgen.configure. js_option('--enable-smoosh', default=False, help='Enable SmooshMonkey (new JS engine frontend)') @depends('--enable-smoosh') def enable_smoosh(value): if value: return True set_config('JS_ENABLE_SMOOSH', enable_smoosh) set_define('JS_ENABLE_SMOOSH', enable_smoosh) include('../build/moz.configure/nspr.configure', when='--enable-compile-environment') include('../build/moz.configure/rust.configure', when='--enable-compile-environment') include('../build/moz.configure/bindgen.configure', when='--enable-compile-environment') @depends('JS_STANDALONE') def js_standalone(value): if value: return True set_config('JS_STANDALONE', js_standalone) set_define('JS_STANDALONE', js_standalone) add_old_configure_assignment('JS_STANDALONE', js_standalone) js_option('--disable-js-shell', default=building_js, help='{Build|Do not build} the JS shell') @depends('--disable-js-shell') def js_disable_shell(value): if not value: return True set_config('JS_DISABLE_SHELL', js_disable_shell) set_define('JS_64BIT', depends(target)(lambda t: t.bitness == 64 or None)) set_define('JS_PUNBOX64', depends(target)(lambda t: t.bitness == 64 or None)) set_define('JS_NUNBOX32', depends(target)(lambda t: t.bitness == 32 or None)) # SpiderMonkey as a shared library, and how its symbols are exported # ================================================================== js_option('--disable-shared-js', when=js_standalone, help='{Create|Do not create} a shared library') js_option('--disable-export-js', when=js_standalone, help='{Mark|Do not mark} JS symbols as DLL exported/visible') @depends('--disable-shared-js', '--disable-export-js', when=js_standalone) def shared_js(shared_js, export_js): if shared_js: if not export_js: die('Must export JS symbols when building a shared library.') return True set_config('JS_SHARED_LIBRARY', shared_js) add_old_configure_assignment('JS_SHARED_LIBRARY', shared_js) @depends(shared_js, '--disable-export-js', when=js_standalone) def exportable_js_api(shared_js, export_js): if not shared_js and export_js: return True set_define('STATIC_EXPORTABLE_JS_API', exportable_js_api) @depends(shared_js, exportable_js_api) def static_js_api(shared_js, export_js): if not shared_js and not export_js: return True set_define('STATIC_JS_API', static_js_api) @depends(shared_js) def static_js(value): if not value: return True set_define('MOZ_STATIC_JS', static_js) js_option(env='NO_RUST_PANIC_HOOK', when=js_standalone, help='Disable rust panic hook') set_define('NO_RUST_PANIC_HOOK', True, when='NO_RUST_PANIC_HOOK') # JIT support # ======================================================= @depends(target) def jit_default(target): if target.cpu in ('x86', 'x86_64', 'arm', 'aarch64', 'mips32', 'mips64'): return True return False js_option('--enable-jit', default=jit_default, help='{Enable|Disable} use of the JITs') @deprecated_option('--enable-ion') def report_deprecated(value): if value: die('--enable-ion is deprecated, use --enable-jit instead') else: die('--disable-ion is deprecated, use --disable-jit instead') # JIT code simulator for cross compiles # ======================================================= js_option('--enable-simulator', choices=('arm', 'arm64', 'mips32', 'mips64'), nargs=1, help='Enable a JIT code simulator for the specified architecture') @depends('--enable-jit', '--enable-simulator', target, '--help') def simulator(jit_enabled, simulator_enabled, target, _): if not jit_enabled or not simulator_enabled: return sim_cpu = simulator_enabled[0] if sim_cpu in ('arm', 'mips32'): if target.cpu != 'x86': die('The %s simulator only works on x86.' % sim_cpu) if sim_cpu in ('arm64', 'mips64'): if target.cpu != 'x86_64': die('The %s simulator only works on x86-64.' % sim_cpu) return namespace(**{sim_cpu: True}) set_config('JS_SIMULATOR', depends_if(simulator)(lambda x: True)) set_config('JS_SIMULATOR_ARM', simulator.arm) set_config('JS_SIMULATOR_ARM64', simulator.arm64) set_config('JS_SIMULATOR_MIPS32', simulator.mips32) set_config('JS_SIMULATOR_MIPS64', simulator.mips64) set_define('JS_SIMULATOR', depends_if(simulator)(lambda x: True)) set_define('JS_SIMULATOR_ARM', simulator.arm) set_define('JS_SIMULATOR_ARM64', simulator.arm64) set_define('JS_SIMULATOR_MIPS32', simulator.mips32) set_define('JS_SIMULATOR_MIPS64', simulator.mips64) @depends('--enable-jit', simulator, target) def jit_codegen(jit_enabled, simulator, target): if not jit_enabled: return namespace(none=True) if simulator: return simulator if target.cpu == 'aarch64': return namespace(arm64=True) elif target.cpu == 'x86_64': return namespace(x64=True) return namespace(**{str(target.cpu): True}) set_config('JS_CODEGEN_NONE', jit_codegen.none) set_config('JS_CODEGEN_ARM', jit_codegen.arm) set_config('JS_CODEGEN_ARM64', jit_codegen.arm64) set_config('JS_CODEGEN_MIPS32', jit_codegen.mips32) set_config('JS_CODEGEN_MIPS64', jit_codegen.mips64) set_config('JS_CODEGEN_X86', jit_codegen.x86) set_config('JS_CODEGEN_X64', jit_codegen.x64) set_define('JS_CODEGEN_NONE', jit_codegen.none) set_define('JS_CODEGEN_ARM', jit_codegen.arm) set_define('JS_CODEGEN_ARM64', jit_codegen.arm64) set_define('JS_CODEGEN_MIPS32', jit_codegen.mips32) set_define('JS_CODEGEN_MIPS64', jit_codegen.mips64) set_define('JS_CODEGEN_X86', jit_codegen.x86) set_define('JS_CODEGEN_X64', jit_codegen.x64) # Profiling # ======================================================= js_option('--enable-instruments', env='MOZ_INSTRUMENTS', help='Enable instruments remote profiling') @depends('--enable-instruments', target) def instruments(value, target): if value and target.os != 'OSX': die('--enable-instruments cannot be used when targeting %s', target.os) if value: return True set_config('MOZ_INSTRUMENTS', instruments) set_define('MOZ_INSTRUMENTS', instruments) add_old_configure_assignment('MOZ_INSTRUMENTS', instruments) imply_option('--enable-profiling', instruments, reason='--enable-instruments') js_option('--enable-callgrind', env='MOZ_CALLGRIND', help='Enable callgrind profiling') @depends('--enable-callgrind') def callgrind(value): if value: return True set_define('MOZ_CALLGRIND', callgrind) imply_option('--enable-profiling', callgrind) @depends(milestone) def enable_profiling(milestone): return milestone.is_nightly js_option('--enable-profiling', env='MOZ_PROFILING', default=enable_profiling, help='{Set|Do not set} compile flags necessary for using sampling ' 'profilers (e.g. shark, perf)') @depends('--enable-profiling') def profiling(value): if value: return True add_old_configure_assignment('MOZ_PROFILING', profiling) with only_when('--enable-compile-environment'): imply_option('--enable-frame-pointers', True, when=profiling) @depends(profiling, target) def imply_vtune(value, target): ok_cpu = target.cpu in ['x86', 'x86_64'] ok_kernel = target.kernel == 'WINNT' or \ (target.kernel == 'Linux' and target.os == 'GNU') if value and ok_cpu and ok_kernel: return True set_config('MOZ_PROFILING', profiling) set_define('MOZ_PROFILING', profiling) imply_option('--enable-vtune', imply_vtune, reason='--enable-profiling') js_option('--enable-vtune', env='MOZ_VTUNE', help='Enable VTune profiling') @depends('--enable-vtune') def vtune(value): if value: return True set_config('MOZ_VTUNE', vtune) set_define('MOZ_VTUNE', vtune) js_option('--enable-gc-probes', env='JS_GC_PROBES', help='Turn on probes for allocation and finalization') @depends('--enable-gc-probes') def gc_probes(value): if value: return True set_define('JS_GC_PROBES', gc_probes) js_option('--enable-gczeal', default=depends(when=moz_debug)(lambda: True), help='{Enable|Disable} zealous GCing') set_define('JS_GC_ZEAL', depends_if('--enable-gczeal')(lambda _: True)) # Use a smaller chunk size for GC chunks # ======================================================== # Use large (1MB) chunks by default. This option can be used to give # smaller (currently 256K) chunks. js_option('--enable-small-chunk-size', help='Allocate memory for JS GC things in smaller chunks') set_define('JS_GC_SMALL_CHUNK_SIZE', depends(when='--enable-small-chunk-size')(lambda: True)) # Trace logging. # ======================================================= @depends(milestone) def default_trace_logging(milestone): return milestone.is_nightly js_option('--enable-trace-logging', default=default_trace_logging, help='{Enable|Disable} trace logging') set_config('ENABLE_TRACE_LOGGING', depends_if('--enable-trace-logging')(lambda x: True)) set_define('JS_TRACE_LOGGING', depends_if('--enable-trace-logging')(lambda x: True)) # Enable breakpoint for artificial OOMs # ======================================================= js_option('--enable-oom-breakpoint', help='Enable a breakpoint function for artificial OOMs') set_define('JS_OOM_BREAKPOINT', depends_if('--enable-oom-breakpoint')(lambda _: True)) js_option('--enable-perf', env='JS_ION_PERF', help='Enable Linux perf integration') @depends('--enable-perf') def ion_perf(value): if value: return True set_define('JS_ION_PERF', ion_perf) js_option('--enable-jitspew', default=depends(when=moz_debug)(lambda: True), help='{Enable|Disable} the Jit spew and IONFLAGS environment ' 'variable') set_define('JS_JITSPEW', depends_if('--enable-jitspew')(lambda _: True)) set_config('JS_JITSPEW', depends_if('--enable-jitspew')(lambda _: True)) # Also enable the structured spewer set_define('JS_STRUCTURED_SPEW', depends_if('--enable-jitspew')(lambda _: True)) set_config('JS_STRUCTURED_SPEW', depends_if('--enable-jitspew')(lambda _: True)) @depends('--enable-jit', '--enable-jitspew', simulator, target, moz_debug) def jit_disasm_arm(jit_enabled, spew, simulator, target, debug): if not jit_enabled: return if simulator and (debug or spew): if getattr(simulator, 'arm', None): return True if target.cpu == 'arm' and (debug or spew): return True set_config('JS_DISASM_ARM', jit_disasm_arm) set_define('JS_DISASM_ARM', jit_disasm_arm) @depends('--enable-jit', '--enable-jitspew', simulator, target, moz_debug) def jit_disasm_arm64(jit_enabled, spew, simulator, target, debug): if not jit_enabled: return if simulator and (debug or spew): if getattr(simulator, 'arm64', None): return True if target.cpu == 'aarch64' and (debug or spew): return True set_config('JS_DISASM_ARM64', jit_disasm_arm64) set_define('JS_DISASM_ARM64', jit_disasm_arm64) # When enabled, masm will generate assumeUnreachable calls that act as # assertions in the generated code. This option is worth disabling when you # have to track mutated values through the generated code, to avoid constantly # dumping registers on and off the stack. js_option('--enable-masm-verbose', default=depends(when=moz_debug)(lambda: True), help='{Enable|Disable} MacroAssembler verbosity of generated code.') set_define('JS_MASM_VERBOSE', depends_if('--enable-masm-verbose')(lambda _: True)) set_config('JS_MASM_VERBOSE', depends_if('--enable-masm-verbose')(lambda _: True)) js_option('--enable-more-deterministic', env='JS_MORE_DETERMINISTIC', help='Enable changes that make the shell more deterministic') @depends('--enable-more-deterministic') def more_deterministic(value): if value: return True set_define('JS_MORE_DETERMINISTIC', more_deterministic) # CTypes # ======================================================= @depends(building_js) def ctypes_default(building_js): return not building_js js_option('--enable-ctypes', default=ctypes_default, help='{Enable|Disable} js-ctypes') build_ctypes = depends_if('--enable-ctypes')(lambda _: True) set_config('BUILD_CTYPES', build_ctypes) set_define('BUILD_CTYPES', build_ctypes) @depends(build_ctypes, building_js) def js_has_ctypes(ctypes, js): if ctypes and js: return True set_config('JS_HAS_CTYPES', js_has_ctypes) set_define('JS_HAS_CTYPES', js_has_ctypes) @depends('--enable-ctypes', '--enable-compile-environment') def ctypes_and_compile_environment(ctypes, compile_environment): return ctypes and compile_environment include('ffi.configure', when=ctypes_and_compile_environment) # Enable pipeline operator # =================================================== js_option('--enable-pipeline-operator', default=False, help='Enable pipeline operator') @depends('--enable-pipeline-operator') def enable_pipeline_operator(value): if value: return True set_config('ENABLE_PIPELINE_OPERATOR', enable_pipeline_operator) set_define('ENABLE_PIPELINE_OPERATOR', enable_pipeline_operator) # SIMD acceleration for encoding_rs # ============================================================== js_option('--enable-rust-simd', env='MOZ_RUST_SIMD', help='Enable explicit SIMD in Rust code.') @depends('--enable-rust-simd', target) def rust_simd(value, target): # As of 2019-09-17, the simd-accel feature of encoding_rs has not # been properly set up outside aarch64, armv7, x86 and x86_64. if target.cpu in ('aarch64', 'arm', 'x86', 'x86_64') and value: return True set_config('MOZ_RUST_SIMD', rust_simd) set_define('MOZ_RUST_SIMD', rust_simd) # Support for wasm code generation with Cranelift # ============================================================== @depends(milestone.is_nightly, target, simulator) def cranelift_default(is_nightly, target, simulator): if is_nightly or target.cpu == 'aarch64' or (simulator is not None and simulator.arm64): return True js_option('--enable-cranelift', default=cranelift_default, help='{Enable|Disable} Cranelift code generator for wasm') set_config('ENABLE_WASM_CRANELIFT', depends_if('--enable-cranelift')(lambda x: True)) set_define('ENABLE_WASM_CRANELIFT', depends_if('--enable-cranelift')(lambda x: True)) # Telemetry to measure compile time and generated-code runtime # ============================================================ js_option('--enable-spidermonkey-telemetry', default=milestone.is_nightly, help='{Enable|Disable} performance telemetry for SpiderMonkey (e.g. compile and run times)') set_define('ENABLE_SPIDERMONKEY_TELEMETRY', depends_if('--enable-spidermonkey-telemetry')(lambda x: True)) # Support for debugging code generated by wasm backends # ===================================================== js_option('--enable-wasm-codegen-debug', default=depends(when=moz_debug)(lambda: True), help='{Enable|Disable} debugging for wasm codegen') set_config('WASM_CODEGEN_DEBUG', depends_if('--enable-wasm-codegen-debug')(lambda x: True)) set_define('WASM_CODEGEN_DEBUG', depends_if('--enable-wasm-codegen-debug')(lambda x: True)) # Support for typed objects. # ===================================================== @depends(milestone.is_nightly) def default_typed_objects(is_nightly): return is_nightly js_option('--enable-typed-objects', default=default_typed_objects, help='{Enable|Disable} typed objects') set_config('JS_HAS_TYPED_OBJECTS', depends_if('--enable-typed-objects')(lambda x: True)) set_define('JS_HAS_TYPED_OBJECTS', depends_if('--enable-typed-objects')(lambda x: True)) # Support for WebAssembly reference types. # ===================================================== js_option('--disable-wasm-reftypes', help='Disable WebAssembly reference types') @depends('--disable-wasm-reftypes') def enable_wasm_reftypes(value): if value: return True set_config('ENABLE_WASM_REFTYPES', enable_wasm_reftypes) set_define('ENABLE_WASM_REFTYPES', enable_wasm_reftypes) # Support for WebAssembly GC. # =========================== @depends(milestone.is_nightly, '--enable-wasm-reftypes', '--enable-typed-objects') def default_wasm_gc(is_nightly, reftypes, typed_objects): if is_nightly and reftypes and typed_objects: return True js_option('--enable-wasm-gc', default=default_wasm_gc, help='{Enable|Disable} WebAssembly GC') @depends('--enable-wasm-gc', '--enable-wasm-reftypes', '--enable-typed-objects') def wasm_gc(value, reftypes, typed_objects): if not value: return if reftypes and typed_objects: return True die('--enable-wasm-gc only possible with --enable-wasm-reftypes and --enable-typed-objects') set_config('ENABLE_WASM_GC', wasm_gc) set_define('ENABLE_WASM_GC', wasm_gc) # Support for WebAssembly private ref types. # Prevent (ref T) types from being exposed to JS content so that wasm need do # no typechecking at the JS/wasm boundary # =========================================================================== @depends(milestone.is_nightly, '--enable-wasm-gc') def default_wasm_private_reftypes(is_nightly, gc): if gc and is_nightly: return True js_option('--enable-wasm-private-reftypes', default=default_wasm_private_reftypes, help='{Enable|Disable} WebAssembly private reference types') set_config('WASM_PRIVATE_REFTYPES', depends_if('--enable-wasm-private-reftypes')(lambda x: True)) set_define('WASM_PRIVATE_REFTYPES', depends_if('--enable-wasm-private-reftypes')(lambda x: True)) # Support for the WebAssembly multi-value proposal. # Do not remove until Cranelift supports multi-value. # ===================================================== js_option('--disable-wasm-multi-value', help='Disable WebAssembly multi-value blocks and function calls') @depends('--disable-wasm-multi-value') def enable_wasm_multi_value(value): if value: return True set_config('ENABLE_WASM_MULTI_VALUE', enable_wasm_multi_value) set_define('ENABLE_WASM_MULTI_VALUE', enable_wasm_multi_value) # Support for WebAssembly shared memory and atomics. # # This affects the JS shell only and here to allow the use of # Cranelift in the shell. Once Cranelift supports shared memory # and atomics it can go away. # ===================================================== js_option('--disable-shared-memory', help='Disable JS/WebAssembly shared memory and atomics') @depends('--disable-shared-memory') def enable_shared_memory(value): if value: return True set_config('ENABLE_SHARED_MEMORY', enable_shared_memory) set_define('ENABLE_SHARED_MEMORY', enable_shared_memory) # Support for WebAssembly SIMD # ===================================================== @depends('--enable-jit', '--enable-simulator', target) def default_wasm_simd(jit_enabled, simulator, target): if not jit_enabled or simulator: return if target.cpu in ('x86_64', 'x86'): return True js_option('--enable-wasm-simd', default=default_wasm_simd, help='{Enable|Disable} WebAssembly SIMD') @depends('--enable-wasm-simd', '--enable-jit', '--enable-simulator', target) def wasm_simd(value, jit_enabled, simulator, target): if not value: return if jit_enabled and not simulator: if target.cpu in ('x86_64', 'x86'): return True die('--enable-wasm-simd only possible when targeting the x86_64/x86 jit') set_config('ENABLE_WASM_SIMD', wasm_simd) set_define('ENABLE_WASM_SIMD', wasm_simd) # Options for generating the shell as a script # ============================================ js_option('--with-qemu-exe', nargs=1, help='Use path as an arm emulator on host platforms') set_config('QEMU_EXE', depends_if('--with-qemu-exe')(lambda x: x)) js_option('--with-cross-lib', nargs=1, default=depends(target.alias)(lambda x: '/usr/%s' % x), help='Use dir as the location for arm libraries') set_config('CROSS_LIB', depends_if('--with-cross-lib')(lambda x: x)) # Enable static checking using sixgill # ==================================== js_option('--with-sixgill', nargs=1, help='Enable static checking of code using sixgill') @depends_if('--with-sixgill') @imports('os') def sixgill(value): for f in ('bin/xdbfind', 'gcc/xgill.so', 'scripts/wrap_gcc/g++'): if not os.path.exists(os.path.join(value[0], f)): die('The sixgill plugin and binaries are not at the specified path') return value[0] set_config('SIXGILL_PATH', sixgill) # Support for readline # ===================================================== @depends('--enable-js-shell', target_is_windows, compile_environment) def editline(js_shell, is_windows, compile_environment): return js_shell and not is_windows and compile_environment js_option('--enable-readline', help='Link js shell to system readline library', when=editline) has_readline = check_symbol('readline', flags=['-lreadline'], when='--enable-readline', onerror=lambda: die('No system readline library found')) set_config('EDITLINE_LIBS', ['-lreadline'], when=has_readline) @depends('--enable-readline', editline, when=editline) def bundled_editline(readline, editline): return editline and not readline set_config('JS_BUNDLED_EDITLINE', bundled_editline) set_define('EDITLINE', True, when=editline) # JIT observers # ============= js_option('--with-jitreport-granularity', default='3', choices=('0', '1', '2', '3'), help='Default granularity at which to report JIT code to external tools ' '(0 - no info, 1 - code ranges for while functions only, ' '2 - per-line information, 3 - per-op information)') set_define('JS_DEFAULT_JITREPORT_GRANULARITY', depends_if('--with-jitreport-granularity')(lambda value: value[0])) # ECMAScript Internationalization API Support (uses ICU) # ====================================================== js_option('--with-system-icu', help='Use system ICU') system_icu = pkg_check_modules('MOZ_ICU', 'icu-i18n >= 67.1', when='--with-system-icu') set_config('MOZ_SYSTEM_ICU', True, when=system_icu) set_define('MOZ_SYSTEM_ICU', True, when=system_icu) js_option('--without-intl-api', help='Disable ECMAScript Internationalization API') @depends('--with-intl-api', building_js) def check_intl_api(enabled, building_js): if not enabled and not building_js: die('--without-intl-api is not supported') set_config('JS_HAS_INTL_API', True, when='--with-intl-api') set_define('JS_HAS_INTL_API', True, when='--with-intl-api') @depends(check_build_environment, when='--with-intl-api') @imports(_from='__builtin__', _import='open') @imports(_from='__builtin__', _import='ValueError') def icu_version(build_env): path = os.path.join(build_env.topsrcdir, 'intl', 'icu', 'source', 'common', 'unicode', 'uvernum.h') with open(path, encoding='utf-8') as fh: for line in fh: if line.startswith('#define'): define = line.split(None, 3) if len(define) == 3 and define[1] == 'U_ICU_VERSION_MAJOR_NUM': try: return str(int(define[2])) except ValueError: pass die('Cannot determine ICU version number from uvernum.h header file') set_config('MOZ_ICU_VERSION', icu_version) # Source files that use ICU should have control over which parts of the ICU # namespace they want to use. set_define('U_USING_ICU_NAMESPACE', '0', when='--with-intl-api') # We build ICU as a static library. set_define('U_STATIC_IMPLEMENTATION', True, when=depends(system_icu)(lambda x: not x)) @depends(yasm, gnu_as, target, compile_environment) def can_build_data_file(yasm, gnu_as, target, compile_environment): if not compile_environment or (target.kernel == 'WINNT' and target.cpu == 'aarch64'): return if not yasm and not gnu_as: die('Building ICU requires either yasm or a GNU assembler. If you do not have ' 'either of those available for this platform you must use --without-intl-api')