diff --git a/internal/engine.cm b/internal/engine.cm index 7aaa9a75..22123d58 100644 --- a/internal/engine.cm +++ b/internal/engine.cm @@ -1165,7 +1165,7 @@ var prog_path = prog + ".ce" var pkg_dir = null var core_dir = null if (!fd.is_file(prog_path)) { - pkg_dir = package.find_package_dir(prog_path) + pkg_dir = package.find_package_dir(".") if (pkg_dir) prog_path = pkg_dir + '/' + prog + '.ce' } diff --git a/internal/os.c b/internal/os.c index 7139e52b..5fe6442e 100644 --- a/internal/os.c +++ b/internal/os.c @@ -358,6 +358,41 @@ static JSValue js_os_dylib_open(JSContext *js, JSValue self, int argc, JSValue * return dylib_obj; } +static JSValue js_os_dylib_preload(JSContext *js, JSValue self, int argc, JSValue *argv) +{ + if (argc < 1) + return JS_NULL; + + const char *path = JS_ToCString(js, argv[0]); + if (!path) + return JS_NULL; + + void *handle; +#ifdef _WIN32 + handle = LoadLibraryA(path); +#else + handle = dlopen(path, RTLD_LAZY | RTLD_GLOBAL); +#endif + + JS_FreeCString(js, path); + + if (!handle) + return JS_NULL; + + JSValue dylib_obj = JS_NewObjectClass(js, js_dylib_class_id); + if (JS_IsException(dylib_obj)) { +#ifdef _WIN32 + FreeLibrary((HMODULE)handle); +#else + dlclose(handle); +#endif + return JS_NULL; + } + + JS_SetOpaque(dylib_obj, handle); + return dylib_obj; +} + static JSValue js_os_dylib_symbol(JSContext *js, JSValue self, int argc, JSValue *argv) { if (argc < 2) { @@ -653,6 +688,7 @@ static const JSCFunctionListEntry js_os_funcs[] = { MIST_FUNC_DEF(os, exit, 0), MIST_FUNC_DEF(os, sleep, 1), MIST_FUNC_DEF(os, dylib_open, 1), + MIST_FUNC_DEF(os, dylib_preload, 1), MIST_FUNC_DEF(os, dylib_close, 1), MIST_FUNC_DEF(os, dylib_symbol, 2), MIST_FUNC_DEF(os, dylib_has_symbol, 2), diff --git a/internal/shop.cm b/internal/shop.cm index 66aa02f1..b066b81c 100644 --- a/internal/shop.cm +++ b/internal/shop.cm @@ -717,9 +717,25 @@ function get_mach_path(pkg, stem) { } // Open a per-module dylib and return the dlopen handle +// Pre-loads sibling dylibs with RTLD_LAZY|RTLD_GLOBAL so cross-dylib symbols resolve function open_module_dylib(dylib_path) { if (open_dls[dylib_path]) return open_dls[dylib_path] if (!fd.is_file(dylib_path)) return null + var dir = fd.dirname(dylib_path) + var entries = fd.readdir(dir) + var i = 0 + var sibling = null + var handle = null + while (i < length(entries)) { + if (ends_with(entries[i], dylib_ext) && entries[i] != fd.basename(dylib_path)) { + sibling = dir + '/' + entries[i] + if (!open_dls[sibling]) { + handle = os.dylib_preload(sibling) + if (handle) open_dls[sibling] = handle + } + } + i = i + 1 + } open_dls[dylib_path] = os.dylib_open(dylib_path) return open_dls[dylib_path] }