mirror of
https://github.com/radareorg/quickjs.git
synced 2026-11-07 14:38:27 -10:00
687 lines
15 KiB
Meson
687 lines
15 KiB
Meson
project(
|
|
'quickjs-ng',
|
|
'c',
|
|
version: '0.15.1',
|
|
default_options: [
|
|
'c_std=gnu11,c11',
|
|
'warning_level=3',
|
|
'buildtype=release',
|
|
'b_ndebug=if-release',
|
|
],
|
|
license: 'MIT',
|
|
license_files: 'LICENSE',
|
|
meson_version: '>=1.3.0',
|
|
)
|
|
|
|
host_system = host_machine.system()
|
|
cc = meson.get_compiler('c')
|
|
|
|
add_project_arguments('-DQUICKJS_NG_BUILD', language: 'c')
|
|
|
|
qjs_gcc_warning_args = [
|
|
'-Wno-unsafe-buffer-usage',
|
|
'-Wno-sign-conversion',
|
|
'-Wno-nonportable-system-include-path',
|
|
'-Wno-implicit-int-conversion',
|
|
'-Wno-shorten-64-to-32',
|
|
'-Wno-reserved-macro-identifier',
|
|
'-Wno-reserved-identifier',
|
|
'-Wdeprecated-declarations',
|
|
|
|
'-Wno-implicit-fallthrough',
|
|
'-Wno-sign-compare',
|
|
'-Wno-missing-field-initializers',
|
|
'-Wno-unused-parameter',
|
|
'-Wno-unused-but-set-variable',
|
|
'-Wno-array-bounds',
|
|
'-Wno-format-truncation',
|
|
]
|
|
qjs_gcc_args = []
|
|
|
|
if host_system != 'sunos'
|
|
qjs_gcc_args += '-funsigned-char'
|
|
endif
|
|
|
|
if host_system == 'darwin'
|
|
# https://github.com/quickjs-ng/quickjs/issues/453
|
|
qjs_gcc_warning_args += '-Wno-maybe-uninitialized'
|
|
endif
|
|
|
|
# https://github.com/microsoft/cpp-docs/tree/main/docs/error-messages/compiler-warnings
|
|
qjs_msvc_warning_args = [
|
|
'/wd4018', # -Wno-sign-conversion
|
|
'/wd4061', # -Wno-implicit-fallthrough
|
|
'/wd4100', # -Wno-unused-parameter
|
|
'/wd4200', # -Wno-zero-length-array
|
|
'/wd4242', # -Wno-shorten-64-to-32
|
|
'/wd4244', # -Wno-shorten-64-to-32
|
|
'/wd4245', # -Wno-sign-compare
|
|
'/wd4267', # -Wno-shorten-64-to-32
|
|
'/wd4388', # -Wno-sign-compare
|
|
'/wd4389', # -Wno-sign-compare
|
|
'/wd4710', # Function not inlined
|
|
'/wd4711', # Function was inlined
|
|
'/wd4820', # Padding added after construct
|
|
'/wd4996', # -Wdeprecated-declarations
|
|
'/wd5045', # Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
|
|
]
|
|
qjs_msvc_args = [
|
|
'/experimental:c11atomics',
|
|
'/J', # -funsigned-char
|
|
]
|
|
|
|
if cc.get_argument_syntax() == 'msvc'
|
|
add_project_arguments(
|
|
cc.get_supported_arguments(qjs_msvc_warning_args),
|
|
cc.get_id().contains('clang') ? cc.get_supported_arguments(qjs_gcc_warning_args) : [],
|
|
qjs_msvc_args,
|
|
language: 'c',
|
|
)
|
|
else
|
|
add_project_arguments(
|
|
cc.get_supported_arguments(qjs_gcc_warning_args),
|
|
qjs_gcc_args,
|
|
language: 'c',
|
|
)
|
|
endif
|
|
|
|
if host_system == 'windows'
|
|
# Set a 8MB default stack size on Windows.
|
|
# It defaults to 1MB on MSVC, which is the same as our current JS stack size,
|
|
# so it will overflow and crash otherwise.
|
|
# On MinGW it defaults to 2MB.
|
|
stack_size = 8 * 1024 * 1024
|
|
if cc.get_argument_syntax() == 'msvc'
|
|
add_project_link_arguments(f'/STACK:@stack_size@', language: 'c')
|
|
else
|
|
add_project_link_arguments(f'-Wl,--stack,@stack_size@', language: 'c')
|
|
endif
|
|
endif
|
|
|
|
if meson.is_cross_build()
|
|
native_cc = meson.get_compiler('c', native: true)
|
|
|
|
if native_cc.get_argument_syntax() == 'msvc'
|
|
# https://github.com/microsoft/cpp-docs/tree/main/docs/error-messages/compiler-warnings
|
|
add_project_arguments(
|
|
native_cc.get_supported_arguments(qjs_msvc_warning_args),
|
|
native_cc.get_id().contains('clang') ? native_cc.get_supported_arguments(qjs_gcc_warning_args) : [],
|
|
qjs_msvc_args,
|
|
|
|
language: 'c',
|
|
native: true,
|
|
)
|
|
else
|
|
add_project_arguments(
|
|
native_cc.get_supported_arguments(qjs_gcc_warning_args),
|
|
qjs_gcc_args,
|
|
|
|
language: 'c',
|
|
native: true,
|
|
)
|
|
endif
|
|
endif
|
|
if get_option('debug')
|
|
add_project_arguments(
|
|
cc.get_supported_arguments('-fno-omit-frame-pointer'),
|
|
language: 'c',
|
|
)
|
|
endif
|
|
|
|
qjs_sys_deps = []
|
|
|
|
m_dep = cc.find_library('m', required: false)
|
|
qjs_sys_deps += m_dep
|
|
qjs_sys_deps += dependency('threads', required: false)
|
|
qjs_sys_deps += dependency('dl', required: false)
|
|
|
|
qjs_srcs = files(
|
|
'dtoa.c',
|
|
'libregexp.c',
|
|
'libunicode.c',
|
|
'quickjs.c',
|
|
)
|
|
qjs_hdrs = files(
|
|
'quickjs.h',
|
|
)
|
|
|
|
qjs_libc = get_option('libc')
|
|
qjs_libc_srcs = files('quickjs-libc.c')
|
|
qjs_libc_hdrs = files('quickjs-libc.h')
|
|
|
|
if qjs_libc
|
|
qjs_hdrs += qjs_libc_hdrs
|
|
add_project_arguments(
|
|
'-DQJS_BUILD_LIBC',
|
|
language: 'c'
|
|
)
|
|
endif
|
|
|
|
qjs_parser = get_option('parser')
|
|
|
|
qjs_c_args = ['-D_GNU_SOURCE']
|
|
|
|
if host_system == 'windows'
|
|
qjs_c_args += ['-DWIN32_LEAN_AND_MEAN', '-D_WIN32_WINNT=0x0601']
|
|
endif
|
|
|
|
if not qjs_parser
|
|
qjs_c_args += ['-DQJS_DISABLE_PARSER']
|
|
endif
|
|
|
|
qjs_lib = library(
|
|
'qjs',
|
|
qjs_srcs,
|
|
qjs_libc ? qjs_libc_srcs : [],
|
|
|
|
dependencies: qjs_sys_deps,
|
|
c_args: qjs_c_args,
|
|
c_shared_args: ['-DBUILDING_QJS_SHARED'],
|
|
gnu_symbol_visibility: 'hidden',
|
|
|
|
install: true,
|
|
version: meson.project_version(),
|
|
)
|
|
|
|
qjs_export_variables = [
|
|
f'have_parser=@qjs_parser@'
|
|
]
|
|
|
|
# This note is only of interest on Windows.
|
|
# Be conservative here: only pass -DUSING_QJS_SHARED iff default_library ==
|
|
# 'shared', thus qjs is guaranteed to be a DLL. Not passing -DUSING_QJS_SHARED if
|
|
# qjs is a DLL is not harmful, but passing the definition for DLL qjs is desired.
|
|
# Conversely, if -DUSING_QJS_SHARED is passed for static qjs, the consumers
|
|
# will not compile.
|
|
qjs_dep_args = get_option('default_library') == 'shared' ? ['-DUSING_QJS_SHARED'] : []
|
|
|
|
qjs_dep = declare_dependency(
|
|
compile_args: qjs_dep_args,
|
|
link_with: qjs_lib,
|
|
dependencies: qjs_sys_deps,
|
|
include_directories: include_directories('.'),
|
|
variables: qjs_export_variables,
|
|
)
|
|
|
|
if host_system != 'windows'
|
|
qjs_module_dep = declare_dependency(
|
|
compile_args: [qjs_dep_args, '-DQUICKJS_NG_MODULE_BUILD'],
|
|
include_directories: include_directories('.'),
|
|
)
|
|
else
|
|
qjs_module_dep = declare_dependency(
|
|
compile_args: [qjs_dep_args, '-DQUICKJS_NG_MODULE_BUILD'],
|
|
include_directories: include_directories('.'),
|
|
# Windows can't resolve symbols at runtime thus we explicitly link to qjs.
|
|
dependencies: qjs_dep,
|
|
)
|
|
endif
|
|
|
|
if qjs_libc
|
|
qjs_libc_dep = declare_dependency(
|
|
include_directories: include_directories('.'),
|
|
dependencies: qjs_dep,
|
|
)
|
|
else
|
|
qjs_libc_lib = static_library(
|
|
'quickjs-libc',
|
|
qjs_libc_srcs,
|
|
|
|
c_args: qjs_c_args,
|
|
dependencies: [qjs_sys_deps, qjs_dep],
|
|
gnu_symbol_visibility: 'hidden',
|
|
)
|
|
qjs_libc_dep = declare_dependency(
|
|
link_with: qjs_libc_lib,
|
|
# Pick up quickjs-libc.h.
|
|
include_directories: include_directories('.'),
|
|
)
|
|
endif
|
|
|
|
if host_system == 'emscripten'
|
|
qjs_wasm_export_name = 'getQuickJs'
|
|
executable(
|
|
'qjs_wasm',
|
|
qjs_srcs,
|
|
link_args: cc.get_supported_link_arguments(
|
|
# in emscripten 3.x, this will be set to 16k which is too small for quickjs.
|
|
'-sSTACK_SIZE=@0@'.format(2 * 1024 * 1024), # let it be 2m = 2 * 1024 * 1024, otherwise, stack overflow may be occured at bootstrap
|
|
'-sNO_INVOKE_RUN',
|
|
'-sNO_EXIT_RUNTIME',
|
|
'-sMODULARIZE', # do not mess the global
|
|
'-sEXPORT_ES6', # export js file to morden es module
|
|
'-sEXPORT_NAME=@0@'.format(qjs_wasm_export_name), # give a name
|
|
'-sTEXTDECODER=1', # it will be 2 if we use -Oz, and that will cause js -> c string convertion fail
|
|
'-sNO_DEFAULT_TO_CXX', # this project is pure c project, no need for c plus plus handle
|
|
'-sEXPORTED_RUNTIME_METHODS=ccall,cwrap',
|
|
),
|
|
dependencies: m_dep,
|
|
c_args: qjs_c_args,
|
|
)
|
|
endif
|
|
|
|
install_headers(qjs_hdrs, subdir: 'quickjs-ng')
|
|
|
|
if not meson.is_subproject()
|
|
docdir = get_option('docdir')
|
|
datadir = get_option('datadir')
|
|
|
|
if docdir == ''
|
|
docdir = datadir / 'doc' / meson.project_name()
|
|
endif
|
|
install_data(
|
|
'LICENSE',
|
|
install_dir: docdir,
|
|
|
|
install_tag: 'doc',
|
|
)
|
|
install_subdir(
|
|
'examples',
|
|
install_dir: docdir,
|
|
|
|
strip_directory: false,
|
|
install_tag: 'doc',
|
|
)
|
|
endif
|
|
|
|
meson.override_dependency('quickjs-ng', qjs_dep)
|
|
|
|
import('pkgconfig').generate(
|
|
qjs_lib,
|
|
subdirs: 'quickjs-ng',
|
|
name: 'quickjs-ng',
|
|
description: 'QuickJS, the Next Generation: a mighty JavaScript engine',
|
|
url: 'https://github.com/quickjs-ng/quickjs',
|
|
version: meson.project_version(),
|
|
variables: qjs_export_variables,
|
|
# Export -DUSING_QJS_SHARED, if needed, in the pkgconfig file.
|
|
extra_cflags: qjs_dep_args,
|
|
)
|
|
|
|
if not qjs_parser
|
|
subdir_done()
|
|
endif
|
|
|
|
# QuickJS bytecode compiler
|
|
qjsc_srcs = files(
|
|
'qjsc.c',
|
|
)
|
|
qjsc_exe = executable(
|
|
'qjsc',
|
|
qjsc_srcs,
|
|
|
|
c_args: qjs_c_args,
|
|
dependencies: [qjs_dep, qjs_libc_dep],
|
|
install: true,
|
|
)
|
|
|
|
mimalloc_dep = []
|
|
mimalloc_sys_dep = dependency('mimalloc', required: get_option('cli_mimalloc'))
|
|
if mimalloc_sys_dep.found()
|
|
mimalloc_dep = declare_dependency(
|
|
dependencies: mimalloc_sys_dep,
|
|
compile_args: '-DQJS_USE_MIMALLOC',
|
|
)
|
|
endif
|
|
|
|
# QuickJS CLI
|
|
qjs_exe_srcs = files(
|
|
'gen/repl.c',
|
|
'gen/standalone.c',
|
|
'qjs.c',
|
|
)
|
|
qjs_exe = executable(
|
|
'qjs',
|
|
qjs_exe_srcs,
|
|
|
|
c_args: qjs_c_args,
|
|
dependencies: [qjs_dep, qjs_libc_dep, mimalloc_dep],
|
|
export_dynamic: true,
|
|
|
|
install: true,
|
|
)
|
|
|
|
if meson.is_cross_build()
|
|
mimalloc_native_dep = []
|
|
mimalloc_sys_native_dep = dependency('mimalloc', required: get_option('cli_mimalloc'), native: true)
|
|
if mimalloc_sys_dep.found()
|
|
mimalloc_native_dep = declare_dependency(
|
|
dependencies: mimalloc_sys_native_dep,
|
|
compile_args: '-DQJS_USE_MIMALLOC',
|
|
)
|
|
endif
|
|
|
|
qjs_sys_native_deps = [
|
|
native_cc.find_library('m', required: false),
|
|
dependency('threads', required: false, native: true),
|
|
dependency('dl', required: false, native: true),
|
|
]
|
|
qjs_native_lib = static_library(
|
|
'qjs_native',
|
|
qjs_srcs,
|
|
qjs_libc_srcs,
|
|
|
|
dependencies: qjs_sys_native_deps,
|
|
c_args: qjs_c_args,
|
|
gnu_symbol_visibility: 'hidden',
|
|
|
|
build_by_default: false,
|
|
native: true,
|
|
install: false,
|
|
)
|
|
|
|
meson.override_find_program(
|
|
'qjsc',
|
|
executable(
|
|
'qjsc_native',
|
|
qjsc_srcs,
|
|
|
|
c_args: qjs_c_args,
|
|
link_with: qjs_native_lib,
|
|
dependencies: qjs_sys_native_deps,
|
|
|
|
build_by_default: false,
|
|
native: true,
|
|
install: false,
|
|
),
|
|
)
|
|
meson.override_find_program(
|
|
'qjs',
|
|
executable(
|
|
'qjs_native',
|
|
qjs_exe_srcs,
|
|
|
|
c_args: qjs_c_args,
|
|
link_with: qjs_native_lib,
|
|
dependencies: [qjs_sys_native_deps, mimalloc_native_dep],
|
|
export_dynamic: true,
|
|
|
|
build_by_default: false,
|
|
native: true,
|
|
install: false,
|
|
),
|
|
)
|
|
else
|
|
meson.override_find_program('qjsc', qjsc_exe)
|
|
meson.override_find_program('qjs', qjs_exe)
|
|
endif
|
|
|
|
tests = get_option('tests').disable_auto_if(meson.is_subproject())
|
|
examples = get_option('examples').disable_auto_if(meson.is_subproject())
|
|
|
|
if tests.allowed()
|
|
if host_system != 'emscripten'
|
|
# Test262 runner
|
|
run262_exe = executable(
|
|
'run-test262',
|
|
'run-test262.c',
|
|
|
|
c_args: qjs_c_args,
|
|
dependencies: [qjs_dep, qjs_libc_dep]
|
|
)
|
|
|
|
test(
|
|
'test',
|
|
run262_exe,
|
|
args: ['-c', files('tests.conf')],
|
|
workdir: meson.current_source_dir(),
|
|
)
|
|
|
|
foreach bench : [
|
|
'empty_loop',
|
|
|
|
'date_now',
|
|
|
|
'prop_read',
|
|
'prop_write',
|
|
'prop_create',
|
|
'prop_delete',
|
|
|
|
'array_read',
|
|
'array_write',
|
|
'array_prop_create',
|
|
'array_length_decr',
|
|
'array_hole_length_decr',
|
|
'array_push',
|
|
'array_pop',
|
|
|
|
'typed_array_read',
|
|
'typed_array_write',
|
|
|
|
'global_read',
|
|
'global_write',
|
|
'global_write_strict',
|
|
|
|
'local_destruct',
|
|
'global_destruct',
|
|
'global_destruct_strict',
|
|
|
|
'func_call',
|
|
'closure_var',
|
|
|
|
'int_arith',
|
|
'float_arith',
|
|
|
|
'map_set',
|
|
'map_delete',
|
|
'weak_map_set',
|
|
'weak_map_delete',
|
|
|
|
'array_for',
|
|
'array_for_in',
|
|
'array_for_of',
|
|
|
|
'math_min',
|
|
|
|
'object_null',
|
|
|
|
'regexp_ascii',
|
|
'regexp_utf16',
|
|
|
|
'string_build1',
|
|
'string_build2',
|
|
|
|
'string_slice1',
|
|
'string_slice2',
|
|
'string_slice3',
|
|
|
|
'sort_bench',
|
|
|
|
'int_to_string',
|
|
'int_toString',
|
|
|
|
'float_to_string',
|
|
'float_toString',
|
|
'float_toFixed',
|
|
'float_toPrecision',
|
|
'float_toExponential',
|
|
|
|
'string_to_int',
|
|
'string_to_float',
|
|
|
|
'bigint64_arith',
|
|
'bigint256_arith',
|
|
]
|
|
benchmark(
|
|
bench,
|
|
qjs_exe,
|
|
args: [files('tests/microbench.js'), bench],
|
|
)
|
|
endforeach
|
|
endif
|
|
|
|
# API test
|
|
test(
|
|
'api',
|
|
executable(
|
|
'api-test',
|
|
'api-test.c',
|
|
|
|
c_args: qjs_c_args,
|
|
dependencies: qjs_dep,
|
|
build_by_default: false,
|
|
),
|
|
)
|
|
|
|
# LRE test
|
|
test(
|
|
'lre',
|
|
executable(
|
|
'lre-test',
|
|
'lre-test.c',
|
|
'libregexp.c',
|
|
'libunicode.c',
|
|
|
|
c_args: qjs_c_args,
|
|
build_by_default: false,
|
|
),
|
|
)
|
|
|
|
# Function.toString() test
|
|
test(
|
|
'function_source',
|
|
executable(
|
|
'function_source',
|
|
'gen/function_source.c',
|
|
|
|
c_args: qjs_c_args,
|
|
dependencies: [qjs_dep, qjs_libc_dep],
|
|
build_by_default: false,
|
|
),
|
|
)
|
|
endif
|
|
|
|
# Unicode generator
|
|
unicode_gen = executable(
|
|
'unicode_gen',
|
|
'unicode_gen.c',
|
|
|
|
c_args: qjs_c_args,
|
|
build_by_default: false,
|
|
)
|
|
|
|
run_target(
|
|
'libunicode-table.h',
|
|
command: [
|
|
unicode_gen,
|
|
meson.current_source_dir() / 'unicode',
|
|
files('libunicode-table.h'),
|
|
],
|
|
)
|
|
|
|
# bytecode to c source code for builtin and examples
|
|
alias_target('codegen',
|
|
run_target(
|
|
'codegen_repl.c',
|
|
command: [
|
|
qjsc_exe,
|
|
'-ss',
|
|
'-o', files('gen/repl.c'),
|
|
'-m',
|
|
'-n', 'repl.js',
|
|
files('repl.js'),
|
|
],
|
|
),
|
|
run_target(
|
|
'codegen_standalone.c',
|
|
command: [
|
|
qjsc_exe,
|
|
'-ss',
|
|
'-o', files('gen/standalone.c'),
|
|
'-m',
|
|
'-n', 'standalone.js',
|
|
files('standalone.js'),
|
|
],
|
|
),
|
|
run_target(
|
|
'codegen_function_source.c',
|
|
command: [
|
|
qjsc_exe,
|
|
'-e',
|
|
'-o', files('gen/function_source.c'),
|
|
'-n', 'tests/function_source.js',
|
|
files('tests/function_source.js'),
|
|
],
|
|
),
|
|
run_target(
|
|
'codegen_hello.c',
|
|
command: [
|
|
qjsc_exe,
|
|
'-e',
|
|
'-o', files('gen/hello.c'),
|
|
'-n', 'examples/hello.js',
|
|
files('examples/hello.js'),
|
|
],
|
|
),
|
|
run_target(
|
|
'codegen_hello_module.c',
|
|
command: [
|
|
qjsc_exe,
|
|
'-e',
|
|
'-o', files('gen/hello_module.c'),
|
|
'-m',
|
|
'-n', 'examples/hello_module.js',
|
|
files('examples/hello_module.js'),
|
|
],
|
|
),
|
|
run_target(
|
|
'codegen_test_fib.c',
|
|
command: [
|
|
qjsc_exe,
|
|
'-e',
|
|
'-o', files('gen/test_fib.c'),
|
|
'-m',
|
|
'-n', 'examples/test_fib.js',
|
|
files('examples/test_fib.js'),
|
|
],
|
|
),
|
|
run_target(
|
|
'codegen_builtin-array-fromasync.h',
|
|
command: [
|
|
qjsc_exe,
|
|
'-C',
|
|
'-ss',
|
|
'-o', files('builtin-array-fromasync.h'),
|
|
'-n', 'builtin-array-fromasync.js',
|
|
files('builtin-array-fromasync.js'),
|
|
],
|
|
),
|
|
)
|
|
|
|
if examples.allowed()
|
|
if host_system == 'windows' and get_option('default_library') != 'shared'
|
|
warning('Binary modules used with static qjs on Windows.')
|
|
warning(
|
|
'There might be runtime errors when the modules are used due to',
|
|
'two copies of qjs in memory.'
|
|
)
|
|
warning('Please use "-Ddefault_library=shared" if possible.')
|
|
endif
|
|
executable(
|
|
'hello',
|
|
'gen/hello.c',
|
|
|
|
c_args: qjs_c_args,
|
|
dependencies: [qjs_dep, qjs_libc_dep]
|
|
)
|
|
|
|
executable(
|
|
'hello_module',
|
|
'gen/hello_module.c',
|
|
|
|
c_args: qjs_c_args,
|
|
dependencies: [qjs_dep, qjs_libc_dep]
|
|
)
|
|
|
|
subdir('examples')
|
|
|
|
executable(
|
|
'test_fib',
|
|
'gen/test_fib.c',
|
|
|
|
c_args: qjs_c_args,
|
|
dependencies: [qjs_dep, qjs_libc_dep],
|
|
export_dynamic: true,
|
|
)
|
|
endif
|