[ longish mail, bear with me ] Greetings, Marko,
On Thu, Feb 18, 2016 at 10:43:27AM -0700, Marko Dimjašević wrote:
# Please CC me in replies as I'm not on d-devel Hi all, I would need help with fixing a SONAME issue with my ITP package. It's a tool for development, which systematically explores as many as possible execution paths in a given program, potentially triggering crashes unknown before.
[...]
The issue is reported by Lintian: E: klee: sharedobject-in-library-directory-missing-soname usr/lib/libkleeRuntest.so N: N: A shared object was identified in a library directory (a directory in N: the standard linker path) which doesn't have a SONAME. This is usually N: an error. N: N: SONAMEs are set with something like gcc -Wl,-soname,libfoo.so.0, where 0 N: is the major version of the library. If your package uses libtool, then N: libtool invoked with the right options should be doing this. N: N: To view the SONAME of a shared library, run readelf -d on the shared N: library and look for the tag of type SONAME. N: N: Severity: important, Certainty: possible N: N: Check: shared-libs, Type: binary, udeb N: The packaged tool doesn't use Libtool. I understand what the error message is saying, but even with the help I got on d-mentors I wasn't able to resolve the issue. Therefore, I'd appreciate if someone could take a look and help with resolving it.
I packaged a library (libwildmagic) that involved re-writing partially the makefile shipped by upstream. In the process I tried to explain what involves packaging a UNIX/LINUX-based shared object file to the upstream developer who was only knowledgeable of Windows-based development. I put that text that I modified to suit your case below. ~~~~~ soname stuff explained ~~~~~ Shared libraries are one of the most interesting/complex fields in GNU/Linux systems. I'll try to be clear. However, if you want a document that is pretty neat, then head for this page: http://www.dwheeler.com/program-library/Program-Library-HOWTO/ by David Wheeler, who is a respected hacker. But, I'm willing to recap some things here, akin to an "exec summary": Shared libraries in GNU/Linux are versioned, contrary to what used to be with Windows-based dlls. We work on a library that is named kleeRuntest and the file on disk is thus libkleeRuntest. SONAME ====== The library file proper should store a specific bit of information that is called a SONAME (shared object name). That SONAME should be in the form lib<name>.so.<major-version-number>. In our example, that would be libkleeRuntest.so.1 (as suggested by then file klee_1.1.0-1.dsc). REAL-NAME ========= Note however, that the SONAME is not the "real name" of the library, that is, the name of the actual file containing the binary code offered by the library. The real name of the library typically is the soname *plus* a minor version number, that is actually called the release number. That REAL-NAME is the name that should be used when actually *creating* the library file upon building it (which is not the case presently with your build setup, see below). Thus, the REAL-NAME would be lib<name>.so.<major-version-number>.<minor-version.number> libkleeRuntest.so.1.1 (again, klee_1.1.0-1.dsc). OK, with that out of the way, let's go on with use/dev operations involving the library: LINKER-NAME =========== When building a software that makes use of a library, the linker should be told the library name to use. That library name should be in the form of the SONAME *without the version number*. That is, the linker should only know the name of the library to use for the linkage. For your library, that would be: libkleeRuntest.so But, then, how to tell from the LINKER-NAME, which actual file should be used, as we've seen above that the actual file is named with the REAL-NAME? Well, the bridge between LINKER-NAME and REAL-NAME is a simple symbolic link.For your lib, the real binary library file what we should ship is:
/usr/lib/libkleeRuntest.so.1.1 Then, the packager is reponsible for creating the LINKER-NAME symbolic link: /usr/lib/libkleeRuntest.so ---> /usr/lib/libkleeRuntest.so.1.1 so that, when the linkder searches for /usr/lib/libkleeRuntest it ends up actually using /usr/lib/libkleeRuntest.so.1.1. The linker name is a development/build-time name. This is not the name that is actually used when dynamically linking the library upon execution of the program code. The dynamic loading process needs yet another name, that would be the SONAME. But, as above, the SONAME is *not* the name of the library as we ship it, so again we should provide a symbolic link: /usr/lib/libkleeRuntest.so.1 ---> /usr/lib/libkleeRuntest.so.1.1 The SONAME is the name that the dynamic loader gets from the program that is being executed and that requires to load library stuff. For example, my massXpert program has these library NEEDS: objdump -x /usr/bin/massxpert | grep NEEDED NEEDED libQtSvg.so.4 NEEDED libQtGui.so.4 NEEDED libQtXml.so.4 NEEDED libQtCore.so.4 NEEDED libstdc++.so.6 NEEDED libm.so.6 NEEDED libgcc_s.so.1 NEEDED libc.so.6 Now, as you can see, the listed names are all SONAMES : lib<name>.so.<version>. For example, if I now want to see the files relating to libQtCore.so.4: ls /usr/lib/x86_64-linux-gnu/libQtCore.so* -l 18 Jan 12 05:15 /usr/lib/x86_64-linux-gnu/libQtCore.so -> libQtCore.so.4.8.6 18 Jan 12 05:15 /usr/lib/x86_64-linux-gnu/libQtCore.so.4 -> libQtCore.so.4.8.6 18 Jan 12 05:15 /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8 -> libQtCore.so.4.8.6 3033168 Jan 12 05:17 /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.6 You can see that the real library name is indeed libQtCore.so.4.8.6, of size 3033168, and the other ones are only symbolic links. OK, NOW THAT WE HAVE THESE FUNDAMENTALS HOW WOULD WE BE DOING WITH libkleeRuntest library ? The real name ============= Generate the library right from the build with the proper name: libkleeRuntest.so.1.1 How would we do that ? We need to tell the linker how to create the library file: compilation flags to build your libkleeRuntest shared object lib: -shared -fPIC -Wl,-soname,libkleeRuntest.so.1.1 -o libkleeRuntest.so.1.1 These flags need to go in the makefile that drives the build of the library. This will build the properly-named lib file: libkleeRuntest.so.1.1. You can check that by running this command: readelf -d libkleeRuntest.so.1.1 will output something like: Dynamic section at offset 0xb8c0 contains 26 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000000000000e (SONAME) Library soname: [libkleeRuntest.so.1] 0x000000000000000c (INIT) 0x4e68 0x000000000000000d (FINI) 0x965c As you can see, the SONAME is correctly mentioned now. This is all we need to make real-world UNIX-based libs. Now, we still need the symbolic links, and this is your debian packager duty. How is this implemented in Debian and Debian-based systems ? When packaging libraries, we always start from a source package that somehow only ships the original source tarball plus methods to build the binary packages. A random user will only want binary packages because she would not even know what to do with a source package. The software will be shipped as source in the debian source package named libkleeruntest. This source package will contain an attached archive file containing a debian/ directory plus all of its contents. In the debian/* files, we document how to process the source package to actually build binary packages. For each source package that contains a library (or set of libraries, as is your case) we need to produce two different binary packages: libkleeruntest1, which is the binary package that a user will have to install if she ever needs to install a package that makes use of that library. This package only contains the REAL-NAME file and the SONAME-to-REAL-NAME symbolic link. libkleeruntest-dev, which is the binary package that ships all the files needed for the use of the library from a development perspective. That is the package where the /usr/include/*.h[pp] files are shipped. We also ship the second LINKER-NAME-to-REAL-NAME symbolic link. In most cases, the -dev package is not versioned: it is typically the last version of the library which in turn depends on the other binary package of the same version, that of course ships the real library file. Hope this helps. I tried to ./configure the package, but I am missing a library on this system and I cannot install it. If you cannot succeed with the explanations above, send the makefile's (there are some, I saw) and I'll try to see if I can help. Ciao Filippo -- Filippo Rusconi, PhD - public crypto key 7694CF42@ pgp.mit.edu
pgpjehWCHZSLo.pgp
Description: PGP signature