| Message ID | 59ba081c8c874065b6cdc050a2897422be4a7a59.1770707181.git.liezhi.yang@windriver.com |
|---|---|
| State | New |
| Headers | show |
| Series | [v4,1/7] package_rpm.bbclass: Drop external dependency generator to support rpm 6 | expand |
On Mon, 2026-02-09 at 23:10 -0800, Robert Yang via lists.openembedded.org wrote: > From: Robert Yang <liezhi.yang@windriver.com> > > Fixed: > $ bitbake core-image-full-cmdline:do_testimage > %post(busybox-1.37.0-r0.x86_64_x32): execv(/bin/sh) pid 624 > error: failed to exec scriptlet interpreter /bin/sh: No such file or directory > > It is because busybox and libc6 depends on each other, busybox' elf files > depends on libc6, and libc6's postin depends on busybox' /bin/sh, the do_rootfs > works well is because dnf-native has set RPM_NO_CHROOT_FOR_SCRIPTS=1, but it > would be failed for a fresh rootfs. > > In rpm 4.20.1, it let the installed files' Requires win, so it installed > busybox firstly, but in rpm 6.0.1, it let the postin's Requires win since > postin would run immediately after the files are installed, this does make > sense, so it installed busybox (which provides /bin/sh required by libc6' > postin) firstly, then we got the errors. I couldn't find which commit made this > change because a lot of files and functions are refactored during 4.20.1 and > 6.0.0 (not .1), I also tried bisect, but failed because a lot of do_patch or > do_configure/do_compile failures for each build. > > For libc6's the postin is: > > #!/bin/sh > if [ x"$D" = "x" ]; then > if [ -x /sbin/ldconfig ]; then /sbin/ldconfig ; fi > fi > > This doesn't make sense for lib6 since there is no /bin/sh or ldconfig when > libc6 is not ready yet, so we can just remove libc6's postin to fix the > problem. > > And also remove the workarounds in oeqa/runtime/cases/dnf.py, they are not > needed any more since the circular dependency is fixed. > > Signed-off-by: Robert Yang <liezhi.yang@windriver.com> > --- > meta/classes-global/package_rpm.bbclass | 6 ++++-- > meta/lib/oeqa/runtime/cases/dnf.py | 8 -------- > 2 files changed, 4 insertions(+), 10 deletions(-) > > diff --git a/meta/classes-global/package_rpm.bbclass b/meta/classes-global/package_rpm.bbclass > index f4dd779a52..526ac57982 100644 > --- a/meta/classes-global/package_rpm.bbclass > +++ b/meta/classes-global/package_rpm.bbclass > @@ -421,12 +421,14 @@ python write_specfile () { > spec_preamble_bottom.append('') > > # Now process scriptlets > - if splitrpreinst: > + # The libc6 shouldn't have %pre or %post to avoid circular dependency > + libc6 = '%slibc6' % (d.getVar('MLPREFIX') or '') > + if splitrpreinst and splitname != libc6: > spec_scriptlets_bottom.append('%%pre -n %s' % splitname) > spec_scriptlets_bottom.append('# %s - preinst' % splitname) > spec_scriptlets_bottom.append(splitrpreinst) > spec_scriptlets_bottom.append('') > - if splitrpostinst: > + if splitrpostinst and splitname != libc6: > spec_scriptlets_bottom.append('%%post -n %s' % splitname) > spec_scriptlets_bottom.append('# %s - postinst' % splitname) > spec_scriptlets_bottom.append(splitrpostinst) I'm not happy about coding a "libc6" reference into the generic package class. It does make me wonder if there is a similar issue with musl for example and we'd end up with a longer hardcoded list. Could/shouldn't we just not add that postinst for libc6? You could for example force the value of pkg_postinst:libc6 during the packaging process and empty the postinst instead. Also the commit message explains the problem with the postinst but not really why the preinst is a problem? What does that contain which is problematic? Cheers, Richard
Hi RP, On 2/10/26 16:52, Richard Purdie wrote: > On Mon, 2026-02-09 at 23:10 -0800, Robert Yang via lists.openembedded.org wrote: >> From: Robert Yang <liezhi.yang@windriver.com> >> >> Fixed: >> $ bitbake core-image-full-cmdline:do_testimage >> %post(busybox-1.37.0-r0.x86_64_x32): execv(/bin/sh) pid 624 >> error: failed to exec scriptlet interpreter /bin/sh: No such file or directory >> >> It is because busybox and libc6 depends on each other, busybox' elf files >> depends on libc6, and libc6's postin depends on busybox' /bin/sh, the do_rootfs >> works well is because dnf-native has set RPM_NO_CHROOT_FOR_SCRIPTS=1, but it >> would be failed for a fresh rootfs. >> >> In rpm 4.20.1, it let the installed files' Requires win, so it installed >> busybox firstly, but in rpm 6.0.1, it let the postin's Requires win since >> postin would run immediately after the files are installed, this does make >> sense, so it installed busybox (which provides /bin/sh required by libc6' >> postin) firstly, then we got the errors. I couldn't find which commit made this >> change because a lot of files and functions are refactored during 4.20.1 and >> 6.0.0 (not .1), I also tried bisect, but failed because a lot of do_patch or >> do_configure/do_compile failures for each build. >> >> For libc6's the postin is: >> >> #!/bin/sh >> if [ x"$D" = "x" ]; then >> if [ -x /sbin/ldconfig ]; then /sbin/ldconfig ; fi >> fi >> >> This doesn't make sense for lib6 since there is no /bin/sh or ldconfig when >> libc6 is not ready yet, so we can just remove libc6's postin to fix the >> problem. >> >> And also remove the workarounds in oeqa/runtime/cases/dnf.py, they are not >> needed any more since the circular dependency is fixed. >> >> Signed-off-by: Robert Yang <liezhi.yang@windriver.com> >> --- >> meta/classes-global/package_rpm.bbclass | 6 ++++-- >> meta/lib/oeqa/runtime/cases/dnf.py | 8 -------- >> 2 files changed, 4 insertions(+), 10 deletions(-) >> >> diff --git a/meta/classes-global/package_rpm.bbclass b/meta/classes-global/package_rpm.bbclass >> index f4dd779a52..526ac57982 100644 >> --- a/meta/classes-global/package_rpm.bbclass >> +++ b/meta/classes-global/package_rpm.bbclass >> @@ -421,12 +421,14 @@ python write_specfile () { >> spec_preamble_bottom.append('') >> >> # Now process scriptlets >> - if splitrpreinst: >> + # The libc6 shouldn't have %pre or %post to avoid circular dependency >> + libc6 = '%slibc6' % (d.getVar('MLPREFIX') or '') >> + if splitrpreinst and splitname != libc6: >> spec_scriptlets_bottom.append('%%pre -n %s' % splitname) >> spec_scriptlets_bottom.append('# %s - preinst' % splitname) >> spec_scriptlets_bottom.append(splitrpreinst) >> spec_scriptlets_bottom.append('') >> - if splitrpostinst: >> + if splitrpostinst and splitname != libc6: >> spec_scriptlets_bottom.append('%%post -n %s' % splitname) >> spec_scriptlets_bottom.append('# %s - postinst' % splitname) >> spec_scriptlets_bottom.append(splitrpostinst) > > I'm not happy about coding a "libc6" reference into the generic package > class. It does make me wonder if there is a similar issue with musl for > example and we'd end up with a longer hardcoded list. > > Could/shouldn't we just not add that postinst for libc6? You could for > example force the value of pkg_postinst:libc6 during the packaging > process and empty the postinst instead. I think you meant add the following lines in glibc-package.inc: pkg_postinst:glibc () { echo } We need an "echo" here, otherwise, meta/lib/oe/package.py would add the "#!/bin/sh" to the postinst: if needs_ldconfig: bb.debug(1, 'adding ldconfig call to postinst for %s' % pkg) postinst = d.getVar('pkg_postinst:%s' % pkg) if not postinst: postinst = '#!/bin/sh\n' postinst += d.getVar('ldconfig_postinst_fragment') d.setVar('pkg_postinst:%s' % pkg, postinst) But this still doesn't work, because rpm will add the /bin/sh as the default interpreter when not specified. And currently, meta/lib/oe/package.py add the ldconfig_postinst_fragment automatically when find so files, that the root cause, so how about we add a value like: NEEDS_LDCONFIG:<pkg> = "0" or "1" Then we can add the following line to glibc-package.inc to skip that. NEEDS_LDCONFIG:libc6 = "0" And also we need update meta/lib/oe/package.py to check the NEEDS_LDCONFIG:pkg. > > Also the commit message explains the problem with the postinst but not > really why the preinst is a problem? What does that contain which is > problematic? > It is similar to posint, the prinst has a harder situation than postinst. // Robert > Cheers, > > Richard
On 2/10/26 18:08, Robert Yang wrote: > Hi RP, > > On 2/10/26 16:52, Richard Purdie wrote: >> On Mon, 2026-02-09 at 23:10 -0800, Robert Yang via lists.openembedded.org wrote: >>> From: Robert Yang <liezhi.yang@windriver.com> >>> >>> Fixed: >>> $ bitbake core-image-full-cmdline:do_testimage >>> %post(busybox-1.37.0-r0.x86_64_x32): execv(/bin/sh) pid 624 >>> error: failed to exec scriptlet interpreter /bin/sh: No such file or directory >>> >>> It is because busybox and libc6 depends on each other, busybox' elf files >>> depends on libc6, and libc6's postin depends on busybox' /bin/sh, the do_rootfs >>> works well is because dnf-native has set RPM_NO_CHROOT_FOR_SCRIPTS=1, but it >>> would be failed for a fresh rootfs. >>> >>> In rpm 4.20.1, it let the installed files' Requires win, so it installed >>> busybox firstly, but in rpm 6.0.1, it let the postin's Requires win since >>> postin would run immediately after the files are installed, this does make >>> sense, so it installed busybox (which provides /bin/sh required by libc6' >>> postin) firstly, then we got the errors. I couldn't find which commit made this >>> change because a lot of files and functions are refactored during 4.20.1 and >>> 6.0.0 (not .1), I also tried bisect, but failed because a lot of do_patch or >>> do_configure/do_compile failures for each build. >>> >>> For libc6's the postin is: >>> >>> #!/bin/sh >>> if [ x"$D" = "x" ]; then >>> if [ -x /sbin/ldconfig ]; then /sbin/ldconfig ; fi >>> fi >>> >>> This doesn't make sense for lib6 since there is no /bin/sh or ldconfig when >>> libc6 is not ready yet, so we can just remove libc6's postin to fix the >>> problem. >>> >>> And also remove the workarounds in oeqa/runtime/cases/dnf.py, they are not >>> needed any more since the circular dependency is fixed. >>> >>> Signed-off-by: Robert Yang <liezhi.yang@windriver.com> >>> --- >>> meta/classes-global/package_rpm.bbclass | 6 ++++-- >>> meta/lib/oeqa/runtime/cases/dnf.py | 8 -------- >>> 2 files changed, 4 insertions(+), 10 deletions(-) >>> >>> diff --git a/meta/classes-global/package_rpm.bbclass b/meta/classes-global/ >>> package_rpm.bbclass >>> index f4dd779a52..526ac57982 100644 >>> --- a/meta/classes-global/package_rpm.bbclass >>> +++ b/meta/classes-global/package_rpm.bbclass >>> @@ -421,12 +421,14 @@ python write_specfile () { >>> spec_preamble_bottom.append('') >>> # Now process scriptlets >>> - if splitrpreinst: >>> + # The libc6 shouldn't have %pre or %post to avoid circular dependency >>> + libc6 = '%slibc6' % (d.getVar('MLPREFIX') or '') >>> + if splitrpreinst and splitname != libc6: >>> spec_scriptlets_bottom.append('%%pre -n %s' % splitname) >>> spec_scriptlets_bottom.append('# %s - preinst' % splitname) >>> spec_scriptlets_bottom.append(splitrpreinst) >>> spec_scriptlets_bottom.append('') >>> - if splitrpostinst: >>> + if splitrpostinst and splitname != libc6: >>> spec_scriptlets_bottom.append('%%post -n %s' % splitname) >>> spec_scriptlets_bottom.append('# %s - postinst' % splitname) >>> spec_scriptlets_bottom.append(splitrpostinst) >> >> I'm not happy about coding a "libc6" reference into the generic package >> class. It does make me wonder if there is a similar issue with musl for >> example and we'd end up with a longer hardcoded list. >> >> Could/shouldn't we just not add that postinst for libc6? You could for >> example force the value of pkg_postinst:libc6 during the packaging >> process and empty the postinst instead. > > I think you meant add the following lines in glibc-package.inc: > > pkg_postinst:glibc () { > echo > } > > We need an "echo" here, otherwise, meta/lib/oe/package.py would add the > "#!/bin/sh" to the postinst: > > if needs_ldconfig: > bb.debug(1, 'adding ldconfig call to postinst for %s' % pkg) > postinst = d.getVar('pkg_postinst:%s' % pkg) > if not postinst: > postinst = '#!/bin/sh\n' > postinst += d.getVar('ldconfig_postinst_fragment') > d.setVar('pkg_postinst:%s' % pkg, postinst) > > But this still doesn't work, because rpm will add the /bin/sh as the default > interpreter when not specified. And currently, meta/lib/oe/package.py > add the ldconfig_postinst_fragment automatically when find so files, > that the root cause, so how about we add a value like: > > NEEDS_LDCONFIG:<pkg> = "0" or "1" > > Then we can add the following line to glibc-package.inc to skip that. > NEEDS_LDCONFIG:libc6 = "0" > > And also we need update meta/lib/oe/package.py to check the > NEEDS_LDCONFIG:pkg. A easier way should be like this: lyang1@ala-lpggp3:glibc$ git diff diff --git a/meta/lib/oe/package.py b/meta/lib/oe/package.py index 17535ebd6d..f97eae104f 100644 --- a/meta/lib/oe/package.py +++ b/meta/lib/oe/package.py @@ -1824,7 +1824,8 @@ def process_shlibs(pkgfiles, d): if s[0] not in shlib_provider: shlib_provider[s[0]] = {} shlib_provider[s[0]][s[1]] = (pkg, pkgver) - if needs_ldconfig: + if needs_ldconfig and \ + not bb.utils.to_boolean(d.getVar('SKIP_LDCONFIG_POSTINST_FRAGMENT:%s' % pkg)): bb.debug(1, 'adding ldconfig call to postinst for %s' % pkg) postinst = d.getVar('pkg_postinst:%s' % pkg) if not postinst: diff --git a/meta/recipes-core/glibc/glibc-package.inc b/meta/recipes-core/glibc/glibc-package.inc index 21f2200d19..df0dd6720f 100644 --- a/meta/recipes-core/glibc/glibc-package.inc +++ b/meta/recipes-core/glibc/glibc-package.inc @@ -293,7 +293,10 @@ pkg_postinst:nscd () { fi fi } + CONFFILES:nscd = "${sysconfdir}/nscd.conf" +SKIP_LDCONFIG_POSTINST_FRAGMENT:${PN} = "1" +do_package[vardeps] += "SKIP_LDCONFIG_POSTINST_FRAGMENT" SYSTEMD_PACKAGES = "nscd" SYSTEMD_SERVICE:nscd = "nscd.service" And also set the value for musl. I will send the updated patches after more testing. // Robert > >> >> Also the commit message explains the problem with the postinst but not >> really why the preinst is a problem? What does that contain which is >> problematic? >> > > It is similar to posint, the prinst has a harder situation than postinst. > > // Robert > > >> Cheers, >> >> Richard >
diff --git a/meta/classes-global/package_rpm.bbclass b/meta/classes-global/package_rpm.bbclass index f4dd779a52..526ac57982 100644 --- a/meta/classes-global/package_rpm.bbclass +++ b/meta/classes-global/package_rpm.bbclass @@ -421,12 +421,14 @@ python write_specfile () { spec_preamble_bottom.append('') # Now process scriptlets - if splitrpreinst: + # The libc6 shouldn't have %pre or %post to avoid circular dependency + libc6 = '%slibc6' % (d.getVar('MLPREFIX') or '') + if splitrpreinst and splitname != libc6: spec_scriptlets_bottom.append('%%pre -n %s' % splitname) spec_scriptlets_bottom.append('# %s - preinst' % splitname) spec_scriptlets_bottom.append(splitrpreinst) spec_scriptlets_bottom.append('') - if splitrpostinst: + if splitrpostinst and splitname != libc6: spec_scriptlets_bottom.append('%%post -n %s' % splitname) spec_scriptlets_bottom.append('# %s - postinst' % splitname) spec_scriptlets_bottom.append(splitrpostinst) diff --git a/meta/lib/oeqa/runtime/cases/dnf.py b/meta/lib/oeqa/runtime/cases/dnf.py index 3ccb18ce83..029651c571 100644 --- a/meta/lib/oeqa/runtime/cases/dnf.py +++ b/meta/lib/oeqa/runtime/cases/dnf.py @@ -124,15 +124,8 @@ class DnfRepoTest(DnfTest): self.target.run('mkdir -p %s/bin %s/sbin %s/usr/bin %s/usr/sbin' % (rootpath, rootpath, rootpath, rootpath), 1500) self.target.run('mkdir -p %s/dev' % rootpath, 1500) #Handle different architectures lib dirs - self.target.run('mkdir -p %s/lib' % rootpath, 1500) - self.target.run('mkdir -p %s/libx32' % rootpath, 1500) - self.target.run('mkdir -p %s/lib64' % rootpath, 1500) - self.target.run('cp /lib/libtinfo.so.5 %s/lib' % rootpath, 1500) - self.target.run('cp /libx32/libtinfo.so.5 %s/libx32' % rootpath, 1500) - self.target.run('cp /lib64/libtinfo.so.5 %s/lib64' % rootpath, 1500) self.target.run('cp -r /etc/rpm %s/etc' % rootpath, 1500) self.target.run('cp -r /etc/dnf %s/etc' % rootpath, 1500) - self.target.run('cp /bin/sh %s/bin' % rootpath, 1500) self.target.run('mount -o bind /dev %s/dev/' % rootpath, 1500) self.dnf_with_repo('install --installroot=%s -v -y --rpmverbosity=debug busybox' % rootpath) status, output = self.target.run('test -e %s/var/cache/dnf' % rootpath, 1500) @@ -156,7 +149,6 @@ class DnfRepoTest(DnfTest): self.target.run("for l in /lib*; do mkdir -p %s/usr/$l; ln -s usr/$l %s/$l; done" % (rootpath, rootpath)) self.target.run('cp -r /etc/rpm %s/etc' % rootpath) self.target.run('cp -r /etc/dnf %s/etc' % rootpath) - self.target.run('cp /bin/busybox %s/bin/sh' % rootpath) self.target.run('mount -o bind /dev %s/dev/' % rootpath) self.dnf_with_repo('install --installroot=%s -v -y --rpmverbosity=debug busybox' % rootpath) status, output = self.target.run('test -e %s/var/cache/dnf' % rootpath)