diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d7d897a1c..cad6e54b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -643,11 +643,14 @@ jobs: - name: clang+sanitize args: >- "-Db_sanitize=address,undefined" + "-Db_lundef=false" extra_envs: CC: clang CXX: clang++ - name: clang+msan - args: -Db_sanitize=memory + args: >- + "-Db_sanitize=memory" + "-Db_lundef=false" extra_envs: CC: clang CXX: clang++ @@ -657,6 +660,7 @@ jobs: - name: clang-cl+sanitize args: >- "-Db_sanitize=address,undefined" + "-Db_lundef=false" extra_envs: CC: clang-cl CXX: clang-cl diff --git a/CMakeLists.txt b/CMakeLists.txt index cf6bf1754..5cc76bd04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,9 @@ set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS ON) set(CMAKE_C_STANDARD 11) +# Used to properly define QJS_LIBC_EXTERN. +add_compile_definitions(QUICKJS_NG_BUILD) + # MINGW doesn't exist in older cmake versions, newer versions don't know # about CMAKE_COMPILER_IS_MINGW, and there is no unique CMAKE_C_COMPILER_ID # for mingw-based compilers... @@ -232,7 +235,7 @@ endif() xoption(QJS_BUILD_LIBC "Build standard library modules as part of the library" OFF) macro(add_qjs_libc_if_needed target) if(NOT QJS_BUILD_LIBC) - target_sources(${target} PRIVATE quickjs-libc.c) + target_link_libraries(${target} PRIVATE qjs-libc) endif() endmacro() macro(add_static_if_needed target) @@ -245,7 +248,6 @@ macro(add_static_if_needed target) endmacro() set(qjs_sources - cutils.c dtoa.c libregexp.c libunicode.c @@ -254,6 +256,8 @@ set(qjs_sources if(QJS_BUILD_LIBC) list(APPEND qjs_sources quickjs-libc.c) + # The definition must be added to the entire project. + add_compile_definitions(QJS_BUILD_LIBC) endif() list(APPEND qjs_defines _GNU_SOURCE) if(WIN32) @@ -278,13 +282,37 @@ if(M_LIBRARIES OR CMAKE_C_COMPILER_ID STREQUAL "TinyCC") list(APPEND qjs_libs m) endif() +add_library(cutils STATIC cutils.c) +target_compile_definitions(cutils PRIVATE ${qjs_defines}) +target_link_libraries(cutils PRIVATE ${qjs_libs}) + add_library(qjs ${qjs_sources}) -target_compile_definitions(qjs PRIVATE ${qjs_defines}) +target_compile_definitions(qjs PRIVATE ${qjs_defines} QUICKJS_NG_QJS_INTERNAL) target_include_directories(qjs PUBLIC $ $ ) target_link_libraries(qjs PUBLIC ${qjs_libs}) +target_link_libraries(qjs PRIVATE $) +if(QJS_BUILD_EXAMPLES) + # We shouldn't really support building examples with static qjs.. + # Anyways, this is required for fib.so and point.so to link properly. + set_target_properties(qjs PROPERTIES POSITION_INDEPENDENT_CODE ON) +endif() + +# Pass a compiler definition so that Windows gets its declspec's right. +get_target_property(QJS_LIB_TYPE qjs TYPE) +if(QJS_LIB_TYPE STREQUAL "SHARED_LIBRARY") + # We use PUBLIC here because we want the consumers to also have this + # definition. + target_compile_definitions(qjs PUBLIC QUICKJS_NG_DLL) +endif() + +if(NOT QJS_BUILD_LIBC) + add_library(qjs-libc STATIC quickjs-libc.c) + target_compile_definitions(qjs-libc PRIVATE ${qjs_defines}) + target_link_libraries(qjs-libc PRIVATE ${qjs_libs} qjs cutils) +endif() if(EMSCRIPTEN) add_executable(qjs_wasm ${qjs_sources}) @@ -301,7 +329,7 @@ if(EMSCRIPTEN) -sEXPORTED_RUNTIME_METHODS=ccall,cwrap ) target_compile_definitions(qjs_wasm PRIVATE ${qjs_defines}) - target_link_libraries(qjs_wasm m) + target_link_libraries(qjs_wasm PRIVATE m) endif() @@ -314,7 +342,7 @@ add_executable(qjsc add_qjs_libc_if_needed(qjsc) add_static_if_needed(qjsc) target_compile_definitions(qjsc PRIVATE ${qjs_defines}) -target_link_libraries(qjsc qjs) +target_link_libraries(qjsc PRIVATE qjs cutils) # QuickJS CLI @@ -331,7 +359,7 @@ set_target_properties(qjs_exe PROPERTIES OUTPUT_NAME "qjs" ) target_compile_definitions(qjs_exe PRIVATE ${qjs_defines}) -target_link_libraries(qjs_exe qjs) +target_link_libraries(qjs_exe PRIVATE qjs cutils) if(NOT WIN32) set_target_properties(qjs_exe PROPERTIES ENABLE_EXPORTS TRUE) endif() @@ -339,9 +367,9 @@ if(QJS_BUILD_CLI_WITH_MIMALLOC OR QJS_BUILD_CLI_WITH_STATIC_MIMALLOC) find_package(mimalloc REQUIRED) # Upstream mimalloc doesn't provide a way to know if both libraries are supported. if(QJS_BUILD_CLI_WITH_STATIC_MIMALLOC) - target_link_libraries(qjs_exe mimalloc-static) + target_link_libraries(qjs_exe PRIVATE mimalloc-static) else() - target_link_libraries(qjs_exe mimalloc) + target_link_libraries(qjs_exe PRIVATE mimalloc) endif() endif() @@ -354,7 +382,7 @@ if(NOT EMSCRIPTEN) ) add_qjs_libc_if_needed(run-test262) target_compile_definitions(run-test262 PRIVATE ${qjs_defines}) - target_link_libraries(run-test262 qjs) + target_link_libraries(run-test262 PRIVATE qjs cutils) endif() # Interrupt test @@ -364,17 +392,17 @@ add_executable(api-test api-test.c ) target_compile_definitions(api-test PRIVATE ${qjs_defines}) -target_link_libraries(api-test qjs) +target_link_libraries(api-test PRIVATE qjs cutils) # Unicode generator # add_executable(unicode_gen EXCLUDE_FROM_ALL - cutils.c libunicode.c unicode_gen.c ) target_compile_definitions(unicode_gen PRIVATE ${qjs_defines}) +target_link_libraries(unicode_gen PRIVATE cutils) add_executable(function_source gen/function_source.c @@ -382,7 +410,7 @@ add_executable(function_source add_qjs_libc_if_needed(function_source) target_include_directories(function_source PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(function_source PRIVATE ${qjs_defines}) -target_link_libraries(function_source qjs) +target_link_libraries(function_source PRIVATE qjs) # Examples # @@ -394,7 +422,7 @@ if(QJS_BUILD_EXAMPLES) add_qjs_libc_if_needed(hello) target_include_directories(hello PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(hello PRIVATE ${qjs_defines}) - target_link_libraries(hello qjs) + target_link_libraries(hello PRIVATE qjs) add_executable(hello_module gen/hello_module.c @@ -402,17 +430,16 @@ if(QJS_BUILD_EXAMPLES) add_qjs_libc_if_needed(hello_module) target_include_directories(hello_module PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(hello_module PRIVATE ${qjs_defines}) - target_link_libraries(hello_module qjs) + target_link_libraries(hello_module PRIVATE qjs) add_library(fib MODULE examples/fib.c) set_target_properties(fib PROPERTIES PREFIX "" C_VISIBILITY_PRESET default ) - target_compile_definitions(fib PRIVATE JS_SHARED_LIBRARY) - if(WIN32) - target_link_libraries(fib qjs) - elseif(APPLE) + target_link_libraries(fib PRIVATE qjs) + target_compile_definitions(fib PRIVATE QUICKJS_NG_MODULE_BUILD) + if(APPLE) target_link_options(fib PRIVATE -undefined dynamic_lookup) endif() @@ -421,10 +448,9 @@ if(QJS_BUILD_EXAMPLES) PREFIX "" C_VISIBILITY_PRESET default ) - target_compile_definitions(point PRIVATE JS_SHARED_LIBRARY) - if(WIN32) - target_link_libraries(point qjs) - elseif(APPLE) + target_link_libraries(point PRIVATE qjs) + target_compile_definitions(point PRIVATE QUICKJS_NG_MODULE_BUILD) + if(APPLE) target_link_options(point PRIVATE -undefined dynamic_lookup) endif() @@ -434,8 +460,8 @@ if(QJS_BUILD_EXAMPLES) ) add_qjs_libc_if_needed(test_fib) target_include_directories(test_fib PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - target_compile_definitions(test_fib PRIVATE ${qjs_defines}) - target_link_libraries(test_fib qjs) + target_compile_definitions(test_fib PRIVATE ${qjs_defines} QUICKJS_NG_MODULE_BUILD) + target_link_libraries(test_fib PRIVATE qjs) endif() # Install target diff --git a/examples/fib.c b/examples/fib.c index b965acc5b..a9eb29d92 100644 --- a/examples/fib.c +++ b/examples/fib.c @@ -21,7 +21,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "../quickjs.h" + +#include #define countof(x) (sizeof(x) / sizeof((x)[0])) @@ -55,21 +56,7 @@ static int js_fib_init(JSContext *ctx, JSModuleDef *m) countof(js_fib_funcs)); } -#ifdef JS_SHARED_LIBRARY -#define JS_INIT_MODULE js_init_module -#else -#define JS_INIT_MODULE js_init_module_fib -#endif - -#ifndef JS_EXTERN -#ifdef _WIN32 -#define JS_EXTERN __declspec(dllexport) -#else -#define JS_EXTERN -#endif -#endif - -JS_EXTERN JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) +JS_MODULE_EXTERN JSModuleDef *js_init_module(JSContext *ctx, const char *module_name) { JSModuleDef *m; m = JS_NewCModule(ctx, module_name, js_fib_init); diff --git a/examples/meson.build b/examples/meson.build index 08c9d87b6..dc7512032 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -3,9 +3,9 @@ shared_module( 'fib.c', name_prefix: '', - gnu_symbol_visibility: 'default', - c_args: ['-DJS_SHARED_LIBRARY'], - dependencies: host_system == 'windows' ? qjs_dep : [], + gnu_symbol_visibility: 'hidden', + c_args: qjs_module_args, + dependencies: qjs_dep, ) shared_module( @@ -13,7 +13,7 @@ shared_module( 'point.c', name_prefix: '', - gnu_symbol_visibility: 'default', - c_args: ['-DJS_SHARED_LIBRARY'], - dependencies: host_system == 'windows' ? qjs_dep : [], + gnu_symbol_visibility: 'hidden', + c_args: qjs_module_args, + dependencies: qjs_dep, ) diff --git a/examples/point.c b/examples/point.c index a82df1519..baa06388c 100644 --- a/examples/point.c +++ b/examples/point.c @@ -21,9 +21,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "../quickjs.h" + #include +#include + #define countof(x) (sizeof(x) / sizeof((x)[0])) /* Point Class */ @@ -141,15 +143,7 @@ static int js_point_init(JSContext *ctx, JSModuleDef *m) return 0; } -#ifndef JS_EXTERN -#ifdef _WIN32 -#define JS_EXTERN __declspec(dllexport) -#else -#define JS_EXTERN -#endif -#endif - -JS_EXTERN JSModuleDef *js_init_module(JSContext *ctx, const char *module_name) +JS_MODULE_EXTERN JSModuleDef *js_init_module(JSContext *ctx, const char *module_name) { JSModuleDef *m; m = JS_NewCModule(ctx, module_name, js_point_init); diff --git a/meson.build b/meson.build index cf79060bc..fa80447ec 100644 --- a/meson.build +++ b/meson.build @@ -5,7 +5,6 @@ project( default_options: [ 'c_std=gnu11,c11', 'warning_level=3', - 'default_library=static', ], license: 'MIT', license_files: 'LICENSE', @@ -15,6 +14,8 @@ project( 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', @@ -133,7 +134,6 @@ qjs_sys_deps += dependency('threads', required: false) qjs_sys_deps += dependency('dl', required: false) qjs_srcs = files( - 'cutils.c', 'dtoa.c', 'libregexp.c', 'libunicode.c', @@ -149,6 +149,10 @@ 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') @@ -163,29 +167,25 @@ if not qjs_parser qjs_c_args += ['-DQJS_DISABLE_PARSER'] endif -qjs_libc_lib = static_library( - 'quickjs-libc', - qjs_libc_srcs, +qjs_module_args = ['-DQUICKJS_NG_MODULE_BUILD'] + +cutils_lib = static_library( + 'cutils', + 'cutils.c', dependencies: qjs_sys_deps, - c_args: qjs_c_args, - gnu_symbol_visibility: 'hidden', + c_args: qjs_c_args ) qjs_lib = library( 'qjs', qjs_srcs, - - # export public headers - generator( - find_program('cp', 'xcopy'), - output: ['@PLAINNAME@'], - arguments: ['@INPUT@', '@OUTPUT@'], - ).process(qjs_hdrs), + qjs_libc ? qjs_libc_srcs : [], dependencies: qjs_sys_deps, - link_whole: qjs_libc ? qjs_libc_lib : [], - c_args: qjs_c_args, + link_with: cutils_lib, + c_args: [qjs_c_args, '-DQUICKJS_NG_QJS_INTERNAL'], + c_shared_args: ['-DQUICKJS_NG_DLL'], gnu_symbol_visibility: 'hidden', install: true, @@ -196,13 +196,41 @@ qjs_export_variables = [ f'have_parser=@qjs_parser@' ] +# Be conservative here: only pass -DQUICKJS_NG_DLL iff default_library == +# 'shared', thus qjs is guarranteed to be a DLL. Not passing -DQUICKJS_NG_DLL if +# qjs is a DLL is not harmful, but passing the definition for DLL qjs is desired. +# Alternatively, if -DQUICKJS_NG_DLL is passed for static qjs, the consumers +# will not compile. +qjs_dep_args = get_option('default_library') == 'shared' ? ['-DQUICKJS_NG_DLL'] : [] + qjs_dep = declare_dependency( + compile_args: qjs_dep_args, link_with: qjs_lib, dependencies: qjs_sys_deps, - include_directories: qjs_lib.private_dir_include(), + include_directories: include_directories('.'), variables: qjs_export_variables, ) + +if qjs_libc + qjs_libc_dep = declare_dependency( + dependencies: qjs_dep + ) +else + qjs_libc_lib = static_library( + 'quickjs-libc', + qjs_libc_srcs, + + c_args: qjs_c_args, + link_with: cutils_lib, + dependencies: [qjs_sys_deps, qjs_dep], + gnu_symbol_visibility: 'hidden', + ) + qjs_libc_dep = declare_dependency( + link_with: qjs_libc_lib + ) +endif + if host_system == 'emscripten' qjs_wasm_export_name = 'getQuickJs' executable( @@ -274,9 +302,8 @@ qjsc_exe = executable( qjsc_srcs, c_args: qjs_c_args, - link_with: qjs_libc ? [] : qjs_libc_lib, - dependencies: qjs_dep, - + link_with: [cutils_lib], + dependencies: [qjs_dep, qjs_libc_dep], install: true, ) @@ -300,8 +327,8 @@ qjs_exe = executable( qjs_exe_srcs, c_args: qjs_c_args, - link_with: qjs_libc ? [] : qjs_libc_lib, - dependencies: [qjs_dep, mimalloc_dep], + link_with: [cutils_lib], + dependencies: [qjs_dep, qjs_libc_dep, mimalloc_dep], export_dynamic: true, install: true, @@ -328,7 +355,7 @@ if meson.is_cross_build() qjs_libc_srcs, dependencies: qjs_sys_native_deps, - c_args: qjs_c_args, + c_args: [qjs_c_args, '-DQUICKJS_NG_QJS_INTERNAL'], gnu_symbol_visibility: 'hidden', build_by_default: false, @@ -381,10 +408,10 @@ if tests.allowed() run262_exe = executable( 'run-test262', 'run-test262.c', - qjs_libc_srcs, + link_with: cutils_lib, c_args: qjs_c_args, - dependencies: qjs_dep, + dependencies: [qjs_dep, qjs_libc_dep] ) test( @@ -484,6 +511,7 @@ if tests.allowed() 'api-test', 'api-test.c', + link_with: cutils_lib, c_args: qjs_c_args, dependencies: qjs_dep, build_by_default: false, @@ -496,10 +524,9 @@ if tests.allowed() executable( 'function_source', 'gen/function_source.c', - qjs_libc_srcs, c_args: qjs_c_args, - dependencies: qjs_dep, + dependencies: [qjs_dep, qjs_libc_dep], build_by_default: false, ), ) @@ -508,9 +535,9 @@ endif # Unicode generator unicode_gen = executable( 'unicode_gen', - 'cutils.c', 'unicode_gen.c', + link_with: cutils_lib, c_args: qjs_c_args, build_by_default: false, ) @@ -607,19 +634,17 @@ if examples.allowed() executable( 'hello', 'gen/hello.c', - qjs_libc_srcs, c_args: qjs_c_args, - dependencies: qjs_dep, + dependencies: [qjs_dep, qjs_libc_dep] ) executable( 'hello_module', 'gen/hello_module.c', - qjs_libc_srcs, c_args: qjs_c_args, - dependencies: qjs_dep, + dependencies: [qjs_dep, qjs_libc_dep] ) subdir('examples') @@ -628,10 +653,9 @@ if examples.allowed() 'test_fib', 'examples/fib.c', 'gen/test_fib.c', - qjs_libc_srcs, - c_args: qjs_c_args, - dependencies: qjs_dep, + c_args: [qjs_c_args, qjs_module_args], + dependencies: [qjs_dep, qjs_libc_dep], export_dynamic: true, ) endif diff --git a/quickjs-libc.h b/quickjs-libc.h index 58c2525bc..06aae5b83 100644 --- a/quickjs-libc.h +++ b/quickjs-libc.h @@ -34,49 +34,41 @@ extern "C" { #endif -#if defined(__GNUC__) || defined(__clang__) -#define JS_EXTERN __attribute__((visibility("default"))) -#else -#define JS_EXTERN /* nothing */ -#endif - -JS_EXTERN JSModuleDef *js_init_module_std(JSContext *ctx, +JS_LIBC_EXTERN JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name); -JS_EXTERN JSModuleDef *js_init_module_os(JSContext *ctx, +JS_LIBC_EXTERN JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name); -JS_EXTERN JSModuleDef *js_init_module_bjson(JSContext *ctx, +JS_LIBC_EXTERN JSModuleDef *js_init_module_bjson(JSContext *ctx, const char *module_name); -JS_EXTERN void js_std_add_helpers(JSContext *ctx, int argc, char **argv); -JS_EXTERN int js_std_loop(JSContext *ctx); -JS_EXTERN JSValue js_std_await(JSContext *ctx, JSValue obj); -JS_EXTERN void js_std_init_handlers(JSRuntime *rt); -JS_EXTERN void js_std_free_handlers(JSRuntime *rt); -JS_EXTERN void js_std_dump_error(JSContext *ctx); -JS_EXTERN uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, +JS_LIBC_EXTERN void js_std_add_helpers(JSContext *ctx, int argc, char **argv); +JS_LIBC_EXTERN int js_std_loop(JSContext *ctx); +JS_LIBC_EXTERN JSValue js_std_await(JSContext *ctx, JSValue obj); +JS_LIBC_EXTERN void js_std_init_handlers(JSRuntime *rt); +JS_LIBC_EXTERN void js_std_free_handlers(JSRuntime *rt); +JS_LIBC_EXTERN void js_std_dump_error(JSContext *ctx); +JS_LIBC_EXTERN uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename); -JS_EXTERN int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, +JS_LIBC_EXTERN int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, bool use_realpath, bool is_main); -JS_EXTERN JSModuleDef *js_module_loader(JSContext *ctx, +JS_LIBC_EXTERN JSModuleDef *js_module_loader(JSContext *ctx, const char *module_name, void *opaque, JSValueConst attributes); -JS_EXTERN int js_module_check_attributes(JSContext *ctx, void *opaque, +JS_LIBC_EXTERN int js_module_check_attributes(JSContext *ctx, void *opaque, JSValueConst attributes); -JS_EXTERN int js_module_test_json(JSContext *ctx, JSValueConst attributes); -JS_EXTERN void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, +JS_LIBC_EXTERN int js_module_test_json(JSContext *ctx, JSValueConst attributes); +JS_LIBC_EXTERN void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, int flags); -JS_EXTERN void js_std_promise_rejection_tracker(JSContext *ctx, +JS_LIBC_EXTERN void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise, JSValueConst reason, bool is_handled, void *opaque); // Defaults to JS_NewRuntime, no-op if compiled without worker support. // Call before creating the first worker thread. -JS_EXTERN void js_std_set_worker_new_runtime_func(JSRuntime *(*func)(void)); +JS_LIBC_EXTERN void js_std_set_worker_new_runtime_func(JSRuntime *(*func)(void)); // Defaults to JS_NewContext, no-op if compiled without worker support. // Call before creating the first worker thread. -JS_EXTERN void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)); - -#undef JS_EXTERN +JS_LIBC_EXTERN void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)); #ifdef __cplusplus } /* extern "C" { */ diff --git a/quickjs.h b/quickjs.h index d66051324..2dd41e42b 100644 --- a/quickjs.h +++ b/quickjs.h @@ -39,14 +39,104 @@ extern "C" { #define QUICKJS_NG 1 +/* Helpers. */ +#if defined(_WIN32) || defined(__CYGWIN__) +# define QUICKJS_NG_PLAT_WIN32 1 +#endif /* defined(_WIN32) || defined(__CYGWIN__) */ + #if defined(__GNUC__) || defined(__clang__) -#define js_force_inline inline __attribute__((always_inline)) -#define JS_EXTERN __attribute__((visibility("default"))) +# define QUICKJS_NG_CC_GNULIKE 1 +#endif /* defined(__GNUC__) || defined(__clang__) */ + +/* + * `js_force_inline` -- helper macro forcing the inlining of a function. + */ +#ifdef QUICKJS_NG_PLAT_WIN32 +# ifdef QUICKJS_NG_CC_GNULIKE +# define js_force_inline inline __attribute__((always_inline)) +# else +# define js_force_inline __forceinline +# endif +#else +# ifdef QUICKJS_NG_CC_GNULIKE +# define js_force_inline inline __attribute__((always_inline)) +# else +# define js_force_inline inline +# endif +#endif /* QUICKJS_NG_PLAT_WIN32 */ + +/* + * `JS_EXTERN` -- helper macro that must be used to mark the external + * interfaces of libqjs. + * + * Explicitly undefine the macro first in case a previous header included this. + * This is done in order to avoid the redefinition warnings/errors upon a + * different definition of `JS_EXTERN`. + * + * Windows note: The `__declspec` syntax is supported by both Clang and GCC. + * The QUICKJS_NG_QJS_INTERNAL macro must be defined for libqjs (and only for + * it) to properly export symbols. + */ +#ifdef QUICKJS_NG_PLAT_WIN32 +/* Define QUICKJS_NG_DLL if building or using shared qjs. */ +# ifdef QUICKJS_NG_DLL +# ifdef QUICKJS_NG_QJS_INTERNAL +# define JS_EXTERN __declspec(dllexport) +# else +# define JS_EXTERN __declspec(dllimport) +# endif +# else +# define JS_EXTERN /* nothing */ +# endif +#else +# ifdef QUICKJS_NG_CC_GNULIKE +# define JS_EXTERN __attribute__((visibility("default"))) +# else +# define JS_EXTERN /* nothing */ +# endif +#endif /* QUICKJS_NG_PLAT_WIN32 */ + +/* + * `JS_LIBC_EXTERN` -- helper macro that must be used to mark the extern + * interfaces of quickjs-libc specifically. + */ +#if defined(QUICKJS_NG_BUILD) && !defined(QJS_BUILD_LIBC) && defined(QUICKJS_NG_PLAT_WIN32) +/* + * We are building QuickJS-NG, quickjs-libc is a static library and we are on + * Windows. Then, make sure to not export any interfaces. + */ +# define JS_LIBC_EXTERN /* nothing */ #else -#define js_force_inline inline -#define JS_EXTERN /* nothing */ +/* + * Otherwise, if we are either (1) not building QuickJS-NG, (2) libc is built as + * a part of libqjs, or (3) we are not on Windows, define JS_LIBC_EXTERN to + * JS_EXTERN. + */ +# define JS_LIBC_EXTERN JS_EXTERN #endif +/* + * `JS_MODULE_EXTERN` -- helper macro that must be used to mark `js_init_module` + * and other public functions of the binary modules. See examples/ for examples + * of the usage. + * + * Windows note: -DQUICKJS_NG_MODULE_BUILD must be set when building a binary + * module to properly set __declspec. + */ +#ifdef QUICKJS_NG_PLAT_WIN32 +# ifdef QUICKJS_NG_MODULE_BUILD +# define JS_MODULE_EXTERN __declspec(dllexport) +# else +# define JS_MODULE_EXTERN __declspec(dllimport) +# endif +#else +# ifdef QUICKJS_NG_CC_GNULIKE +# define JS_MODULE_EXTERN __attribute__((visibility("default"))) +# else +# define JS_MODULE_EXTERN /* nothing */ +# endif +#endif /* QUICKJS_NG_PLAT_WIN32 */ + /* Borrowed from Folly */ #ifndef JS_PRINTF_FORMAT #ifdef _MSC_VER @@ -65,6 +155,9 @@ extern "C" { #endif #endif +#undef QUICKJS_NG_CC_GNULIKE +#undef QUICKJS_NG_PLAT_WIN32 + typedef struct JSRuntime JSRuntime; typedef struct JSContext JSContext; typedef struct JSObject JSObject; @@ -1325,7 +1418,6 @@ JS_EXTERN const char* JS_GetVersion(void); /* Integration point for quickjs-libc.c, not for public use. */ JS_EXTERN uintptr_t js_std_cmd(int cmd, ...); -#undef JS_EXTERN #undef js_force_inline #ifdef __cplusplus