Wednesday, April 13, 2022

[SOLVED] rpmbuild not including symlink shared object as a Provides

Issue

I am building an RPM which is essentially just packaging a set of vendor provided .so binaries so that they are available for our internal application, which is also installed via RPM.

One of the libraries comes with multiple versions - libexample_base.so and libexample_debug.so (among others). I am currently trying to package these so that they are all included in the RPM (so that developers can switch between them if needed), but picks libexample_base.so as the default version by creating a symlink during %install, which then gets packaged as a file in the RPM.

%install
[... Copy the files from the tarball to the buildroot ...]
pushd %{buildroot}%{_libdir}
ln -sf libexample_base.so libexample.so
popd

This works great... except for one problem. It's using automatic dependency generation, and while it's providing all of the shared objects for which is has actual files, it's not providing libexample.so, despite the symlink being in %files and installing properly. Unfortunately, the vendor libraries do not provide SONAME entries, and as they are binary blobs I can't readily add them, so RPM is depending on the actual file names. All of the downstream RPMs require libexample.so, and since this RPM is not listing it as a requires, they are refusing to install due to missing dependencies, even though the do actually work (ldconfig can find libexample.so without issue).

Any ideas on how to prompt rpmbuild to parse the symlink as a provides?


Solution

After some further research, I have determined that what I am trying to do is not possible, as well as why. The core problem comes down to rpmbuild's behavior, which was built to handle correctly generated shared objects with SONAME entries. It explicitly does not list symlinks to shared objects that end in .so as provides because with normal behavior, those point to a versioned shared object (.so.#.#), and your application is supposed to depend on those versioned objects - the symlink is meant to be included in the devel package just to give your linker a way to find the latest one.

I'm running into a second case that is used as a backup for when things aren't done correctly - for both RPM and GCC, when no SONAME is present, it uses the file name. When I run GCC, the filename is libexample.so (the symlink to the real one), and it has no SONAME, so it just configures itself to link against libexample.so; rpmbuild sees this and sets that as a requires for the application RPM. However, since rpmbuild is explicitly excluding that name from the library rpm since it looks like a devel link, there is no way to reconcile the two rpms.

The solution? For now, I'm using my workaround, just making a copy of the file - when there's a physical file with that name, it works. The correct way is to fix the shared objects, although I'm going to need to go to the upstream vendor to get that done.



Answered By - matthock
Answer Checked By - Gilberto Lyons (WPSolving Admin)