diff --git a/meson.build b/meson.build index 3306a5c1..d81884e5 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project('cell', ['c', 'cpp'], version: '0.9.3', meson_version: '>=1.4', - default_options : [ 'cpp_std=c++11']) + default_options : [ 'cpp_std=c++11', 'default_library=static']) libtype = get_option('default_library') @@ -138,7 +138,8 @@ if host_machine.system() == 'windows' deps += cc.find_library('bcrypt') sdl3_opts.add_cmake_defines({'HAVE_ISINF': '1'}) # Hack for MSYS2 sdl3_opts.add_cmake_defines({'HAVE_ISNAN': '1'}) - link += '-static' + link += ['-static', '-static-libgcc', '-static-libstdc++'] + add_project_link_arguments('-static-libgcc', '-static-libstdc++', language: ['c', 'cpp']) endif if host_machine.system() == 'emscripten' @@ -232,18 +233,31 @@ if host_machine.system() != 'emscripten' endif src += 'qjs_enet.c' - deps += dependency('mimalloc') - - tracy_opts = ['fibers=true', 'no_exit=true', 'on_demand=true'] - add_project_arguments('-DTRACY_ENABLE', language:['c','cpp']) - - # Try to find system-installed tracy first - tracy_dep = dependency('tracy', static: true, required: false) - if not tracy_dep.found() - message('⚙ System tracy not found, building subproject...') - deps += dependency('tracy', static:true, default_options:tracy_opts) + mimalloc_enabled = get_option('mimalloc') + if mimalloc_enabled + message('⚙ Using mimalloc subproject for static linking...') + deps += dependency('mimalloc', static:true) + add_project_arguments('-DHAVE_MIMALLOC', language: ['c', 'cpp']) else - deps += tracy_dep + message('⚙ Mimalloc support disabled') + endif + + tracy_enabled = get_option('tracy') + if tracy_enabled + message('⚙ Tracy profiling enabled') + tracy_opts = ['fibers=true', 'no_exit=true', 'on_demand=true'] + add_project_arguments('-DTRACY_ENABLE', language:['c','cpp']) + + # Try to find system-installed tracy first + tracy_dep = dependency('tracy', static: true, required: false) + if not tracy_dep.found() + message('⚙ System tracy not found, building subproject...') + deps += dependency('tracy', static:true, default_options:tracy_opts) + else + deps += tracy_dep + endif + else + message('⚙ Tracy profiling disabled') endif src += 'qjs_dmon.c' @@ -258,13 +272,20 @@ else deps += soloud_dep endif -# Try to find system-installed qrencode first -qr_dep = dependency('qrencode', static: true, required: false) -if not qr_dep.found() - message('⚙ System qrencode not found, building subproject...') - deps += dependency('libqrencode', static:true) +# QR code support (optional) +qrencode_enabled = get_option('qrencode') +if qrencode_enabled + qr_dep = dependency('qrencode', static: true, required: false) + if not qr_dep.found() + message('⚙ System qrencode not found, building subproject...') + deps += dependency('libqrencode', static:true) + else + deps += qr_dep + endif + add_project_arguments('-DHAVE_QRENCODE', language: ['c', 'cpp']) + src += 'qjs_qr.c' else - deps += qr_dep + message('⚙ QR code support disabled') endif # Always build for Steam unless it's Emscripten @@ -308,7 +329,7 @@ src += [ 'anim.c', 'config.c', 'datastream.c','font.c','HandmadeMath.c','jsffi.c','model.c', 'render.c','simplex.c','spline.c', 'transform.c','cell.c', 'wildmatch.c', 'sprite.c', 'rtree.c', 'qjs_nota.c', 'qjs_soloud.c', 'qjs_sdl.c', 'qjs_sdl_input.c', 'qjs_sdl_video.c', 'qjs_sdl_surface.c', 'qjs_math.c', 'qjs_geometry.c', 'qjs_transform.c', 'qjs_sprite.c', 'qjs_io.c', 'qjs_fd.c', 'qjs_os.c', 'qjs_actor.c', - 'qjs_qr.c', 'qjs_wota.c', 'monocypher.c', 'qjs_blob.c', 'qjs_crypto.c', 'qjs_time.c', 'qjs_http.c', 'qjs_rtree.c', 'qjs_spline.c', 'qjs_js.c', 'qjs_debug.c', 'picohttpparser.c', 'qjs_miniz.c', 'timer.c', 'qjs_socket.c', 'qjs_kim.c', 'qjs_utf8.c', 'qjs_fit.c', 'qjs_text.c', 'qjs_layout.c' + 'qjs_wota.c', 'monocypher.c', 'qjs_blob.c', 'qjs_crypto.c', 'qjs_time.c', 'qjs_http.c', 'qjs_rtree.c', 'qjs_spline.c', 'qjs_js.c', 'qjs_debug.c', 'picohttpparser.c', 'qjs_miniz.c', 'timer.c', 'qjs_socket.c', 'qjs_kim.c', 'qjs_utf8.c', 'qjs_fit.c', 'qjs_text.c', 'qjs_layout.c' ] # quirc src src += [ diff --git a/meson.options b/meson.options index 04f60782..72b974c8 100644 --- a/meson.options +++ b/meson.options @@ -1,3 +1,6 @@ option('editor', type:'boolean', value:true) option('chipmunk', type:'boolean', value:true) option('storefront', type:'combo', choices:['none','steam', 'gog', 'egs'], value:'none') +option('qrencode', type:'boolean', value:false) +option('mimalloc', type:'boolean', value:false) +option('tracy', type:'boolean', value:false) diff --git a/scripts/engine.cm b/scripts/engine.cm index ad0c69ad..ccf1a49c 100644 --- a/scripts/engine.cm +++ b/scripts/engine.cm @@ -190,7 +190,8 @@ globalThis.use = function use(file, ...args) { loadingStack.push(path) // Determine the compiled file path in .cell directory - var compiledPath = ".cell/build/" + io.realdir(path) + "/" + path + '.o' + var cleanPath = (io.realdir(path) + "/" + path).replace(/[:\\]/g, '/').replace(/\/+/g, '/') + var compiledPath = ".cell/build/" + cleanPath + '.o' io.mkdir(compiledPath.dir()) diff --git a/source/cell.c b/source/cell.c index 8881cadb..39e8cb66 100644 --- a/source/cell.c +++ b/source/cell.c @@ -11,7 +11,9 @@ #include #include +#ifdef HAVE_MIMALLOC #include +#endif #ifdef __APPLE__ #include @@ -185,7 +187,9 @@ void actor_free(cell_rt *actor) SDL_UnlockMutex(actor->msg_mutex); SDL_DestroyMutex(actor->msg_mutex); +#ifdef HAVE_MIMALLOC mi_heap_destroy(actor->heap); +#endif free(actor); SDL_LockMutex(actors_mutex); @@ -219,16 +223,26 @@ void *js_mi_malloc(JSMallocState *s, size_t sz) { assert(sz != 0); if (unlikely(s->malloc_size + sz > s->malloc_limit)) return NULL; +#ifdef HAVE_MIMALLOC cell_rt *actor = (cell_rt*)s->opaque; ptr = mi_heap_malloc(actor->heap, sz); +#else + ptr = malloc(sz); +#endif if (!ptr) return NULL; s->malloc_count++; s->malloc_size += js_mi_malloc_usable_size(ptr) + MALLOC_OVERHEAD; #ifdef TRACY_ENABLE - if (tracy_profiling_enabled) + if (tracy_profiling_enabled) { +#ifdef HAVE_MIMALLOC + cell_rt *actor = (cell_rt*)s->opaque; TracyCAllocN(ptr, js_mi_malloc_usable_size(ptr) + MALLOC_OVERHEAD, actor->name); +#else + TracyCAllocN(ptr, js_mi_malloc_usable_size(ptr) + MALLOC_OVERHEAD, "actor"); +#endif + } #endif return ptr; @@ -242,17 +256,24 @@ void js_mi_free(JSMallocState *s, void *p) { #ifdef TRACY_ENABLE if (tracy_profiling_enabled) { +#ifdef HAVE_MIMALLOC cell_rt *actor = s->opaque; TracyCFreeN(p, actor->name); +#else + TracyCFreeN(p, "actor"); +#endif } #endif +#ifdef HAVE_MIMALLOC mi_free(p); +#else + free(p); +#endif } void *js_mi_realloc(JSMallocState *s, void *p, size_t sz) { size_t old_size; - cell_rt *actor = (cell_rt*)s->opaque; if (!p) return sz ? js_mi_malloc(s, sz) : NULL; @@ -261,39 +282,68 @@ void *js_mi_realloc(JSMallocState *s, void *p, size_t sz) { s->malloc_count--; s->malloc_size -= old_size + MALLOC_OVERHEAD; #ifdef TRACY_ENABLE - if (tracy_profiling_enabled) + if (tracy_profiling_enabled) { +#ifdef HAVE_MIMALLOC + cell_rt *actor = (cell_rt*)s->opaque; TracyCFreeN(p, actor->name); +#else + TracyCFreeN(p, "actor"); #endif + } +#endif +#ifdef HAVE_MIMALLOC mi_free(p); +#else + free(p); +#endif return NULL; } if (s->malloc_size + sz - old_size > s->malloc_limit) return NULL; #ifdef TRACY_ENABLE - if (tracy_profiling_enabled) + if (tracy_profiling_enabled) { +#ifdef HAVE_MIMALLOC + cell_rt *actor = (cell_rt*)s->opaque; TracyCFreeN(p, actor->name); +#else + TracyCFreeN(p, "actor"); +#endif + } #endif +#ifdef HAVE_MIMALLOC + cell_rt *actor = (cell_rt*)s->opaque; p = mi_heap_realloc(actor->heap, p, sz); +#else + p = realloc(p, sz); +#endif if (!p) return NULL; s->malloc_size += js_mi_malloc_usable_size(p) - old_size; #ifdef TRACY_ENABLE - if (tracy_profiling_enabled) + if (tracy_profiling_enabled) { +#ifdef HAVE_MIMALLOC + cell_rt *actor = (cell_rt*)s->opaque; TracyCAllocN(p, js_mi_malloc_usable_size(p) + MALLOC_OVERHEAD, actor->name); +#else + TracyCAllocN(p, js_mi_malloc_usable_size(p) + MALLOC_OVERHEAD, "actor"); +#endif + } #endif return p; } +#ifdef HAVE_MIMALLOC static const JSMallocFunctions mimalloc_funcs = { js_mi_malloc, js_mi_free, js_mi_realloc, js_mi_malloc_usable_size }; +#endif static void free_zip(void) { @@ -393,7 +443,9 @@ void actor_unneeded(cell_rt *actor, JSValue fn, double seconds) cell_rt *create_actor(void *wota) { cell_rt *actor = calloc(sizeof(*actor), 1); +#ifdef HAVE_MIMALLOC actor->heap = mi_heap_new(); +#endif actor->init_wota = wota; actor->idx_buffer = JS_NULL; actor->message_handle = JS_NULL; @@ -739,7 +791,11 @@ void script_startup(cell_rt *prt) { JSRuntime *rt; +#ifdef HAVE_MIMALLOC rt = JS_NewRuntime2(&mimalloc_funcs, prt); +#else + rt = JS_NewRuntime(); +#endif JSContext *js = JS_NewContextRaw(rt); JS_SetInterruptHandler(rt, actor_interrupt_cb, prt); diff --git a/source/cell.h b/source/cell.h index 1d3b1350..029bc08a 100644 --- a/source/cell.h +++ b/source/cell.h @@ -11,7 +11,9 @@ extern "C" { #endif +#ifdef HAVE_MIMALLOC typedef struct mi_heap_s mi_heap_t; +#endif /* Letter type for unified message queue */ typedef enum { @@ -53,7 +55,9 @@ typedef struct { typedef struct cell_rt { JSContext *context; - mi_heap_t *heap; +#ifdef HAVE_MIMALLOC +mi_heap_t *heap; +#endif JSValue idx_buffer; JSValue on_exception; JSValue message_handle; diff --git a/source/jsffi.c b/source/jsffi.c index e9c8753a..67517b13 100644 --- a/source/jsffi.c +++ b/source/jsffi.c @@ -36,7 +36,9 @@ #include "qjs_nota.h" #include "qjs_wota.h" #include "qjs_soloud.h" +#ifdef HAVE_QRENCODE #include "qjs_qr.h" +#endif #include "qjs_sdl.h" #include "qjs_sdl_video.h" #include "qjs_math.h" @@ -1635,7 +1637,9 @@ void ffi_load(JSContext *js) arrput(rt->module_registry, ((ModuleEntry){"fd", js_fd_use})); arrput(rt->module_registry, MISTLINE(socket)); arrput(rt->module_registry, ((ModuleEntry){"os", js_os_use})); +#ifdef HAVE_QRENCODE arrput(rt->module_registry, MISTLINE(qr)); +#endif arrput(rt->module_registry, MISTLINE(http)); arrput(rt->module_registry, MISTLINE(crypto)); arrput(rt->module_registry, MISTLINE(miniz));