From 17b9aaaf51249de6da3830b4cae7d7051b84ad70 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Sun, 11 Jan 2026 11:49:48 -0600 Subject: [PATCH] fix issue where linked packages would not load dylibs correctly --- internal/shop.cm | 60 +++++++++++++++++++++++++++--------------------- package.cm | 43 ++++++++++++++++++++++++++-------- 2 files changed, 68 insertions(+), 35 deletions(-) diff --git a/internal/shop.cm b/internal/shop.cm index 5f615412..1c0cd8f7 100644 --- a/internal/shop.cm +++ b/internal/shop.cm @@ -547,14 +547,14 @@ Shop.open_package_dylib = function(pkg) { var link_target = link.get_target(pkg) var resolved_pkg = link_target ? link_target : pkg - + var pkg_dir; if (resolved_pkg.startsWith('/')) { pkg_dir = resolved_pkg } else { pkg_dir = get_packages_dir() + '/' + safe_package_path(resolved_pkg) } - + var toml_path = pkg_dir + '/cell.toml' if (fd.is_file(toml_path)) { try { @@ -563,18 +563,27 @@ Shop.open_package_dylib = function(pkg) { if (cfg.dependencies) { for (var alias in cfg.dependencies) { var dep_pkg = cfg.dependencies[alias] - Shop.open_package_dylib(dep_pkg) + try { + Shop.open_package_dylib(dep_pkg) + } catch (dep_e) { + // Dependency dylib load failed, continue with others + } } } } catch (e) { - // Ignore errors reading cell.toml + // Error reading toml, continue } } var dl_path = get_lib_path(pkg) if (fd.is_file(dl_path)) { if (!open_dls[dl_path]) { - open_dls[dl_path] = os.dylib_open(dl_path) + try { + open_dls[dl_path] = os.dylib_open(dl_path) + } catch (e) { + dylib_visited[pkg] = false + throw e + } } } } @@ -582,20 +591,19 @@ Shop.open_package_dylib = function(pkg) { // Resolve a C symbol by searching: // 1. If package_context is null, only check core internal symbols // 2. Otherwise: own package (internal then dylib) -> other packages (internal then dylib) -> core (internal only) - // Core is never loaded as a dynamic library via dlopen - function resolve_c_symbol(path, package_context) - { - var explicit = split_explicit_package_import(path) - if (explicit) { - if (is_internal_path(explicit.path) && package_context && explicit.package != package_context) - explicit = null - } - if (explicit) { - var sym = make_c_symbol(explicit.package, explicit.path) - if (os.internal_exists(sym)) { - return { - symbol: function() { return os.load_internal(sym) }, - scope: SCOPE_PACKAGE, +// Core is never loaded as a dynamic library via dlopen +function resolve_c_symbol(path, package_context) { + var explicit = split_explicit_package_import(path) + if (explicit) { + if (is_internal_path(explicit.path) && package_context && explicit.package != package_context) + explicit = null + } + if (explicit) { + var sym = make_c_symbol(explicit.package, explicit.path) + if (os.internal_exists(sym)) { + return { + symbol: function() { return os.load_internal(sym) }, + scope: SCOPE_PACKAGE, package: explicit.package, path: sym } @@ -626,7 +634,7 @@ Shop.open_package_dylib = function(pkg) { } return null } - + // 1. Check own package first (internal, then dylib) var sym = make_c_symbol(package_context, path) if (os.internal_exists(sym)) { @@ -647,10 +655,10 @@ Shop.open_package_dylib = function(pkg) { path: sym } } - + if (is_internal_path(path)) return null - + // 2. Check aliased package imports (e.g. 'prosperon/sprite') var pkg_alias = get_import_package(path) if (pkg_alias) { @@ -658,7 +666,7 @@ Shop.open_package_dylib = function(pkg) { if (canon_pkg) { var mod_name = get_import_name(path) var sym = make_c_symbol(canon_pkg, mod_name) - + // Check internal first if (os.internal_exists(sym)) { return { @@ -668,7 +676,7 @@ Shop.open_package_dylib = function(pkg) { path: sym } } - + // Then check dylib Shop.open_package_dylib(canon_pkg) var dl_path = get_lib_path(canon_pkg) @@ -682,7 +690,7 @@ Shop.open_package_dylib = function(pkg) { } } } - + // 3. Check core internal symbols (core is never a dynamic library) var core_sym = `js_${path.replaceAll('/', '_')}_use` if (os.internal_exists(core_sym)) { @@ -692,7 +700,7 @@ Shop.open_package_dylib = function(pkg) { path: core_sym } } - + return null } diff --git a/package.cm b/package.cm index 16fa3fec..5ea76d3f 100644 --- a/package.cm +++ b/package.cm @@ -3,6 +3,7 @@ var package = {} var fd = use('fd') var toml = use('toml') var os = use('os') +var link = use('link') // Convert package name to a safe directory name // For absolute paths (local packages), replace / with _ @@ -22,6 +23,18 @@ function get_path(name) // If name is already an absolute path, use it directly if (name.startsWith('/')) return name + + // Check if this package is linked - if so, use the link target directly + // This avoids symlink-related issues with file reading + var link_target = link.get_target(name) + if (link_target) { + // If link target is a local path, use it directly + if (link_target.startsWith('/')) + return link_target + // Otherwise it's another package name, resolve that + return os.global_shop_path + '/packages/' + link_target.replaceAll('@', '_') + } + // Remote packages use nested directories, so don't transform slashes return os.global_shop_path + '/packages/' + name.replaceAll('@', '_') } @@ -36,7 +49,12 @@ package.load_config = function(name) if (!content || content.trim().length == 0) return {} - return toml.decode(content) + var result = toml.decode(content) + if (!result) { + return {} + } + + return result } package.save_config = function(name, config) @@ -127,17 +145,24 @@ package.split_alias = function(name, path) if (!path || path.length == 0) { return null } - + var parts = path.split('/') var first_part = parts[0] - - var config = package.load_config(name) - if (config.dependencies && config.dependencies[first_part]) { - var dep_locator = config.dependencies[first_part] - var remaining_path = parts.slice(1).join('/') - return { package: dep_locator, path: remaining_path } + + try { + var config = package.load_config(name) + if (!config) return null + + var deps = config.dependencies + if (deps && deps[first_part]) { + var dep_locator = deps[first_part] + var remaining_path = parts.slice(1).join('/') + return { package: dep_locator, path: remaining_path } + } + } catch (e) { + // Config doesn't exist or couldn't be loaded } - + return null }