Skip to contentSkip to conversation

glibc: Package AArch64 dynamic loader symlink correctly with usrmerge

PATCH In review Mike Crowe 2 participants 3 messages Nov 15, 2018 – Nov 16, 2018

lore
Share & tools
lore

Mike Crowe

author
#0 lore raw

PATCH 1/1 glibc: Package AArch64 dynamic loader symlink correctly with usrmerge

When using usrmerge, the compatibility dynamic loader symlink created in do_install_append_aarch64 ends up in /usr/lib rather than /lib. This means that the path added to libc_baselibs needs to be altered to match.

It's also necessary to tweak do_poststash_install_cleanup to not fail when the symlink exists. I'm not entirely sure that the fix I've applied here is the best one, but it does appear to work.

Compile-tested with:
MACHINE = "qemuarm64"
MULTILIBS = "multilib:lib32" DEFAULTTUNE_virtclass-multilib-lib32 = "armv7at-neon" require conf/multilib.conf

and:
MACHINE = "qemuarm64"
without multilib

---
 meta/recipes-core/glibc/glibc-package.inc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
meta/recipes-core/glibc/glibc-package.inc +2 -2
index a98ae1a29c..582ccbd751 100644
@@ -15,7 +15,7 @@ RPROVIDES_glibc-thread-db = "eglibc-thread-db"
 RPROVIDES_${PN}-pcprofile = "eglibc-pcprofile"
 RPROVIDES_${PN}-dbg = "eglibc-dbg"
 libc_baselibs = "${base_libdir}/libc.so.* ${base_libdir}/libc-*.so ${base_libdir}/libm*.so.* ${base_libdir}/libm-*.so ${base_libdir}/libmvec-*.so ${base_libdir}/ld*.so.* ${base_libdir}/ld-*.so ${base_libdir}/libpthread*.so.* ${base_libdir}/libpthread-*.so ${base_libdir}/libresolv*.so.* ${base_libdir}/libresolv-*.so ${base_libdir}/librt*.so.* ${base_libdir}/librt-*.so ${base_libdir}/libutil*.so.* ${base_libdir}/libutil-*.so ${base_libdir}/libnsl*.so.* ${base_libdir}/libnsl-*.so ${base_libdir}/libnss_files*.so.* ${base_libdir}/libnss_files-*.so ${base_libdir}/libnss_compat*.so.* ${base_libdir}/libnss_compat-*.so ${base_libdir}/libnss_dns*.so.* ${base_libdir}/libnss_dns-*.so ${base_libdir}/libdl*.so.* ${base_libdir}/libdl-*.so ${base_libdir}/libanl*.so.* ${base_libdir}/libanl-*.so ${base_libdir}/libBrokenLocale*.so.* ${base_libdir}/libBrokenLocale-*.so"
-libc_baselibs_append_aarch64 = " /lib/ld-linux-aarch64*.so.1"
+libc_baselibs_append_aarch64 = " ${nonarch_base_libdir}/ld-linux-aarch64*.so.1"
 INSANE_SKIP_${PN}_append_aarch64 = " libdir"
 
 FILES_${PN} = "${libc_baselibs} ${libexecdir}/* ${base_sbindir}/ldconfig ${sysconfdir}/ld.so.conf"
@@ -206,7 +206,7 @@ do_poststash_install_cleanup () {
 	rm -rf ${D}${libdir}/gconv
 	rm -rf ${D}/${localedir}
 	rm -rf ${D}${datadir}/locale
-	if [ "${libdir}" != "${exec_prefix}/lib" ]; then
+	if [ "${libdir}" != "${exec_prefix}/lib" -a "${libdir}" != "${exec_prefix}/lib64" ]; then
 		if [ -d ${D}${exec_prefix}/lib ]; then
 			# error out if directory isn't empty
 			# this dir should only contain locale dir
Signature · 1 line
2.11.0
#1 lore raw
Quoted 8 lines · Mike Crowe

When using usrmerge, the compatibility dynamic loader symlink created in do_install_append_aarch64 ends up in /usr/lib rather than /lib. This means that the path added to libc_baselibs needs to be altered to match.

It's also necessary to tweak do_poststash_install_cleanup to not fail when the symlink exists. I'm not entirely sure that the fix I've applied here is the best one, but it does appear to work.

I'm afraid I really don't like this. Its creating a twisted web of logic which is going to be hard to maintain as the code is trying to do too many different things.

In particular, hardcoding "lib64" is usually a bad sign, as is swapping /lib for nonarch_base_libdir since whilst those happen to be similar, they do mean different things here. Its pure luck that usrmerge happens to end up doing the right thing and it will work until someone else wants to do something interesting with the layout and we can complicate this even more.

I'm hoping there is a better way to address this...

Cheers,

Richard

author
#2 lore raw
Quoted 14 lines · Richard Purdie
Quoted 8 lines · Mike Crowe

When using usrmerge, the compatibility dynamic loader symlink created in do_install_append_aarch64 ends up in /usr/lib rather than /lib. This means that the path added to libc_baselibs needs to be altered to match.

It's also necessary to tweak do_poststash_install_cleanup to not fail when the symlink exists. I'm not entirely sure that the fix I've applied here is the best one, but it does appear to work.

I'm afraid I really don't like this. Its creating a twisted web of logic which is going to be hard to maintain as the code is trying to do too many different things.

Quoted 8 lines

In particular, hardcoding "lib64" is usually a bad sign, as is swapping /lib for nonarch_base_libdir since whilst those happen to be similar, they do mean different things here. Its pure luck that usrmerge happens to end up doing the right thing and it will work until someone else wants to do something interesting with the layout and we can complicate this even more.

I'm hoping there is a better way to address this...

I can't say that I'm particularly keen on it either.

The FILES_ line used ${nonarch_base_libdir} because that's what glibc-package.inc:do_install_append_aarch64 already used. To me, this part seems correct: ${nonarch_base_libdir} means what will end up at /lib, no matter what multilib (or even perhaps one day multiarch) prefix is appropriate, and no matter whether that happens to be /usr/lib for installation purposes due to usrmerge.

Stepping back, it looks like there are four cases to deal with based on the two settings of multilib and usrmerge when considering the AArch64 ABI requirement that the dynamic linker must be available in /lib.

* No multilib and no usrmerge:

The dynamic linker ends up in ${base_libdir} which is /lib. Job done.

* usrmerge but no multilib:

The dynamic linker ends up in ${base_libdir} which is /usr/lib. There's a symlink from /lib to /usr/lib. Job done.

* multilib but no usrmerge:

The dynamic linker ends up in ${base_libdir} which is /lib64. We need to create a symlink to /lib. The existing code appears to work for this case.

* multilib and usrmerge:

The dynamic linker ends up in ${base_libdir} which is /usr/lib64 (which is symlinked from /lib64.) We need to create a symlink in /usr/lib (which is symlinked from /lib. This is what I was attempting to fix.

We could invent some sort of "I really want this to be available in /lib on the target" variable, but I don't see how that would end up being different to nonarch_base_libdir.

I think (but haven't tested) that I can get rid of the explicit checks for lib and lib64 by changing the patch to:

meta/recipes-core/glibc/glibc-package.inc +2 -2
index a98ae1a29c..73b86dfa6e 100644
@@ -15,7 +15,7 @@ RPROVIDES_glibc-thread-db = "eglibc-thread-db"
 RPROVIDES_${PN}-pcprofile = "eglibc-pcprofile"
 RPROVIDES_${PN}-dbg = "eglibc-dbg"
 libc_baselibs = "${base_libdir}/libc.so.* ${base_libdir}/libc-*.so ${base_libdir}/libm*.so.* ${base_libdir}/libm-*.so ${base_libdir}/libmvec-*.so ${base_libdir}/ld*.so.* ${base_libdir}/ld-*.so ${base_libdir}/libpthread*.so.* ${base_libdir}/libpthread-*.so ${base_libdir}/libresolv*.so.* ${base_libdir}/libresolv-*.so ${base_libdir}/librt*.so.* ${base_libdir}/librt-*.so ${base_libdir}/libutil*.so.* ${base_libdir}/libutil-*.so ${base_libdir}/libnsl*.so.* ${base_libdir}/libnsl-*.so ${base_libdir}/libnss_files*.so.* ${base_libdir}/libnss_files-*.so ${base_libdir}/libnss_compat*.so.* ${base_libdir}/libnss_compat-*.so ${base_libdir}/libnss_dns*.so.* ${base_libdir}/libnss_dns-*.so ${base_libdir}/libdl*.so.* ${base_libdir}/libdl-*.so ${base_libdir}/libanl*.so.* ${base_libdir}/libanl-*.so ${base_libdir}/libBrokenLocale*.so.* ${base_libdir}/libBrokenLocale-*.so"
-libc_baselibs_append_aarch64 = " /lib/ld-linux-aarch64*.so.1"
+libc_baselibs_append_aarch64 = " ${nonarch_base_libdir}/ld-linux-aarch64*.so.1"
 INSANE_SKIP_${PN}_append_aarch64 = " libdir"
 
 FILES_${PN} = "${libc_baselibs} ${libexecdir}/* ${base_sbindir}/ldconfig ${sysconfdir}/ld.so.conf"
@@ -206,7 +206,7 @@ do_poststash_install_cleanup () {
 	rm -rf ${D}${libdir}/gconv
 	rm -rf ${D}/${localedir}
 	rm -rf ${D}${datadir}/locale
-	if [ "${libdir}" != "${exec_prefix}/lib" ]; then
+	if [ "${libdir}" != "${nonarch_base_libdir}" ]; then
 		if [ -d ${D}${exec_prefix}/lib ]; then
 			# error out if directory isn't empty
 			# this dir should only contain locale dir

Thanks.

Mike.