DevHeads.net

rpm cpio error: prelink and SBCL

I'm trying to package up a Common Lisp application that is built with
SBCL. Near the end of the rpmbuild run, I see this right before the
list of Provides:

prelink: /home/jamesjer/rpmbuild/BUILDROOT/pvs-sbcl-4.2-2.svn20091008.fc12.x86_64/usr/lib64/pvs/bin/ix86_64-Linux/runtime/pvs-sbclisp:
Section .gnu.version created after prelinking

The rpmbuild run appears to complete successfully. However, when I
try to rpm -i the resulting rpm, I get this:

# rpm -i pvs-sbcl-4.2-2.svn20091008.fc12.x86_64.rpm
error: unpacking of archive failed on file
/usr/lib64/pvs/bin/ix86_64-Linux/runtime/pvs-sbclisp;4b2a52f1: cpio:
Digest mismatch
# rpm -K pvs-sbcl-4.2-2.svn20091008.fc12.x86_64.rpm
pvs-sbcl-4.2-2.svn20091008.fc12.x86_64.rpm: sha1 md5 OK

Is that due to prelink? If so, what is broken? SBCL, because it
isn't putting a .gnu.version section in the executable images it
creates? Prelink, because it somehow manages to break the rpm? Both?
And how do I build an RPM that can be installed successfully?

Thanks,

Comments

Re: rpm cpio error: prelink and SBCL

By yersinia at 12/17/2009 - 13:12

You probably have a prelinked file in BUILD ROOT (objdump -s <file> |
grep prelink) . Try to get rid of this in %install with prelink -u

Regards

Re: rpm cpio error: prelink and SBCL

By Jerry James at 12/17/2009 - 14:24

Oh ho! The sbcl executable has already been prelinked. When
save-lisp-and-die is called (at least with :executable t), the sbcl
executable itself is dumped with the Lisp core written into it. So we
wind up with a prelinked image in the build directory, like so:

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (defun my-fun () "Isn't this fun?")

MY-FUN
* (save-lisp-and-die "sbcl-test" :executable t)
[undoing binding stack and other enclosing state... done]
[saving current Lisp image into sbcl-test:
writing 6176 bytes from the read-only space at 0x20000000
writing 4064 bytes from the static space at 0x20100000
writing 42983424 bytes from the dynamic space at 0x1000000000
done]
$ objdump -s sbcl-test | grep -F prelink
Contents of section .gnu.prelink_undo:
So this is going to hit anybody who tries to package up an executable
produced by SBCL. Perhaps this should be noted on
<a href="https://fedoraproject.org/wiki/Packaging:Lisp" title="https://fedoraproject.org/wiki/Packaging:Lisp">https://fedoraproject.org/wiki/Packaging:Lisp</a>.

Re: rpm cpio error: prelink and SBCL

By Jerry James at 12/17/2009 - 16:48

And it's even worse than I thought: "prelink -u saved-image" strips
out the dumped Lisp image! I had a saved image go from 43MB to 171552
bytes when I did that. It looks like putting this in the spec file
works:

%global __prelink_undo_cmd %{nil}

Re: rpm cpio error: prelink and SBCL

By Jakub Jelinek at 12/17/2009 - 16:54

You need to first prelink -u on a copy of the program, then
run it and let it dump itself, then package it up.

I'd actually argue that such packaging is broken anyway, because you didn't
compile the binary you are packaging from source, you copied it from
/usr/bin.

Jakub

Re: rpm cpio error: prelink and SBCL

By Jerry James at 12/17/2009 - 17:09

Ah, thanks.

True, so future sbcl updates wouldn't be reflected in the saved image.
How should I deal with that? I can think of a few approaches.

1. Put an explicit versioned dependency on the sbcl used to build.
Then every sbcl update breaks upgrades for anyone with my package
installed until I get around to rebuilding it. It looks like maxima
has taken this approach.

2. Don't dump an executable, but instead store individual FASL files
that are loaded at runtime by whatever version of sbcl happens to be
installed. The application I'm working with did not take this
approach because of the large size of the application, which would
lead to a significant startup delay. Plus, the SBCL documentation
explicitly doesn't guarantee that FASL files generated by one version
can be loaded and used without error by another version.

3. Compile sbcl AND the application I really want to build from
source. Not only will that make my spec file significantly more
complex, but then I have to stay on top of future sbcl updates so I
can update my package, too. That doesn't seem any better than what
I'm doing now (embedding the existing sbcl binary into my
application).

Even with its faults, #1 seems best to me. Does anybody see another
approach that will work better?

Re: rpm cpio error: prelink and SBCL

By Jerry James at 12/21/2009 - 12:55

FWIW, this didn't work. It solved the problem with generating
uninstallable RPMs, but the binary RPM contains a pristine SBCL image.
I know a good image was dumped, because it is executed during the
build to generate some auxiliary files. I see it running in the log,
so something about the binary RPM generation stripped out all the
built stuff and threw it away. So far, the only successful build came
from a spec file with this entry:

%global __prelink_undo_cmd %{nil}

Re: rpm cpio error: prelink and SBCL

By Jerry James at 12/21/2009 - 14:22

Nope, ignore that. The real problem is that the dumped image is being
stripped. So to successfully build a project that uses SBCL to
generate a dumped executable, I have to:
(1) Add an explicit requires on the version of SBCL that creates the image;
(2) Use an unprelinked copy of the SBCL binary to build; and
(3) Disable stripping of the dumped image.

This is probably the case for at least some of the other Common Lisps.
Who approves changes to the Lisp packaging requirements page?