Skip to content

pkginfo.install_dir() returns nil for a dependency that exists only in the shared registry cache #514

Description

@wellwei

Problem

pkginfo.install_dir(ns:name, ver) returns nil for a dependency that is installed on disk — in the shared registry cache ($MCPP_HOME/registry/data/xpkgs/<ns>-x-<name>/<ver>) — but is not present in the installing package's member-local xpkgs.

The fallback scan _resolve_dep_via_scan only searches:

  1. _RUNTIME.xpkg_dir
  2. path.directory(path.directory(_RUNTIME.install_dir)) (member-local xpkgs)
  3. _RUNTIME.project_data_dir/xpkgs

It never searches the shared cache. So a dependency that was installed there (e.g. built by a sibling workspace member and reused by this member) is invisible to install hooks.

Minimal repro (mcpp 2026.8.8.2, macOS arm64)

Same workspace as above, but install() records what install_dir() says about a package seeded into the shared cache:

-- pkgs/r/repro-hook.lua — mcpp.deps declares zlib (NOT xpm.deps), mirroring the
-- original connector descriptor.
mcpp = {
    sources = { "repro_anchor.c" },
    targets = { ["repro_hook"] = { kind = "lib" } },
    deps = { ["compat.zlib"] = "1.3.2" },
}
function install()
    local z = pkginfo.install_dir("compat:zlib", "1.3.2")
    -- append "install_dir(compat:zlib@1.3.2) = <z>" to a result file
    return false
end

Steps:

  1. Seed the shared cache: cp -R <an existing compat-x-zlib install> $MCPP_HOME/registry/data/xpkgs/compat-x-zlib/1.3.2
  2. mcpp test -p tests/examples/repro-hook (fresh member dir; zlib not member-local)

Result file:

install_dir(compat:zlib@1.3.2)  = nil
shared cache has zlib         = true      -- zlib IS on disk in the shared cache

Control (no seed — zlib installs member-local):

install_dir(compat:zlib@1.3.2)  = .../tests/examples/repro-hook/.mcpp/.xlings/data/xpkgs/compat-x-zlib/1.3.2
shared cache has zlib         = false

Real-world impact

mcpplibs/mcpp-index#185: compat.mysql-connector-cpp's install hook called pkginfo.install_dir("compat:openssl","3.5.1"); openssl was built into the shared cache by the sibling libmysqlclient member and reused, so the hook got nil and bailed with the empty E_INTERNAL (see #513). The descriptor had to add its own fallback that scans $MCPP_HOME/registry/data/xpkgs.

Related: #484 / #485 (recording the resolved dependency totally would also fix this path — when a resolver record with install_dir exists, install_dir() works; it is the scan fallback / missing record that misses the shared cache).

Expected

install_dir() should locate a dependency that is present in the shared registry cache — either by extending _resolve_dep_via_scan to include $MCPP_HOME/registry/data/xpkgs, or by ensuring the resolver records install_dir for every resolved dependency (including ones reused from the shared cache).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions