Created
January 4, 2023 16:41
-
-
Save robbertvanginkel/5cb999d5b6fb094bd0d286c644617640 to your computer and use it in GitHub Desktop.
quickjs wasi wazero
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 58e4fc1373b6ee5d3810b7e4668762de87731b2f Mon Sep 17 00:00:00 2001 | |
From: Robbert van Ginkel <[email protected]> | |
Date: Wed, 4 Jan 2023 11:05:15 -0500 | |
Subject: [PATCH] Add wazero based build script | |
To build the quickjs interpreter, some js files need to be transformed into | |
quickjs bytecode using qjsc. | |
--- | |
build.sh | 36 ++++++++++++++++++++++++++++++++++++ | |
qjs.c | 4 ++-- | |
qjsc.c | 2 +- | |
quickjs-libc.c | 50 ++++++++++++++++++++++++++++++++++++++++++++------ | |
quickjs.c | 12 ++++++------ | |
quickjs.h | 2 +- | |
6 files changed, 90 insertions(+), 16 deletions(-) | |
create mode 100644 build.sh | |
diff --git a/build.sh b/build.sh | |
new file mode 100644 | |
index 0000000..463716a | |
--- /dev/null | |
+++ b/build.sh | |
@@ -0,0 +1,36 @@ | |
+#!/usr/bin/env bash | |
+ | |
+set -euxo pipefail | |
+ | |
+WASI_SDK_PATH="${WASI_SDK_PATH:-/opt/wasi-sdk}" | |
+ | |
+SHARED_FILES=(libunicode cutils libbf libregexp quickjs quickjs-libc) | |
+ | |
+"$WASI_SDK_PATH/bin/clang" \ | |
+ "--sysroot=$WASI_SDK_PATH/share/wasi-sysroot" \ | |
+ -c "${SHARED_FILES[@]/%/.c}" qjsc.c \ | |
+ -DCONFIG_VERSION='"wasi"' \ | |
+ -DCONFIG_BIGNUM=y \ | |
+ -D_WASI_EMULATED_SIGNAL \ | |
+ -D_WASI_EMULATED_GETPID \ | |
+ -O3 | |
+ | |
+"$WASI_SDK_PATH/bin/clang" \ | |
+ "--sysroot=$WASI_SDK_PATH/share/wasi-sysroot" \ | |
+ -lwasi-emulated-signal -lwasi-emulated-getpid \ | |
+ -O3 \ | |
+ "${SHARED_FILES[@]/%/.o}" qjsc.o -o qjsc.wasm | |
+ | |
+wazero run -mount ".:/" qjsc.wasm -- -c -o /repl.c -m /repl.js | |
+wazero run -mount ".:/" qjsc.wasm -- -fbignum -c -o /qjscalc.c /qjscalc.js | |
+ | |
+"$WASI_SDK_PATH/bin/clang" \ | |
+ "--sysroot=$WASI_SDK_PATH/share/wasi-sysroot" \ | |
+ "${SHARED_FILES[@]/%/.o}" \ | |
+ repl.c qjs.c qjscalc.c \ | |
+ -I . \ | |
+ -DCONFIG_VERSION='"wasi"' \ | |
+ -DCONFIG_BIGNUM=y \ | |
+ -D_WASI_EMULATED_PROCESS_CLOCKS -lwasi-emulated-process-clocks \ | |
+ -D_WASI_EMULATED_SIGNAL -lwasi-emulated-signal \ | |
+ -O3 -g -o qjs.wasm | |
diff --git a/qjs.c b/qjs.c | |
index d56b843..1039b86 100644 | |
--- a/qjs.c | |
+++ b/qjs.c | |
@@ -146,7 +146,7 @@ static inline size_t js_trace_malloc_usable_size(void *ptr) | |
return malloc_size(ptr); | |
#elif defined(_WIN32) | |
return _msize(ptr); | |
-#elif defined(EMSCRIPTEN) | |
+#elif defined(EMSCRIPTEN) || defined(__wasi__) | |
return 0; | |
#elif defined(__linux__) | |
return malloc_usable_size(ptr); | |
@@ -268,7 +268,7 @@ static const JSMallocFunctions trace_mf = { | |
malloc_size, | |
#elif defined(_WIN32) | |
(size_t (*)(const void *))_msize, | |
-#elif defined(EMSCRIPTEN) | |
+#elif defined(EMSCRIPTEN) || defined(__wasi__) | |
NULL, | |
#elif defined(__linux__) | |
(size_t (*)(const void *))malloc_usable_size, | |
diff --git a/qjsc.c b/qjsc.c | |
index b9f1e4c..c1a9eaf 100644 | |
--- a/qjsc.c | |
+++ b/qjsc.c | |
@@ -29,7 +29,7 @@ | |
#include <assert.h> | |
#include <unistd.h> | |
#include <errno.h> | |
-#if !defined(_WIN32) | |
+#if !defined(_WIN32) && !defined(__wasi__) | |
#include <sys/wait.h> | |
#endif | |
diff --git a/quickjs-libc.c b/quickjs-libc.c | |
index e180dd0..43b8c6f 100644 | |
--- a/quickjs-libc.c | |
+++ b/quickjs-libc.c | |
@@ -42,10 +42,12 @@ | |
#include <conio.h> | |
#include <utime.h> | |
#else | |
+#if !defined(__wasi__) | |
#include <dlfcn.h> | |
#include <termios.h> | |
-#include <sys/ioctl.h> | |
#include <sys/wait.h> | |
+#endif | |
+#include <sys/ioctl.h> | |
#if defined(__APPLE__) | |
typedef sig_t sighandler_t; | |
@@ -57,7 +59,7 @@ typedef sig_t sighandler_t; | |
#endif | |
-#if !defined(_WIN32) | |
+#if !defined(_WIN32) && !defined(__wasi__) | |
/* enable the os.Worker API. IT relies on POSIX threads */ | |
#define USE_WORKER | |
#endif | |
@@ -453,7 +455,7 @@ typedef JSModuleDef *(JSInitModuleFunc)(JSContext *ctx, | |
const char *module_name); | |
-#if defined(_WIN32) | |
+#if defined(_WIN32) || defined(__wasi__) | |
static JSModuleDef *js_module_loader_so(JSContext *ctx, | |
const char *module_name) | |
{ | |
@@ -530,7 +532,7 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, | |
return -1; | |
if (!strchr(module_name, ':')) { | |
strcpy(buf, "file://"); | |
-#if !defined(_WIN32) | |
+#if !defined(_WIN32) && !defined(__wasi__) | |
/* realpath() cannot be used with modules compiled with qjsc | |
because the corresponding module source code is not | |
necessarily present */ | |
@@ -680,6 +682,7 @@ static JSValue js_std_unsetenv(JSContext *ctx, JSValueConst this_val, | |
static JSValue js_std_getenviron(JSContext *ctx, JSValueConst this_val, | |
int argc, JSValueConst *argv) | |
{ | |
+#if !defined(__wasi__) | |
char **envp; | |
const char *name, *p, *value; | |
JSValue obj; | |
@@ -712,6 +715,12 @@ static JSValue js_std_getenviron(JSContext *ctx, JSValueConst this_val, | |
fail: | |
JS_FreeValue(ctx, obj); | |
return JS_EXCEPTION; | |
+#else | |
+ JSValue obj; | |
+ obj = JS_NewObject(ctx); | |
+ JS_FreeValue(ctx,obj); | |
+ return obj; | |
+#endif | |
} | |
static JSValue js_std_gc(JSContext *ctx, JSValueConst this_val, | |
@@ -797,9 +806,11 @@ static void js_std_file_finalizer(JSRuntime *rt, JSValue val) | |
JSSTDFile *s = JS_GetOpaque(val, js_std_file_class_id); | |
if (s) { | |
if (s->f && s->close_in_finalizer) { | |
+#if !defined(__wasi__) | |
if (s->is_popen) | |
pclose(s->f); | |
else | |
+#endif | |
fclose(s->f); | |
} | |
js_free_rt(rt, s); | |
@@ -901,6 +912,7 @@ static JSValue js_std_open(JSContext *ctx, JSValueConst this_val, | |
return JS_EXCEPTION; | |
} | |
+#if !defined(__wasi__) | |
static JSValue js_std_popen(JSContext *ctx, JSValueConst this_val, | |
int argc, JSValueConst *argv) | |
{ | |
@@ -936,6 +948,7 @@ static JSValue js_std_popen(JSContext *ctx, JSValueConst this_val, | |
JS_FreeCString(ctx, mode); | |
return JS_EXCEPTION; | |
} | |
+#endif | |
static JSValue js_std_fdopen(JSContext *ctx, JSValueConst this_val, | |
int argc, JSValueConst *argv) | |
@@ -970,6 +983,7 @@ static JSValue js_std_fdopen(JSContext *ctx, JSValueConst this_val, | |
return JS_EXCEPTION; | |
} | |
+#if !defined(__wasi__) | |
static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val, | |
int argc, JSValueConst *argv) | |
{ | |
@@ -981,6 +995,7 @@ static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val, | |
return JS_NULL; | |
return js_new_std_file(ctx, f, TRUE, FALSE); | |
} | |
+#endif | |
static JSValue js_std_sprintf(JSContext *ctx, JSValueConst this_val, | |
int argc, JSValueConst *argv) | |
@@ -1041,8 +1056,10 @@ static JSValue js_std_file_close(JSContext *ctx, JSValueConst this_val, | |
return JS_EXCEPTION; | |
if (!s->f) | |
return JS_ThrowTypeError(ctx, "invalid file handle"); | |
+#if !defined(__wasi__) | |
if (s->is_popen) | |
err = js_get_errno(pclose(s->f)); | |
+#endif | |
else | |
err = js_get_errno(fclose(s->f)); | |
s->f = NULL; | |
@@ -1273,6 +1290,7 @@ static JSValue js_std_file_putByte(JSContext *ctx, JSValueConst this_val, | |
} | |
/* urlGet */ | |
+#if !defined(__wasi__) | |
#define URL_GET_PROGRAM "curl -s -i" | |
#define URL_GET_BUF_SIZE 4096 | |
@@ -1457,6 +1475,7 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val, | |
JS_FreeValue(ctx, response); | |
return JS_EXCEPTION; | |
} | |
+#endif | |
static JSClassDef js_std_file_class = { | |
"FILE", | |
@@ -1489,16 +1508,22 @@ static const JSCFunctionListEntry js_std_funcs[] = { | |
JS_CFUNC_DEF("setenv", 1, js_std_setenv ), | |
JS_CFUNC_DEF("unsetenv", 1, js_std_unsetenv ), | |
JS_CFUNC_DEF("getenviron", 1, js_std_getenviron ), | |
+#if !defined(__wasi__) | |
JS_CFUNC_DEF("urlGet", 1, js_std_urlGet ), | |
+#endif | |
JS_CFUNC_DEF("loadFile", 1, js_std_loadFile ), | |
JS_CFUNC_DEF("strerror", 1, js_std_strerror ), | |
JS_CFUNC_DEF("parseExtJSON", 1, js_std_parseExtJSON ), | |
/* FILE I/O */ | |
JS_CFUNC_DEF("open", 2, js_std_open ), | |
+#if !defined(__wasi__) | |
JS_CFUNC_DEF("popen", 2, js_std_popen ), | |
+#endif | |
JS_CFUNC_DEF("fdopen", 2, js_std_fdopen ), | |
+#if !defined(__wasi__) | |
JS_CFUNC_DEF("tmpfile", 0, js_std_tmpfile ), | |
+#endif | |
JS_CFUNC_MAGIC_DEF("puts", 1, js_std_file_puts, 0 ), | |
JS_CFUNC_DEF("printf", 1, js_std_printf ), | |
JS_CFUNC_DEF("sprintf", 1, js_std_sprintf ), | |
@@ -1665,7 +1690,7 @@ static JSValue js_os_isatty(JSContext *ctx, JSValueConst this_val, | |
return JS_EXCEPTION; | |
return JS_NewBool(ctx, (isatty(fd) != 0)); | |
} | |
- | |
+#if !defined(__wasi__) | |
#if defined(_WIN32) | |
static JSValue js_os_ttyGetWinSize(JSContext *ctx, JSValueConst this_val, | |
int argc, JSValueConst *argv) | |
@@ -1770,6 +1795,7 @@ static JSValue js_os_ttySetRaw(JSContext *ctx, JSValueConst this_val, | |
} | |
#endif /* !_WIN32 */ | |
+#endif /* !__wasi__ */ | |
static JSValue js_os_remove(JSContext *ctx, JSValueConst this_val, | |
int argc, JSValueConst *argv) | |
@@ -1919,6 +1945,7 @@ typedef void (*sighandler_t)(int sig_num); | |
static JSValue js_os_signal(JSContext *ctx, JSValueConst this_val, | |
int argc, JSValueConst *argv) | |
{ | |
+#if !defined(__wasi__) | |
JSRuntime *rt = JS_GetRuntime(ctx); | |
JSThreadState *ts = JS_GetRuntimeOpaque(rt); | |
JSOSSignalHandler *sh; | |
@@ -1960,6 +1987,7 @@ static JSValue js_os_signal(JSContext *ctx, JSValueConst this_val, | |
sh->func = JS_DupValue(ctx, func); | |
signal(sig_num, os_signal_handler); | |
} | |
+#endif | |
return JS_UNDEFINED; | |
} | |
@@ -2650,6 +2678,7 @@ static char *realpath(const char *path, char *buf) | |
} | |
#endif | |
+#if !defined(__wasi__) | |
/* return [path, errorcode] */ | |
static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val, | |
int argc, JSValueConst *argv) | |
@@ -2671,6 +2700,7 @@ static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val, | |
} | |
return make_string_error(ctx, buf, err); | |
} | |
+#endif | |
#if !defined(_WIN32) | |
static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val, | |
@@ -2717,6 +2747,7 @@ static JSValue js_os_readlink(JSContext *ctx, JSValueConst this_val, | |
return make_string_error(ctx, buf, err); | |
} | |
+#if !defined(__wasi__) | |
static char **build_envp(JSContext *ctx, JSValueConst obj) | |
{ | |
uint32_t len, i; | |
@@ -3119,6 +3150,7 @@ static JSValue js_os_dup2(JSContext *ctx, JSValueConst this_val, | |
} | |
#endif /* !_WIN32 */ | |
+#endif /* !__wasi__ */ | |
#ifdef USE_WORKER | |
@@ -3569,7 +3601,7 @@ void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)) | |
#define OS_PLATFORM "win32" | |
#elif defined(__APPLE__) | |
#define OS_PLATFORM "darwin" | |
-#elif defined(EMSCRIPTEN) | |
+#elif defined(EMSCRIPTEN) || defined(__wasi__) | |
#define OS_PLATFORM "js" | |
#else | |
#define OS_PLATFORM "linux" | |
@@ -3595,8 +3627,10 @@ static const JSCFunctionListEntry js_os_funcs[] = { | |
JS_CFUNC_MAGIC_DEF("read", 4, js_os_read_write, 0 ), | |
JS_CFUNC_MAGIC_DEF("write", 4, js_os_read_write, 1 ), | |
JS_CFUNC_DEF("isatty", 1, js_os_isatty ), | |
+#if !defined(__wasi__) | |
JS_CFUNC_DEF("ttyGetWinSize", 1, js_os_ttyGetWinSize ), | |
JS_CFUNC_DEF("ttySetRaw", 1, js_os_ttySetRaw ), | |
+#endif | |
JS_CFUNC_DEF("remove", 1, js_os_remove ), | |
JS_CFUNC_DEF("rename", 2, js_os_rename ), | |
JS_CFUNC_MAGIC_DEF("setReadHandler", 2, js_os_setReadHandler, 0 ), | |
@@ -3644,11 +3678,14 @@ static const JSCFunctionListEntry js_os_funcs[] = { | |
JS_CFUNC_MAGIC_DEF("stat", 1, js_os_stat, 0 ), | |
JS_CFUNC_DEF("utimes", 3, js_os_utimes ), | |
JS_CFUNC_DEF("sleep", 1, js_os_sleep ), | |
+#if !defined(__wasi__) | |
JS_CFUNC_DEF("realpath", 1, js_os_realpath ), | |
+#endif | |
#if !defined(_WIN32) | |
JS_CFUNC_MAGIC_DEF("lstat", 1, js_os_stat, 1 ), | |
JS_CFUNC_DEF("symlink", 2, js_os_symlink ), | |
JS_CFUNC_DEF("readlink", 1, js_os_readlink ), | |
+#if !defined(__wasi__) | |
JS_CFUNC_DEF("exec", 1, js_os_exec ), | |
JS_CFUNC_DEF("waitpid", 2, js_os_waitpid ), | |
OS_FLAG(WNOHANG), | |
@@ -3657,6 +3694,7 @@ static const JSCFunctionListEntry js_os_funcs[] = { | |
JS_CFUNC_DEF("dup", 1, js_os_dup ), | |
JS_CFUNC_DEF("dup2", 2, js_os_dup2 ), | |
#endif | |
+#endif | |
}; | |
static int js_os_init(JSContext *ctx, JSModuleDef *m) | |
diff --git a/quickjs.c b/quickjs.c | |
index 48aeffc..1cb736a 100644 | |
--- a/quickjs.c | |
+++ b/quickjs.c | |
@@ -50,7 +50,7 @@ | |
#define OPTIMIZE 1 | |
#define SHORT_OPCODES 1 | |
-#if defined(EMSCRIPTEN) | |
+#if defined(EMSCRIPTEN) || defined(__wasi__) | |
#define DIRECT_DISPATCH 0 | |
#else | |
#define DIRECT_DISPATCH 1 | |
@@ -62,18 +62,18 @@ | |
#define MALLOC_OVERHEAD 8 | |
#endif | |
-#if !defined(_WIN32) | |
+#if !defined(_WIN32) && !defined(__wasi__) | |
/* define it if printf uses the RNDN rounding mode instead of RNDNA */ | |
#define CONFIG_PRINTF_RNDN | |
#endif | |
/* define to include Atomics.* operations which depend on the OS | |
threads */ | |
-#if !defined(EMSCRIPTEN) | |
+#if !defined(EMSCRIPTEN) && !defined(__wasi__) | |
#define CONFIG_ATOMICS | |
#endif | |
-#if !defined(EMSCRIPTEN) | |
+#if !defined(EMSCRIPTEN) && !defined(__wasi__) | |
/* enable stack limitation */ | |
#define CONFIG_STACK_CHECK | |
#endif | |
@@ -1680,7 +1680,7 @@ static inline size_t js_def_malloc_usable_size(void *ptr) | |
return malloc_size(ptr); | |
#elif defined(_WIN32) | |
return _msize(ptr); | |
-#elif defined(EMSCRIPTEN) | |
+#elif defined(EMSCRIPTEN) || defined(__wasi__) | |
return 0; | |
#elif defined(__linux__) | |
return malloc_usable_size(ptr); | |
@@ -1754,7 +1754,7 @@ static const JSMallocFunctions def_malloc_funcs = { | |
malloc_size, | |
#elif defined(_WIN32) | |
(size_t (*)(const void *))_msize, | |
-#elif defined(EMSCRIPTEN) | |
+#elif defined(EMSCRIPTEN) || defined(__wasi__) | |
NULL, | |
#elif defined(__linux__) | |
(size_t (*)(const void *))malloc_usable_size, | |
diff --git a/quickjs.h b/quickjs.h | |
index d4a5cd3..7e90f00 100644 | |
--- a/quickjs.h | |
+++ b/quickjs.h | |
@@ -53,7 +53,7 @@ typedef struct JSClass JSClass; | |
typedef uint32_t JSClassID; | |
typedef uint32_t JSAtom; | |
-#if INTPTR_MAX >= INT64_MAX | |
+#if INTPTR_MAX >= INT64_MAX && !defined(__wasi__) | |
#define JS_PTR64 | |
#define JS_PTR64_DEF(a) a | |
#else | |
-- | |
2.38.1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment