conan-io / conan

Conan - The open-source C and C++ package manager
https://conan.io
MIT License
8.13k stars 968 forks source link

[question] Dynamic rpath issue for transitive shared libraries #16838

Open donlk opened 3 weeks ago

donlk commented 3 weeks ago

What is your question?

Hi! So I've been struggling with this issue for quite some time, living with it, but eventually it bothered me enough to post about it here.

Scenario: Given a library (in my case mesa) is built as shared through conan. It has a bunch of deps, such as X11 and libxcb, built also as shared, as recommended.

Now, whenever mesa is used by some other conanfile (for simplicity, let's say the other conanfile is it's own test_package), and libGL.so is linked, the linker fails, as it's unable to find it's transitive deps:

[100%] Linking CXX executable test_package
<toolchain>/../../../../x86_64-unknown-linux-gnu/bin/ld: warning: libglapi.so.0, needed by /home/host/conan/home/p/b/mesaa95f779289248/p/lib/libGL.so, not found (try using -rpath or -rpath-link)
<toolchain>/../../../../x86_64-unknown-linux-gnu/bin/ld: warning: libX11.so.6, needed by /home/host/conan/home/p/b/mesaa95f779289248/p/lib/libGL.so, not found (try using -rpath or -rpath-link)
<toolchain>/../../../../x86_64-unknown-linux-gnu/bin/ld: warning: libxcb-dri2.so.0, needed by /home/host/conan/home/p/b/mesaa95f779289248/p/lib/libGL.so, not found (try using -rpath or -rpath-link)
<toolchain>/../../../../x86_64-unknown-linux-gnu/bin/ld: warning: libxcb-glx.so.0, needed by /home/host/conan/home/p/b/mesaa95f779289248/p/lib/libGL.so, not found (try using -rpath or -rpath-link)
<toolchain>/../../../../x86_64-unknown-linux-gnu/bin/ld: warning: libxcb-present.so.0, needed by /home/host/conan/home/p/b/mesaa95f779289248/p/lib/libGL.so, not found (try using -rpath or -rpath-link)
<toolchain>/../../../../x86_64-unknown-linux-gnu/bin/ld: warning: libxcb-xfixes.so.0, needed by /home/host/conan/home/p/b/mesaa95f779289248/p/lib/libGL.so, not found (try using -rpath or -rpath-link)
<toolchain>/../../../../x86_64-unknown-linux-gnu/bin/ld: warning: libxcb-sync.so.1, needed by /home/host/conan/home/p/b/mesaa95f779289248/p/lib/libGL.so, not found (try using -rpath or -rpath-link)
...

All of these libs are build through conan and described in mesa's package_info:

self.cpp_info.components["GL"].set_property("cmake_find_mode", "both")
self.cpp_info.components["GL"].set_property("cmake_file_name", "GL")
self.cpp_info.components["GL"].set_property("cmake_target_name", "GL::GL")
self.cpp_info.components["GL"].set_property("pkg_config_name", "gl")
self.cpp_info.components["GL"].libs = ["GL"]
self.cpp_info.components["GL"].requires = ["glapi"]
if 'x11' in self._platforms:
    self.cpp_info.components["GL"].requires.extend([
        "libxext::xext",
        "libxcb::xcb-dri2",
        "libxcb::xcb-dri3",
        "libxcb::xcb-glx",
        "libxcb::xcb-present",
        "libxcb::xcb-xfixes",
        "libxcb::xcb-sync",
        "libxcb::xcb",
        "libx11::libx11",
])

Weird thing is, libglapi.so.0 is in the same place as libGL.so, so even that fails as $ORIGIN is not set in the rpath.

I've been digging into other issues describing something similar, but I haven't found a solution that's not hacky in some way. I've come up with supplying -Wl,rpath directly through the parent's conanfile:

tc = CMakeToolchain(self)

mesa_package_dir = self.dependencies["mesa"].package_folder
libx11_package_dir = self.dependencies["libx11"].package_folder
libxcb_package_dir = self.dependencies["libxcb"].package_folder
tc.extra_exelinkflags.extend([
    "-Wl,-rpath-link," + os.path.join(mesa_package_dir, "lib"),
    "-Wl,-rpath-link," + os.path.join(libxcb_package_dir, "lib"),
    "-Wl,-rpath-link," + os.path.join(libx11_package_dir, "lib")
])
tc.generate()

In theory conan should take care of this through the VirtualBuildEnv and VirtualRunEnv generators, while CMake can rely on CMakeDeps, yet rpath-link is not supplied. One thing I've noticed is the generated conanrunenv-release-x86_64.sh file has LD_LIBRARY_PATH set with the correct values for runtime use-cases:

export LD_LIBRARY_PATH="/home/host/conan/home/p/b/libx1ea4df21b30070/p/lib:/home/host/conan/home/p/b/libxc48cdf475f4efc/p/lib:$LD_LIBRARY_PATH"

However, conanbuildenv-release-x86_64.sh does not define these paths as rpath-links. Is this intentional?

This happens with other libraries built as shared.

Am I missing something? Thank you!

Have you read the CONTRIBUTING guide?

memsharded commented 3 weeks ago

Hi @donlk

Thanks for your question.

In theory the CMakeDeps has a provision for making this work, see https://github.com/conan-io/conan/blob/f357f8169c1e4ecf2bee5ca0b5fb723fc36d82b0/conan/tools/cmake/cmakedeps/templates/target_configuration.py#L112

The definition of INTERFACE_LINK_DIRECTORIES should result in CMake defining the -Wl,-rpath-link automatically. It is true that in some cases, the way visibility is defined, it could require doing target_link_libraries(mytarget PUBLIC dep_target::dep_target) as defining it as private might disable the -rpath-link thing. Maybe you can check and try this. If it is not this, I'd suggest trying to post a fully reproducible (and as minimal as possible) example, so we can check it too. Thanks!

donlk commented 3 weeks ago

Thanks for the response. Directly going into each lib's CMake scripts and redefining target_link_libraries kind of defeats the purpose of conan in this instance. I've read about it in an other issue of how difficult it is to solve, so not blaming anyone here, I was just a bit frustrated.

EDIT: Btw, these libs mostly used Autotools instead of CMake, don't now if Autotools even differentiates between public and private linking.

Thanks again, I'll leave it up to you to close the issue if no further input is needed from me.

SpaceIm commented 3 weeks ago

Duplicate of https://github.com/conan-io/conan/issues/13560 I think.