windows系统下编译quickjs总结

前言

quickjs是一个轻量化的JavaScript解释器,能够支持ES6语法。不同于v8和nodejs几十M的体积,quickjs编译后只有几M大小,而且作为第三方库也只需要引用几个头文件和一个库文件,非常方便。可以将c语言代码块编译成动态链接库像一般的ES6 module一样在js代码中引用,有良好的封装性和性能表现。
相比lua而言,JavaScript使用范围更广,资料和组件较多,对用户较为友好。

准备工作

  1. 安装MSYS2
  • https://www.msys2.org/
  1. 在MSYS2中安装mingw64

pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-make mingw-w64-x86_64-dlfcn

  1. 拉取quickjs源代码

git clone https://github.com/bellard/quickjs.git

修改源码

  1. quickjs-libc.c
#if defined(_WIN32)
static JSModuleDef *js_module_loader_so(JSContext *ctx, const char *module_name)

函数修改为

static JSModuleDef *js_module_loader_so(JSContext *ctx,
                                        const char *module_name)
{

    //JS_ThrowReferenceError(ctx, "shared library modules are not supported yet");
    JSModuleDef *m;
    HINSTANCE hd;
    JSInitModuleFunc *init;

    char *filename;
    
    if (!strchr(module_name, '/')) {
        /* must add a '/' so that the DLL is not searched in the
           system library paths */
        filename = js_malloc(ctx, strlen(module_name) + 2 + 1);
        if (!filename)
            return NULL;
        strcpy(filename, "./");
        strcpy(filename + 2, module_name);
    } else {
        filename = (char *)module_name;
    }

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

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

    m = init(ctx, module_name);
    if (!m) {
        JS_ThrowReferenceError(ctx, "could not load module filename '%s': initialization error",
                               module_name);
    fail:
        if (hd)
            FreeLibrary(hd);
        return NULL;
    }
    return m;
}

JSModuleDef *js_module_loader(JSContext *ctx, const char *module_name, void *opaque)函数中

if (has_suffix(module_name, ".so") {

修改为

if (has_suffix(module_name, ".so") || has_suffix(module_name, ".dll")) {

编译

所有命令在MSYS2中完成

/mingw64/bin/mingw64-make LDEXPORT="-static -s"
strip -g
gcc -shared -o libquickjs.dll -static -s -Wl,--whole-archive libquickjs.a -lm -Wl,--no-whole-archive

第一步可能会有报错,只要能编译出exe文件可以暂时忽略报错

测试

  1. hello world
./qjsc -e -o hello.c examples/hello.js
gcc -D_GNU_SOURCE -I./ -o hello hello.c -static -s -L./ -lquickjs -lm -ldl -lpthread
./hello

打包

在MSYS2中

zip -9 -r quickjs-$(cat version)-win$(echo ${MSYSTEM:0-2}).zip qjs.exe run-test262.exe
mkdir ./bin
cp /mingw64/bin/libgcc_s_seh-1.dll ./bin/
cp /mingw64/bin/libstdc++-6.dll ./bin/
cp /mingw64/bin/libwinpthread-1.dll ./bin/
mv qjs.exe qjsc.exe run-test262.exe ./bin
mkdir -p ./lib/quickjs
strip -g libquickjs.a
mv libquickjs.a libquickjs.lto.a ./lib/quickjs
mkdir -p ./include/quickjs
cp -p quickjs.h quickjs-libc.h ./include/quickjs
zip -9 -r quickjs-$(cat version)-win$(echo ${MSYSTEM:0-2})-all.zip ./bin ./doc ./examples ./include ./lib Changelog readme.txt TODO VERSION

如果要用动态链接库链接hello.c,则第二行去掉-static-ldl-lpthread参数
2.js中引用第三方模块
在MSYS2中

/mingw64/bin/x86_64-w64-mingw32-gcc fib.c libquickjs.a -fPIC -shared -DJS_SHARED_LIBRARY -o fib.dll

把test_fib.js修改为

import { fib } from "fib.dll";

console.log("Hello World");
console.log("fib(10)=", fib(10));

如果成功输出斐波那契数列则通过
在这里插入图片描述

reference

  1. https://github.com/bellard/quickjs
  2. https://github.com/mengmo/QuickJS-Windows-Build
  3. https://zhuanlan.zhihu.com/p/380018939
  4. https://zhuanlan.zhihu.com/p/379697068
  5. https://zhuanlan.zhihu.com/p/623863082#:~:text=static%20JSModuleDef%20%2Ajs_module_loader_so%28JSContext%20%2Actx%2C%20const%20char%20%2Amodule_name%29%20%7B,%28hd%29%20FreeLibrary%28hd%29%3B%20return%20NULL%3B%20%7D%20return%20m%3B%20%7D
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值