Summary
A package's runtime.library_dirs is also emitted as -L on the link line. The name
says runtime, and the field exists to make dlopen work, but a directory listed there
participates in symbol resolution at build time too — where it can shadow another
package's library and break the link.
Not asking for a behaviour change; the current semantics may well be intended. Asking for
it to be documented, because the failure is remote from its cause and the workaround is
non-obvious.
Where it came up
compat.vulkan-runtime (mcpp-index) is a symlink farm of host Vulkan ICD libraries, in
the shape compat.glx-runtime already uses for OpenGL: an mcpp binary runs under mcpp's
own glibc, so a bare-soname dlopen never searches the host's library path, and the
loader finds every ICD manifest and then fails to open a single driver.
The farm has to carry the ICDs' transitive dependencies, and some of those — libxcb, zlib
— are also packaged in the index. Harvesting the host's libxcb.so (the unversioned
development symlink) put it on -L ahead of compat.xcb, and the link failed:
ld: …/vulkan_runtime/lib/libxcb.so: undefined reference to `XauDisposeAuth'
ld: …/vulkan_runtime/lib/libxcb.so: undefined reference to `XauGetBestAuthByAddr'
ld: …/vulkan_runtime/lib/libxcb.so: undefined reference to `XdmcpWrap'
Nothing in that message points at runtime.library_dirs.
Reproduction
- A package declaring
runtime = { library_dirs = { "<dir>" } }, where <dir> contains
an unversioned libfoo.so for some foo the index also provides.
- A consumer that links
-lfoo through the index package.
mcpp build → the host copy wins and the link fails.
Confirmed on 0.0.109 by inspecting the generated build.ninja: the directory appears as
a plain -L… entry.
Workaround, which is arguably the right spelling anyway
Harvest only versioned sonames (lib*.so.*), never the bare .so. Versioned names
are invisible to the linker — it resolves -lfoo through libfoo.so/libfoo.a — and are
exactly what dlopen asks for. compat.glx-runtime never hit this because the GL family
it harvests is not otherwise linked from the index, so the collision never arose.
Suggested resolution
Either of these would have saved the debugging:
- Document that
runtime.library_dirs contributes to the link search path, with the
"versioned sonames only" guidance for symlink-farm packages; or
- Keep it out of the link line, if runtime-only was the intent.
Happy to send a docs patch if the first is the preferred direction.
Summary
A package's
runtime.library_dirsis also emitted as-Lon the link line. The namesays runtime, and the field exists to make
dlopenwork, but a directory listed thereparticipates in symbol resolution at build time too — where it can shadow another
package's library and break the link.
Not asking for a behaviour change; the current semantics may well be intended. Asking for
it to be documented, because the failure is remote from its cause and the workaround is
non-obvious.
Where it came up
compat.vulkan-runtime(mcpp-index) is a symlink farm of host Vulkan ICD libraries, inthe shape
compat.glx-runtimealready uses for OpenGL: an mcpp binary runs under mcpp'sown glibc, so a bare-soname
dlopennever searches the host's library path, and theloader finds every ICD manifest and then fails to open a single driver.
The farm has to carry the ICDs' transitive dependencies, and some of those — libxcb, zlib
— are also packaged in the index. Harvesting the host's
libxcb.so(the unversioneddevelopment symlink) put it on
-Lahead ofcompat.xcb, and the link failed:Nothing in that message points at
runtime.library_dirs.Reproduction
runtime = { library_dirs = { "<dir>" } }, where<dir>containsan unversioned
libfoo.sofor somefoothe index also provides.-lfoothrough the index package.mcpp build→ the host copy wins and the link fails.Confirmed on 0.0.109 by inspecting the generated
build.ninja: the directory appears asa plain
-L…entry.Workaround, which is arguably the right spelling anyway
Harvest only versioned sonames (
lib*.so.*), never the bare.so. Versioned namesare invisible to the linker — it resolves
-lfoothroughlibfoo.so/libfoo.a— and areexactly what
dlopenasks for.compat.glx-runtimenever hit this because the GL familyit harvests is not otherwise linked from the index, so the collision never arose.
Suggested resolution
Either of these would have saved the debugging:
runtime.library_dirscontributes to the link search path, with the"versioned sonames only" guidance for symlink-farm packages; or
Happy to send a docs patch if the first is the preferred direction.