add emscripten target
This commit is contained in:
@@ -114,7 +114,7 @@ if (target == 'playdate') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.console("Found " + c_files.length + " C files to compile")
|
log.console("Found " + text(c_files.length) + " C files to compile")
|
||||||
|
|
||||||
// Get build directory
|
// Get build directory
|
||||||
var build_dir = build.get_build_dir(target)
|
var build_dir = build.get_build_dir(target)
|
||||||
|
|||||||
@@ -45,6 +45,23 @@ Build.toolchains = {
|
|||||||
c_args: [],
|
c_args: [],
|
||||||
c_link_args: []
|
c_link_args: []
|
||||||
},
|
},
|
||||||
|
windows_i686: {
|
||||||
|
binaries: {
|
||||||
|
c: 'i686-w64-mingw32-gcc',
|
||||||
|
cpp: 'i686-w64-mingw32-g++',
|
||||||
|
ar: 'i686-w64-mingw32-ar',
|
||||||
|
windres: 'i686-w64-mingw32-windres',
|
||||||
|
strip: 'i686-w64-mingw32-strip'
|
||||||
|
},
|
||||||
|
host_machine: {
|
||||||
|
system: 'windows',
|
||||||
|
cpu_family: 'x86',
|
||||||
|
cpu: 'i686',
|
||||||
|
endian: 'little'
|
||||||
|
},
|
||||||
|
c_args: [],
|
||||||
|
c_link_args: []
|
||||||
|
},
|
||||||
linux: {
|
linux: {
|
||||||
binaries: {
|
binaries: {
|
||||||
c: 'zig cc -target x86_64-linux-musl',
|
c: 'zig cc -target x86_64-linux-musl',
|
||||||
@@ -60,6 +77,39 @@ Build.toolchains = {
|
|||||||
},
|
},
|
||||||
c_args: [],
|
c_args: [],
|
||||||
c_link_args: []
|
c_link_args: []
|
||||||
|
},
|
||||||
|
linux_arm64: {
|
||||||
|
binaries: {
|
||||||
|
c: 'zig cc -target aarch64-linux-musl',
|
||||||
|
cpp: 'zig c++ -target aarch64-linux-musl',
|
||||||
|
ar: 'zig ar',
|
||||||
|
strip: 'strip'
|
||||||
|
},
|
||||||
|
host_machine: {
|
||||||
|
system: 'linux',
|
||||||
|
cpu_family: 'aarch64',
|
||||||
|
cpu: 'aarch64',
|
||||||
|
endian: 'little'
|
||||||
|
},
|
||||||
|
c_args: [],
|
||||||
|
c_link_args: []
|
||||||
|
},
|
||||||
|
emscripten: {
|
||||||
|
binaries: {
|
||||||
|
c: 'emcc',
|
||||||
|
cpp: 'em++',
|
||||||
|
ar: 'emar',
|
||||||
|
strip: 'emstrip',
|
||||||
|
ranlib: 'emranlib'
|
||||||
|
},
|
||||||
|
host_machine: {
|
||||||
|
system: 'emscripten',
|
||||||
|
cpu_family: 'wasm32',
|
||||||
|
cpu: 'wasm32',
|
||||||
|
endian: 'little'
|
||||||
|
},
|
||||||
|
c_args: ['-sUSE_PTHREADS=0'],
|
||||||
|
c_link_args: ['-sALLOW_MEMORY_GROWTH=1', '-sEXPORTED_RUNTIME_METHODS=ccall,cwrap']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +247,7 @@ Build.select_c_files = function(files, target) {
|
|||||||
var target_suffix = target ? '_' + target : null
|
var target_suffix = target ? '_' + target : null
|
||||||
|
|
||||||
// Known target suffixes for platform-specific files
|
// Known target suffixes for platform-specific files
|
||||||
var known_targets = ['playdate', 'windows', 'linux', 'macos', 'threaded', 'single']
|
var known_targets = ['playdate', 'windows', 'linux', 'macos', 'emscripten']
|
||||||
|
|
||||||
// First pass: collect all files and identify platform-specific ones
|
// First pass: collect all files and identify platform-specific ones
|
||||||
// Group by generic name (ignoring directory) to find cross-directory variants
|
// Group by generic name (ignoring directory) to find cross-directory variants
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <bcrypt.h>
|
#include <bcrypt.h>
|
||||||
#else
|
#else
|
||||||
#include <sys/sysctl.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
@@ -22,10 +21,15 @@
|
|||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
#include <linux/sysctl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static JSClassID js_dylib_class_id;
|
static JSClassID js_dylib_class_id;
|
||||||
|
|
||||||
static void js_dylib_finalizer(JSRuntime *rt, JSValue val) {
|
static void js_dylib_finalizer(JSRuntime *rt, JSValue val) {
|
||||||
|
|||||||
178
scripts/os_emscripten.c
Normal file
178
scripts/os_emscripten.c
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
// os_emscripten.c - OS module for Emscripten (Web)
|
||||||
|
// Provides system information and utilities for the web platform
|
||||||
|
|
||||||
|
#include "cell.h"
|
||||||
|
#include <emscripten.h>
|
||||||
|
#include <emscripten/heap.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
// cell_ns - nanoseconds since some epoch
|
||||||
|
uint64_t cell_ns(void)
|
||||||
|
{
|
||||||
|
// emscripten_get_now() returns milliseconds with high precision
|
||||||
|
return (uint64_t)(emscripten_get_now() * 1000000.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cell_sleep - sleep for specified seconds
|
||||||
|
void cell_sleep(double seconds)
|
||||||
|
{
|
||||||
|
// Note: This requires ASYNCIFY to work correctly without freezing the browser
|
||||||
|
emscripten_sleep((unsigned int)(seconds * 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSC_CCALL(os_now,
|
||||||
|
return number2js(js, cell_ns());
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_sleep,
|
||||||
|
double secs = js2number(js, argv[0]);
|
||||||
|
cell_sleep(secs);
|
||||||
|
)
|
||||||
|
|
||||||
|
static JSValue js_os_totalmem(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||||
|
// Return heap size or a fixed amount?
|
||||||
|
// heap size is technically dynamic in wasm, but we can query it.
|
||||||
|
// For now, let's return the HEAP8.length equivalent via EM_ASM_INT or similar,
|
||||||
|
// or just return a safe default.
|
||||||
|
// Better yet, use mallinfo if available.
|
||||||
|
return JS_NewInt64(js, (int64_t)emscripten_get_heap_size());
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_os_platform(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||||
|
return JS_NewString(js, "Emscripten");
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_os_hostname(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||||
|
return JS_NewString(js, "browser");
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_os_arch(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||||
|
return JS_NewString(js, "wasm");
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_os_freemem(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||||
|
struct mallinfo i = mallinfo();
|
||||||
|
// Approximate free memory based on mallinfo
|
||||||
|
// total heap - used
|
||||||
|
size_t total = emscripten_get_heap_size();
|
||||||
|
size_t used = i.uordblks;
|
||||||
|
return JS_NewInt64(js, (int64_t)(total - used));
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_os_version(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||||
|
// Could return UserAgent, but for now just "web"
|
||||||
|
return JS_NewString(js, "web");
|
||||||
|
}
|
||||||
|
|
||||||
|
JSC_CCALL(os_mallinfo,
|
||||||
|
ret = JS_NewObject(js);
|
||||||
|
struct mallinfo i = mallinfo();
|
||||||
|
// Add fields if needed, similar to os.c
|
||||||
|
// Using macros from os.c if they were visible, but they aren't public.
|
||||||
|
// We'll just define helper locally or expand it.
|
||||||
|
JS_SetPropertyStr(js, ret, "arena", JS_NewInt32(js, i.arena));
|
||||||
|
JS_SetPropertyStr(js, ret, "ordblks", JS_NewInt32(js, i.ordblks));
|
||||||
|
JS_SetPropertyStr(js, ret, "uordblks", JS_NewInt32(js, i.uordblks));
|
||||||
|
JS_SetPropertyStr(js, ret, "fordblks", JS_NewInt32(js, i.fordblks));
|
||||||
|
)
|
||||||
|
|
||||||
|
static JSValue js_os_rusage(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||||
|
return JS_NewObject(js);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSC_SCALL(os_system,
|
||||||
|
// system() not available in browser
|
||||||
|
ret = JS_NewInt32(js, -1);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_exit,
|
||||||
|
// Terminate execution
|
||||||
|
emscripten_force_exit(0);
|
||||||
|
)
|
||||||
|
|
||||||
|
// dylib functions - assuming static build for now unless side modules are used
|
||||||
|
static JSValue js_os_dylib_open(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||||
|
return JS_ThrowInternalError(js, "dylib_open: not supported on Emscripten");
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_os_dylib_symbol(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||||
|
return JS_ThrowInternalError(js, "dylib_symbol: not supported on Emscripten");
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_os_dylib_has_symbol(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||||
|
return JS_NewBool(js, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSC_CCALL(os_print,
|
||||||
|
size_t len;
|
||||||
|
const char *str = JS_ToCStringLen(js, &len, argv[0]);
|
||||||
|
printf("%.*s", (int)len, str);
|
||||||
|
JS_FreeCString(js, str);
|
||||||
|
)
|
||||||
|
|
||||||
|
static JSValue js_os_load_internal(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||||
|
// dlsym with NULL usually works in Emscripten MAIN_MODULE builds,
|
||||||
|
// but for now we assume no dynamic linking.
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_os_internal_exists(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||||
|
return JS_NewBool(js, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void arc4random_buf(void *buf, size_t nbytes);
|
||||||
|
|
||||||
|
// Random number generation
|
||||||
|
int randombytes(void *buf, size_t n) {
|
||||||
|
// Emscripten implements arc4random_buf using Web Crypto API
|
||||||
|
arc4random_buf(buf, n);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSC_CCALL(os_random,
|
||||||
|
return JS_NewFloat64(js, cell_random_fit());
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_getenv,
|
||||||
|
const char *name = JS_ToCString(js, argv[0]);
|
||||||
|
if (!name) return JS_EXCEPTION;
|
||||||
|
const char *value = getenv(name);
|
||||||
|
JS_FreeCString(js, name);
|
||||||
|
if (value)
|
||||||
|
ret = JS_NewString(js, value);
|
||||||
|
else
|
||||||
|
ret = JS_NULL;
|
||||||
|
)
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_os_funcs[] = {
|
||||||
|
MIST_FUNC_DEF(os, platform, 0),
|
||||||
|
MIST_FUNC_DEF(os, arch, 0),
|
||||||
|
MIST_FUNC_DEF(os, totalmem, 0),
|
||||||
|
MIST_FUNC_DEF(os, freemem, 0),
|
||||||
|
MIST_FUNC_DEF(os, hostname, 0),
|
||||||
|
MIST_FUNC_DEF(os, version, 0),
|
||||||
|
MIST_FUNC_DEF(os, now, 0),
|
||||||
|
MIST_FUNC_DEF(os, rusage, 0),
|
||||||
|
MIST_FUNC_DEF(os, mallinfo, 0),
|
||||||
|
MIST_FUNC_DEF(os, system, 1),
|
||||||
|
MIST_FUNC_DEF(os, exit, 0),
|
||||||
|
MIST_FUNC_DEF(os, sleep, 1),
|
||||||
|
MIST_FUNC_DEF(os, dylib_open, 1),
|
||||||
|
MIST_FUNC_DEF(os, dylib_symbol, 2),
|
||||||
|
MIST_FUNC_DEF(os, dylib_has_symbol, 2),
|
||||||
|
MIST_FUNC_DEF(os, load_internal, 1),
|
||||||
|
MIST_FUNC_DEF(os, internal_exists, 1),
|
||||||
|
MIST_FUNC_DEF(os, print, 1),
|
||||||
|
MIST_FUNC_DEF(os, random, 0),
|
||||||
|
MIST_FUNC_DEF(os, getenv, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
JSValue js_os_use(JSContext *js) {
|
||||||
|
JSValue mod = JS_NewObject(js);
|
||||||
|
JS_SetPropertyFunctionList(js, mod, js_os_funcs, countof(js_os_funcs));
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
#define ENGINE "engine.cm"
|
#define ENGINE "engine.cm"
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
static qop_desc qop_core;
|
static qop_desc qop_core;
|
||||||
static qop_file *qop_hashmap = NULL;
|
static qop_file *qop_hashmap = NULL;
|
||||||
cell_rt *root_cell = NULL;
|
cell_rt *root_cell = NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user