working link
This commit is contained in:
12
build.cm
12
build.cm
@@ -390,11 +390,13 @@ Build.compile_file = function(pkg, file, target, opts) {
|
||||
|
||||
// Layer 2: stat-based manifest probe (zero file reads on warm cache)
|
||||
var mf_obj = null
|
||||
var _linked = fd.is_link(setup.pkg_dir)
|
||||
var _tag = _linked ? ' [linked]' : ''
|
||||
if (!_opts.force) {
|
||||
mf_obj = bmfst_probe(setup.cmd_str, setup.src_path)
|
||||
if (mf_obj) {
|
||||
if (_opts.verbose) log.build('[verbose] manifest hit: ' + file)
|
||||
log.shop('manifest hit ' + file)
|
||||
if (_opts.verbose) log.build(`[verbose] manifest hit: ${pkg}/${file}${_tag}`)
|
||||
log.shop(`manifest hit ${pkg}/${file}${_tag}`)
|
||||
return mf_obj
|
||||
}
|
||||
}
|
||||
@@ -578,11 +580,13 @@ Build.build_module_dylib = function(pkg, file, target, opts) {
|
||||
|
||||
// Stat-based dylib manifest — zero file reads on warm cache
|
||||
var mf_dylib = null
|
||||
var _linked = fd.is_link(setup.pkg_dir)
|
||||
var _tag = _linked ? ' [linked]' : ''
|
||||
if (!_opts.force) {
|
||||
mf_dylib = bmfst_dl_probe(setup, link_info)
|
||||
if (mf_dylib) {
|
||||
if (_opts.verbose) log.build('[verbose] manifest hit: ' + file)
|
||||
log.shop('manifest hit ' + file)
|
||||
if (_opts.verbose) log.build(`[verbose] manifest hit: ${pkg}/${file}${_tag}`)
|
||||
log.shop(`manifest hit ${pkg}/${file}${_tag}`)
|
||||
return mf_dylib
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,6 +139,42 @@ function package_in_shop(package) {
|
||||
return package in lock
|
||||
}
|
||||
|
||||
// Derive canonical lock name from a directory's git origin remote.
|
||||
// Reads .git/config, extracts the origin url, strips https:// and .git suffix,
|
||||
// then checks if that name exists in the lock file.
|
||||
function git_origin_to_lock_name(dir) {
|
||||
var git_cfg = dir + '/.git/config'
|
||||
var raw = null
|
||||
var lines = null
|
||||
var in_origin = false
|
||||
var url = null
|
||||
var candidate = null
|
||||
if (!fd.is_file(git_cfg)) return null
|
||||
raw = text(fd.slurp(git_cfg))
|
||||
if (!raw) return null
|
||||
lines = array(raw, '\n')
|
||||
arrfor(lines, function(line) {
|
||||
var trimmed = trim(line)
|
||||
if (trimmed == '[remote "origin"]') {
|
||||
in_origin = true
|
||||
} else if (starts_with(trimmed, '[')) {
|
||||
in_origin = false
|
||||
} else if (in_origin && starts_with(trimmed, 'url = ')) {
|
||||
url = trim(text(trimmed, 6))
|
||||
}
|
||||
})
|
||||
if (!url) return null
|
||||
candidate = url
|
||||
if (starts_with(candidate, 'https://'))
|
||||
candidate = text(candidate, 8)
|
||||
else if (starts_with(candidate, 'http://'))
|
||||
candidate = text(candidate, 7)
|
||||
if (ends_with(candidate, '.git'))
|
||||
candidate = text(candidate, 0, length(candidate) - 4)
|
||||
if (package_in_shop(candidate)) return candidate
|
||||
return null
|
||||
}
|
||||
|
||||
function abs_path_to_package(package_dir)
|
||||
{
|
||||
if (!fd.is_file(package_dir + '/cell.toml')) {
|
||||
@@ -182,20 +218,21 @@ function abs_path_to_package(package_dir)
|
||||
if (package_in_shop(package_dir))
|
||||
return package_dir
|
||||
|
||||
// For local directories (e.g., linked targets), read the package name from cell.toml
|
||||
var _toml_path = package_dir + '/cell.toml'
|
||||
var content = null
|
||||
var cfg = null
|
||||
if (fd.is_file(_toml_path)) {
|
||||
content = text(fd.slurp(_toml_path))
|
||||
cfg = toml.decode(content)
|
||||
if (cfg.package)
|
||||
return cfg.package
|
||||
}
|
||||
// For local directories, try git remote origin to derive canonical name
|
||||
var _git_name = git_origin_to_lock_name(package_dir)
|
||||
if (_git_name) return _git_name
|
||||
|
||||
return package_dir
|
||||
}
|
||||
|
||||
function safe_canonicalize(pkg) {
|
||||
if (!pkg || !starts_with(pkg, '/')) return pkg
|
||||
var _canon = null
|
||||
var _try = function() { _canon = abs_path_to_package(pkg) } disruption {}
|
||||
_try()
|
||||
return (_canon && _canon != pkg) ? _canon : pkg
|
||||
}
|
||||
|
||||
// given a file, find the absolute path, package name, and import name
|
||||
Shop.file_info = function(file) {
|
||||
var info = {
|
||||
@@ -828,7 +865,7 @@ function resolve_path(path, ctx)
|
||||
if (fd.is_file(ctx_path)) {
|
||||
is_core = (ctx == 'core') || is_core_dir(ctx_dir)
|
||||
scope = is_core ? SCOPE_CORE : SCOPE_LOCAL
|
||||
return {path: ctx_path, scope: scope, pkg: is_core ? 'core' : ctx}
|
||||
return {path: ctx_path, scope: scope, pkg: is_core ? 'core' : safe_canonicalize(ctx)}
|
||||
}
|
||||
|
||||
if (is_internal_path(path))
|
||||
@@ -907,9 +944,10 @@ function read_dylib_manifest(pkg) {
|
||||
// Ensure all C modules for a package are built and loaded.
|
||||
// Returns the array of {file, symbol, dylib} results, cached per package.
|
||||
function ensure_package_dylibs(pkg) {
|
||||
if (package_dylibs[pkg] != null) return package_dylibs[pkg]
|
||||
if (pkg == 'core') {
|
||||
package_dylibs[pkg] = []
|
||||
var _pkg = safe_canonicalize(pkg)
|
||||
if (package_dylibs[_pkg] != null) return package_dylibs[_pkg]
|
||||
if (_pkg == 'core') {
|
||||
package_dylibs[_pkg] = []
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -922,23 +960,23 @@ function ensure_package_dylibs(pkg) {
|
||||
target = detect_host_target()
|
||||
if (!target) return null
|
||||
|
||||
c_files = pkg_tools.get_c_files(pkg, target, true)
|
||||
c_files = pkg_tools.get_c_files(_pkg, target, true)
|
||||
if (!c_files || length(c_files) == 0) {
|
||||
package_dylibs[pkg] = []
|
||||
package_dylibs[_pkg] = []
|
||||
return []
|
||||
}
|
||||
|
||||
log.shop('ensuring C modules for ' + pkg)
|
||||
results = build_mod.build_dynamic(pkg, target, 'release', {})
|
||||
log.shop('ensuring C modules for ' + _pkg)
|
||||
results = build_mod.build_dynamic(_pkg, target, 'release', {})
|
||||
} else {
|
||||
// No build module at runtime — read manifest from cell build
|
||||
results = read_dylib_manifest(pkg)
|
||||
results = read_dylib_manifest(_pkg)
|
||||
if (!results) return null
|
||||
log.shop('loaded manifest for ' + pkg + ' (' + text(length(results)) + ' modules)')
|
||||
log.shop('loaded manifest for ' + _pkg + ' (' + text(length(results)) + ' modules)')
|
||||
}
|
||||
|
||||
if (results == null) results = []
|
||||
package_dylibs[pkg] = results
|
||||
package_dylibs[_pkg] = results
|
||||
|
||||
// Preload all sibling dylibs with RTLD_LAZY|RTLD_GLOBAL
|
||||
arrfor(results, function(r) {
|
||||
@@ -982,7 +1020,7 @@ function try_dylib_symbol(sym, pkg, file_stem) {
|
||||
// Resolve a C symbol by searching:
|
||||
// At each scope: check build-cache dylib first, then internal (static)
|
||||
function resolve_c_symbol(path, _pkg_ctx) {
|
||||
var package_context = is_core_dir(_pkg_ctx) ? 'core' : _pkg_ctx
|
||||
var package_context = is_core_dir(_pkg_ctx) ? 'core' : safe_canonicalize(_pkg_ctx)
|
||||
var explicit = split_explicit_package_import(path)
|
||||
var sym = null
|
||||
var loader = null
|
||||
@@ -1298,7 +1336,7 @@ Shop.use = function use(path, _pkg_ctx) {
|
||||
log.error("use() expects a text module path, but received a non-text value")
|
||||
disrupt
|
||||
}
|
||||
var package_context = is_core_dir(_pkg_ctx) ? 'core' : _pkg_ctx
|
||||
var package_context = is_core_dir(_pkg_ctx) ? 'core' : safe_canonicalize(_pkg_ctx)
|
||||
// Check for embedded module (static builds)
|
||||
var embed_key = 'embedded:' + path
|
||||
var embedded = null
|
||||
|
||||
13
link.ce
13
link.ce
@@ -140,17 +140,18 @@ if (cmd == 'list') {
|
||||
return
|
||||
}
|
||||
|
||||
// Read package name from cell.toml
|
||||
// Derive canonical package name from the target directory
|
||||
_read_toml = function() {
|
||||
content = toml.decode(text(fd.slurp(toml_path)))
|
||||
if (content.package) {
|
||||
pkg_name = content.package
|
||||
var info = shop.file_info(target + '/cell.toml')
|
||||
if (info && info.package) {
|
||||
pkg_name = info.package
|
||||
} else {
|
||||
log.console("Error: cell.toml at " + target + " does not define 'package'")
|
||||
log.console("Error: could not determine package name for " + target)
|
||||
log.console("Ensure it is installed or has a git remote matching a lock entry")
|
||||
$stop()
|
||||
}
|
||||
} disruption {
|
||||
log.console("Error reading cell.toml")
|
||||
log.console("Error determining package name for " + target)
|
||||
$stop()
|
||||
}
|
||||
_read_toml()
|
||||
|
||||
Reference in New Issue
Block a user