Subject: bug#73979: validate-runpath phases fails when binaries linked to package's own libraries

From: Ludovic Courtès <[email-masked]>
Date: Sun, 10 Nov 2024 12:47:19 +0100

Hi,

Maxim Cournoyer <[email-masked]> skribis:

> There's a common pattern in packages where the validate-runpath phases
> fail, which is when a binary is linked to libraries provided by the same
> package.  In this case, our ld-wrapper script appears to not bake the
> required runpath, which then fails the validate-runpath phase.
>
> When this happens, the common workaround is adding link directives such
> as (string-append "-Wl,-rpath=" #$output "/lib/subdir") to LDFLAGS (see
> for example the 'dmraid' package definition).

I believe this is the exception, not the rule, and I see that as a bug
in the build system of those packages.  (As a counterexample, any
package built with Automake/Libtool is fine.)

> g++ mainaccc.o ../../linux/linuxspec.o ac3dload.o ac3dgroup.o -L/tmp/guix-build-torcs-1.3.7.drv-0/torcs-1.3.7/export/lib  -lopenal -lalut -lvorbisfile -L/usr/lib  -ltgf -lplibssg -lplibsg -lplibul -ltxml -lplibjs -lplibssgaux -lplibssg -lplibsm -lplibsl -lplibsg -lplibul -lglut -lGLU -lGL -lpng -lz -ldl -lXrandr -lXrender -lXxf86vm -lXmu -lXi -lXt -lSM -lICE -lXext -lX11 -lm  -o accc-bin

Here it’s missing “-LOUTPUT/lib” or similar, which is why ‘ld-wrapper’
does not add ‘-Wl,-rpath’.  (Libtool, and I believe some other build
systems as well, relink binaries upon installation.)

Note that probably “-L/usr/lib” is meant as “-LOUTPUT/lib”.

> So we see that ld-wrapper saw the accc-bin binary being linked against
> the package's own
> /tmp/guix-build-torcs-1.3.7.drv-0/torcs-1.3.7/export/lib/libtgf.so, but
> this is later dismissed for "not being in the store", by this code in
> gnu/packages/ld-wrapper.in:

Well, yeah.

> One idea could be to allow creating rpaths to %BUILD-DIRECTORY prefixed
> libraries, and have these entries refined in a phase that would run
> after the package is installed, before the validate-runpath phase runs.
> It could be called e.g. 'sanitize-runpath' and proceed along those
> lines:
>
> Scan for RUNPATH entries being prefixed by %BUILD-DIRECTORY; attempt to
> have them rewritten to libraries (.so) found under the package's own
> libdir library prefix (at any depth), including a potential "lib"
> output.  In case it couldn't, it would error.
>
> Does that sound feasible?

It might be feasible, but I think it’s the wrong approach.  The problem
here is in the build system itself; Guix is “not at fault”, so to speak.

Nevertheless, from a practical viewpoint, whether or not Guix is at
fault is largely irrelevant.  So the question becomes: how widespread is
this issue?  If it’s widespread, can it be solved at a (guix
build-system …) level?  (For instance, I think ‘cmake-build-system’ and
‘meson-build-system’ do the right things in that regard.)

If it’s a per-package issue, which seems to be the case given what you
describe, then I would fix it locally in this package, for instance by
passing ‘-Wl,-rpath=$ORIGIN/../lib’ or whatever is convenient.

HTH!

Ludo’.