bitbake do_rootfs install fails with shared library symlink in bbappend - symlink

I am trying to add a shared library package to a Yocto Krogoth image from a custom recipe that is dependent on libudev.so.0 but the openembedded-core layer's eudev recipe only provides libudev.so.1.6.3 and a libudev.so.1 symlink:
libudev.so.1 -> libudev.so.1.6.3
I have added a eudev_%.bbappend recipes_core recipe that creates the symlink
do_install_append() {
ln -srf ${D}${base_libdir}/libudev.so.1 ${D}${base_libdir}/libudev.so.0
}
and I can confirm the libudev.so.0 file is added to the libudev package in
tmp/work/HOST/eudev/3.1.5-r0/image/lib/libudev.so.0
tmp/work/HOST/eudev/3.1.5-r0/package/lib/libudev.so.0
tmp/work/HOST/eudev/3.1.5-r0/packages-split/lib/libudev.so.0
tmp/work/HOST/eudev/3.1.5-r0/sysroot-destdir/lib/libudev.so.0
and installed to the image's tmp/sysroots/MACHINE/lib/libudev.so.0 directory when building the image and is present in the resultant tmp/deploy/images/MACHINE/IMAGENAME.tar.bz2 rootfs archive. The issue is that with the above in place I cannot add my shared library package to the image as it results in the following error:
do_rootfs: ...
Computing transaction...error: Can't install MYRECIPE#HOST: no package provides libudev.so.0
The custom recipe does have RDEPENDS_${PN} = libudev set.
Why is the do_rootfs error generated as the installed libudev package clearly does provide the libudev.so.0 library? Bitbaking the custom recipe independently has no issue, but that obviously does not attempt to install the resultant package into an image.

Why is the do_rootfs error generated as the installed libudev package
clearly does provide the libudev.so.0 library?
I'm pretty sure the the relevant code isn't looking at file names but actual symbols needed by your library -- there's packaging magic that looks at all the libraries and executables and figures out their runtime dependencies based on the symbols they need (this is how the correct dependency libraries end up on the rootfs). I believe the error message is trying to say that no available library exports the symbols that your library needs.
You can check the soname your udev exports with
readelf -a libudev.so.1 | grep SONAME
0x000000000000000e (SONAME) Library soname: [libudev.so.1]
I've not confirmed that this is what the rootfs code checks for but it's quite likely.
Are you expecting a library linked with libudev.so.0 to just work with libudev.so.1 without even a recompile? I'm not familiar with udev but in general libraries are unlikely to work like that.
The custom recipe does have RDEPENDS_${PN} = libudev set.
This is not normally needed -- if your software dynamically links to a library, the runtime dependency is found automatically.

Related

caffe can't find libboost_system.so.166.0

I'm installing caffe on an Ubuntu 17.04 system using boost 1.66. I am able to execute make all and make test without problems:
me#icvr1:~/PackageDownloads/caffe$ make all
make: Nothing to be done for 'all'.
me#icvr1:~/PackageDownloads/caffe$ make test
make: Nothing to be done for 'test'.
However, when I try make runtest, I get the following error:
me#icvr1:~/PackageDownloads/caffe$ make runtest
.build_release/tools/caffe
.build_release/tools/caffe: error while loading shared libraries: libboost_system.so.1.66.0: cannot open shared object file: No such file or directory
Makefile:532: recipe for target 'runtest' failed
make: *** [runtest] Error 127
Now, I know that libboost_system.so.1.66.0 exists in /usr/local/lib, which (I believe) is a fairly standard location:
me#icvr1:~/PackageDownloads/caffe$ ls /usr/local/lib/libboost_system*
/usr/local/lib/libboost_system.a /usr/local/lib/libboost_system.so /usr/local/lib/libboost_system.so.1.66.0
and, in caffe's Makefile.config, /usr/local/lib is on the library path:
LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu/hdf5/serial
So, what am I missing here? How can I ensure caffe will know where to find libboost_system.so.1.66.0 ?
Your /usr/local/lib/libboost_system.so.1.66.0 is evidently one you built
yourself and want the loader to find at runtime without special measures.
But having built it, you didn't update the ldconfig cache
(because you didn't know you had to); so the runtime loader is not yet aware that this
library exists and can't find it.
When the loader is looking for the shared libraries needed to assemble a new process,
it does not search all of the linker's default search directories. That would be slow.
By default it searches a cached database /etc/ld.so.cache, of libraries that were
found by ldconfig, last time it was run.
By default, ldconfig caches libraries that it finds in /lib, /usr/lib and in the directrories
listed in the file /etc/ld.so.conf, and/or any similar *.conf files that are recursively include-ed in /etc/ld.so.conf.
For example:
$ cat /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
$ cat /etc/ld.so.conf.d/*.conf
/usr/lib/x86_64-linux-gnu/libfakeroot
# libc default configuration
/usr/local/lib
# Multiarch support
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
/usr/lib/nvidia-384
/usr/lib32/nvidia-384
/usr/lib/nvidia-384
/usr/lib32/nvidia-384
# Legacy biarch compatibility support
/lib32
/usr/lib32
You see that /usr/local/lib is listed there. So, to make the loader aware
of your new /usr/local/lib/libboost_system.so.1.66.0, just run:
ldconfig
as root. You need to do likewise anytime you install a new locally built
shared library in /usr/local/lib.
If you want the loader to find a shared library /a/b/libfoo.so that isn't in the ldconfig
cache, you can get it to do so by the special measure of appending /a/b/libfoo.so to the value of the
environment variable LD_LIBRARY_PATH (which by default is empty) in the environment in which you launch
the process that needs to load that library. The loader will search the LD_LIBRARY_PATH
directories, if any, before the ldconfig cache. However, not adding a shared library
to the ldconfig cache should be an informed choice and setting LD_LIBRARY_PATH
is, of course, not well motivated merely by ignorance of the ldconfig apparatus or of the linker's -rpath option

How to build a static tar command

I downloaded tar 1.28 and am attempting to compile a static binary to use on system recovery media on Fedora Linux (x86_64). It doesn't have to include common libraries, such as libc or pthreads, but I'd like to eliminate dependencies on selinux, acl, attr, pcre and lzma, etc.
The README indicates I can use
./configure CC=gcc LDFLAGS=-static
but this creates a fully static binary (including libc), but is missing support for anything normally found in the shared libraries (SELinux, ACLs, etc). Reading the config.log shows failed attempts to find a static library for acl
So, I installed libselinux-devel-static RPM, and this time got the selinux support in there, but I can't find static libraries for anything else. Search results say that libacl.a is in libacl-devel, but not mine.
A fully static binary is ok, but really just want to get the odd-balls in there so I don't have to put the shared libraries on the media.
I was looking at this as well, and i would get the following error message:
CCLD tar
../gnu/libgnu.a(quotearg.o): In function `quote':
/home/anarcat/dist/tar-1.27.1/gnu/quotearg.c:968: multiple definition of `quote'
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../lib/libacl.a(quote.o):(.text+0x0): first defined here
names.o: In function `gid_to_gname':
/home/anarcat/dist/tar-1.27.1/src/names.c:95: warning: Using 'getgrgid' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
names.o: In function `gname_to_gid':
/home/anarcat/dist/tar-1.27.1/src/names.c:155: warning: Using 'getgrnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
names.o: In function `uname_to_uid':
/home/anarcat/dist/tar-1.27.1/src/names.c:125: warning: Using 'getpwnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
names.o: In function `uid_to_uname':
/home/anarcat/dist/tar-1.27.1/src/names.c:65: warning: Using 'getpwuid' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
../lib/libtar.a(rtapelib.o): In function `rmt_open__':
/home/anarcat/dist/tar-1.27.1/lib/rtapelib.c:428: warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
collect2: error: ld returned 1 exit status
Makefile:1304: recipe for target 'tar' failed
I don't quite get it, but apparently, "You cannot getpwnam and friends with the whole flexibility that glibc has without shared libraries".
So game over? unclear.
For Fedora you can enable Repository CERT Forensics Tools
and complete build dependencies with some static libs (non-exhaustive list)
zlib-static
libiconv-static
libffi-devel
gettext-devel
pcre-static
ncurses-static
nss-devel
glibc-static
libselinux-static
libsepol-static
libattr-devel
libacl-devel
if libacl.a is missing you have to download source first from:
git clone https://git.savannah.nongnu.org/git/attr.git
git clone https://git.savannah.nongnu.org/git/acl.git
and compile with (first libattr, then libacl, then tar):
./autogen.sh
./configure --prefix=/usr --libexecdir=/usr/lib --enable-static --disable-shared --disable-rpath
make CFLAGS='-static'
make install

Multiple version of library, how to compile with GCC/g++ whit out version number

I am working on a library in C, let us call it ninja.
Ninja depends upon some under laying libraries (which we also provide) (e.g jutsu, goku, bla).
These are all placed in a shared library folder, let us say /usr/lib/secret/.
The clients whom are using this project wants to be able to havde ninja version 1 and 2 laying side by side, this it not so hard. The problem comes when ninja 1 dependes up on for instance jutsu 1 and ninja 2 depends upon jutsu 3. How the h... do we/I do so so that when installing ninja from our package repository. It knows the correct version of jutsu. Of course the rpm/deb package should depend upon the correct version of the jutsu package.
so what we want is when, we execute for instance zypper in ninja. and it installs and compiles on the system, it knows which jutsu library to take with out been given a version number.
So we in the make file don't have to do this:
gcc ninja.c -o ninja -L /usr/local/lib/secret/ -l jutsu_2
But just
gcc ninja.c -o ninja -L /usr/local/lib/secret/ -l jutsu
NOTE: I know it is random to use ninja and so on, but I am not allowed to publish the real library names
You want to use an SONAME. Describing all the steps necessary is probably too large a scope for a good StackOverflow answer, but I can give an overview and point to some documentation.
An SONAME is a special data field inside a shared library. It is typically used to indicate compatibility with other versions of the same library; if two different versions of a shared library have the same SONAME, the linkers will know that either one can fill the dependency on that library. If they have a different SONAME, they can't.
Example: I have libdns88 and libbind-dev version 1:9.8.4.dfsg.P1-6+nmu2+deb7u1 installed on a Debian wheezy system. I build a binary called samurai with -ldns. The GNU linker finds "libdns.so" in my library search path and dynamically links samurai with it. It reads the SONAME field from libdns.so (which is a symlink to libdns.so.88.1.1). The SONAME there is "libdns.so.88".
$ objdump -p /usr/lib/libdns.so | grep SONAME
SONAME libdns.so.88
The libdns developers (or maybe packagers) chose that SONAME to indicate that any version 88.* of libdns is expected to be binary compatible with any other version 88.*. They use that same SONAME for all versions with a compatible ABI. When the ABI had a change, they changed the SONAME to libdns.so.89, and so on. (Most well-managed libraries don't change their ABI that often.)
So the library dependency written into the samurai binary is just libdns.so.88. When I run samurai later, the dynamic linker/loader looks for a file called "libdns.so.88" instead of just "libdns.so".
Also by convention, the name of an rpm or deb package should change when the SONAME of the library contained changes. That's why there is a libdns88 package separate from the libdns100 package, and they can be installed side by side without interfering with each other. My samurai package will have a dependency on "libdns88" and I can expect that any package called libdns88 will have a compatible ABI to the one I built it against. Tools like dpkg-shlibdeps make it simple to create the right shared library package dependencies when SONAMEs and versioned symbols are used.
http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

Building a Shared Library but linking against a Static One

I have an Autogen Makefile.am that I'm trying to use to build a test program for a shared library. To build my test binary, I want to continue building the shared library as target but I want the test program to be linked statically. I've spent the last few hours trying to craft my Makefile.am to get it to do this.
I've tried explicitly changing the LDADD line to use the .a version of the library and get a file not found error even though I can see this library is getting built.
I try to add the .libs directory to my link path via LDFLAGS and still it can't find it.
I tried moving my library sources to my test SOURCES list and this won't work because executable object files are built differently than those for static libraries.
I even tried replicating a lib_LIBRARIES entry for the .a version (so there's both a lib_LTLIBRARIES and a lib_LIBRARIES) and replicate all the LDFLAGS, SOURCES, dir and HEADERS for the shared version as part of the static version (replacing la with a of the form _a_SOURCES = _la_SOURCES. Still that doesn't work because now it can't figure out what to build.
My configure.ac file is using the default LT_INIT which should give me both static and dynamic libraries and as I said it is apprently building both even if the libtool can't see the .a file.
Please, anyone know how to do this?
As #Brett Hale mentions in his comment, you should tell Makefile.am that you want the program to be statically linked.
To achieve this you must append -static to your LDFLAGS.
Changing the LDFLAGS for a specific binary is achieved by changing binary_LDFLAGS (where binary is the name of the binary you want to build).
so something like this should do the trick:
binary_LDFLAGS = $(AM_LDFLAGS) -static

AIX- Does not install shared lib

I am able to build the shared object successfully using the holy native compiler "xlc" on AIX.It does build the shared object library but does not install the shared object library.
Configure command is:
./configure --prefix=/PATH/to/install --exec-prefix=/PATH/to/install --enable-shared --enable-static=no --enable-module=so --build=powerpc-ibm-aix5.3.0.0 --host=powerpc-ibm-aix5.3.0.0 LDFLAGS="-G -shared"
Any help would be appreciated?
So you are trying to compile to the shared library location.
I would suggest seeing if you can compile/link to your local directory.
If that works, try copying the new library to the correct directory. It may be that the oldshared library is open by some process and therefore can't be overwritten.
Are you getting any error messages?
I could install the shared library successfully when i had to exclusively export LDFLAGS as "-brtl -L/path/to/install".
Under AIX, there are two types of shared libraries, AIX style, and SysV compat libs.
AIX style libs are archvies that can contain static libraries as well as multiple versions of shared libraries, and have names like libFOO.a
SysV-compat libs have names like libFoo.so and are more like what you would find on Linux.
Libtool will build either type. If you want SysV-compat libs, add -Wl,-brtl to LDFLAGS.
My guess is that you see /PATH/to/install/lib/libFOO.a and are assuming that it's a static library, when in fact, it's an AIX shared library.

Resources