Skip to content

enable windows binary module import #497

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ if(BUILD_SHARED_LIBS)
message(STATUS "Building a shared library")
endif()

xoption(BUILD_EXAMPLES "Build examples" OFF)
xoption(BUILD_EXAMPLES "Build examples" ON)
xoption(BUILD_STATIC_QJS_EXE "Build a static qjs executable" OFF)
xoption(CONFIG_ASAN "Enable AddressSanitizer (ASan)" OFF)
xoption(CONFIG_MSAN "Enable MemorySanitizer (MSan)" OFF)
Expand Down Expand Up @@ -177,6 +177,12 @@ endif()

add_library(qjs ${qjs_sources})
target_compile_definitions(qjs PRIVATE ${qjs_defines})
if(NOT MSVC)
target_compile_options(qjs PRIVATE -fPIC)
endif()
if(NOT MSVC)
target_compile_options(qjs PRIVATE -fPIC)
endif()
target_include_directories(qjs PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
Expand Down Expand Up @@ -270,7 +276,7 @@ target_link_libraries(function_source ${qjs_libs})
# Examples
#

if(BUILD_EXAMPLES AND NOT WIN32)
if(BUILD_EXAMPLES) # AND NOT WIN32
add_executable(hello
gen/hello.c
)
Expand All @@ -287,12 +293,14 @@ if(BUILD_EXAMPLES AND NOT WIN32)
target_compile_definitions(hello_module PRIVATE ${qjs_defines})
target_link_libraries(hello_module ${qjs_libs})

if(NOT WIN32)
# if(NOT WIN32)
add_library(fib MODULE examples/fib.c)
set_target_properties(fib PROPERTIES
PREFIX ""
C_VISIBILITY_PRESET default
)
target_include_directories(fib PRIVATE .)
target_link_libraries(fib PRIVATE qjs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there no way to do lazy symbol binding on windows?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i am not sure

target_compile_definitions(fib PRIVATE JS_SHARED_LIBRARY)
if(APPLE)
target_link_options(fib PRIVATE -undefined dynamic_lookup)
Expand All @@ -303,11 +311,13 @@ if(BUILD_EXAMPLES AND NOT WIN32)
PREFIX ""
C_VISIBILITY_PRESET default
)
target_include_directories(point PRIVATE .)
target_link_libraries(point PRIVATE qjs)
target_compile_definitions(point PRIVATE JS_SHARED_LIBRARY)
if(APPLE)
target_link_options(point PRIVATE -undefined dynamic_lookup)
endif()
endif()
# endif()

add_executable(test_fib
examples/fib.c
Expand Down
10 changes: 8 additions & 2 deletions examples/fib.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "../quickjs.h"
#include "quickjs.h"

#if defined(_WIN32)
#define FIB_API __declspec(dllexport)
#else
#define FIB_API
#endif

#define countof(x) (sizeof(x) / sizeof((x)[0]))

Expand Down Expand Up @@ -61,7 +67,7 @@ static int js_fib_init(JSContext *ctx, JSModuleDef *m)
#define JS_INIT_MODULE js_init_module_fib
#endif

JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name)
FIB_API JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name)
{
JSModuleDef *m;
m = JS_NewCModule(ctx, module_name, js_fib_init);
Expand Down
52 changes: 33 additions & 19 deletions examples/point.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,17 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "../quickjs.h"

/* point.c */
#include "quickjs.h"
#include <math.h>

#if defined(_WIN32)
#define POINT_API __declspec(dllexport)
#else
#define POINT_API
#endif

#define countof(x) (sizeof(x) / sizeof((x)[0]))

/* Point Class */
Expand All @@ -35,18 +43,18 @@ typedef struct {

static JSClassID js_point_class_id;

static void js_point_finalizer(JSRuntime *rt, JSValue val)
static void js_point_finalizer(JSRuntime* rt, JSValue val)
{
JSPointData *s = JS_GetOpaque(val, js_point_class_id);
JSPointData* s = JS_GetOpaque(val, js_point_class_id);
/* Note: 's' can be NULL in case JS_SetOpaque() was not called */
js_free_rt(rt, s);
}

static JSValue js_point_ctor(JSContext *ctx,
JSValue new_target,
int argc, JSValue *argv)
static JSValue js_point_ctor(JSContext* ctx,
JSValue new_target,
int argc, JSValue* argv)
{
JSPointData *s;
JSPointData* s;
JSValue obj = JS_UNDEFINED;
JSValue proto;

Expand All @@ -68,15 +76,15 @@ static JSValue js_point_ctor(JSContext *ctx,
goto fail;
JS_SetOpaque(obj, s);
return obj;
fail:
fail:
js_free(ctx, s);
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}

static JSValue js_point_get_xy(JSContext *ctx, JSValue this_val, int magic)
static JSValue js_point_get_xy(JSContext* ctx, JSValue this_val, int magic)
{
JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
JSPointData* s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
if (!s)
return JS_EXCEPTION;
if (magic == 0)
Expand All @@ -85,9 +93,9 @@ static JSValue js_point_get_xy(JSContext *ctx, JSValue this_val, int magic)
return JS_NewInt32(ctx, s->y);
}

static JSValue js_point_set_xy(JSContext *ctx, JSValue this_val, JSValue val, int magic)
static JSValue js_point_set_xy(JSContext* ctx, JSValue this_val, JSValue val, int magic)
{
JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
JSPointData* s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
int v;
if (!s)
return JS_EXCEPTION;
Expand All @@ -100,10 +108,10 @@ static JSValue js_point_set_xy(JSContext *ctx, JSValue this_val, JSValue val, in
return JS_UNDEFINED;
}

static JSValue js_point_norm(JSContext *ctx, JSValue this_val,
int argc, JSValue *argv)
static JSValue js_point_norm(JSContext* ctx, JSValue this_val,
int argc, JSValue* argv)
{
JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
JSPointData* s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
if (!s)
return JS_EXCEPTION;
return JS_NewFloat64(ctx, sqrt((double)s->x * s->x + (double)s->y * s->y));
Expand All @@ -120,10 +128,10 @@ static const JSCFunctionListEntry js_point_proto_funcs[] = {
JS_CFUNC_DEF("norm", 0, js_point_norm),
};

static int js_point_init(JSContext *ctx, JSModuleDef *m)
static int js_point_init(JSContext* ctx, JSModuleDef* m)
{
JSValue point_proto, point_class;
JSRuntime *rt = JS_GetRuntime(ctx);
JSRuntime* rt = JS_GetRuntime(ctx);

/* create the Point class */
JS_NewClassID(rt, &js_point_class_id);
Expand All @@ -141,9 +149,15 @@ static int js_point_init(JSContext *ctx, JSModuleDef *m)
return 0;
}

JSModuleDef *js_init_module(JSContext *ctx, const char *module_name)
#ifdef JS_SHARED_LIBRARY
#define JS_INIT_MODULE js_init_module
#else
#define JS_INIT_MODULE js_init_module_fib
#endif

POINT_API JSModuleDef* JS_INIT_MODULE(JSContext* ctx, const char* module_name)
{
JSModuleDef *m;
JSModuleDef* m;
m = JS_NewCModule(ctx, module_name, js_point_init);
if (!m)
return NULL;
Expand Down
53 changes: 52 additions & 1 deletion quickjs-libc.c
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,58 @@ typedef JSModuleDef *(JSInitModuleFunc)(JSContext *ctx,
const char *module_name);


#if defined(_WIN32) || defined(__wasi__)
#if defined(_WIN32)
static JSModuleDef *js_module_loader_so(JSContext *ctx,
const char *module_name)
{
JSModuleDef *m;
HINSTANCE hd;
JSInitModuleFunc *init;
// allocate enough space
char *filename = js_malloc(ctx, strlen(module_name) + 2 + 1 + 1);
if (!strchr(module_name, '/')) {
if (!filename) return NULL;
strcpy(filename, "./");
strcpy(filename + 2, module_name);
} else {
strcpy(filename, module_name);
}
// change the suffix of filename from `.so` to `.dll`
char *start = filename + strlen(filename) - 2;
const char suffix[4] = "dll";
strcpy(start, suffix);

hd = LoadLibrary(filename);
if (!hd) {
JS_ThrowReferenceError(
ctx, "could not load module filename '%s' as shared library",
filename);
goto fail;
}

init = (JSInitModuleFunc *)(uintptr_t)GetProcAddress(hd, "js_init_module");
if (!init) {
JS_ThrowReferenceError(
ctx, "could not load module filename '%s': js_init_module not found",
filename);
goto fail;
}

// module_name or filename?
m = init(ctx, module_name);
if (!m) {
JS_ThrowReferenceError(
ctx, "could not load module filename '%s': initialization error",
filename);
fail:
// free the filename
js_free(ctx, filename);
if (hd) FreeLibrary(hd);
return NULL;
}
return m;
}
#elif defined(__wasi__)
static JSModuleDef *js_module_loader_so(JSContext *ctx,
const char *module_name)
{
Expand Down
Loading