in Infrastructure

RPM Build Issues With Binaries

So today, I decided it was time I built my first RPM. I’m working with EnterpriseDB and got their binary installer for Postgres Enterprise Manager (PEM). I wanted to make it work with Puppet as an RPM install. I followed an online tutorial that walked me through how to setup a build environment on CentOS. I’m currently on a Redhat machine, so this was close enough. It had me do the below steps.

sudo yum install rpm-build
sudo yum install redhat-rpm-config
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
echo '%_topdir %(echo $HOME)/rpmbuild' > ~/.rpmmacros  
sudo yum install make
sudo yum install gcc

I now had an environment setup to work with. I copied the PEM install file to the SOURCES directory and then opened up SPECS/pem-server.spec. The build tools pre-populated my spec file with the basics that I needed. I edited those based on a tutorial I had found and some other spec files that were available to me from our company’s internal Git repo. I started small with the build and just wanted to verify the file was being copied into place correctly before I really tried to do anything complicated. My spec file looked like this:

Summary: install postgres enterprise manager PEM
Name: pem-server
Version: 5.0.0
Release: 2
License: Purchase From EnterpriseDB
BuildArch: x86_64
Group: Infrastructure Tools
Source0: pem_server-5.0.0-2-linux-x64.run

%description
Deploy the pem enterprise tool and its dependencies

%prep

%build

%install
rm -rf %{buildroot}/tmp
mkdir -p %{buildroot}/tmp
cp -rp * %{buildroot}/tmp

%clean
#rm -rf %{buildroot}

%files
%defattr(-,root,root,-)
/tmp

%changelog

I commented out the cleanup so that I could see the files without having to actually install the RPM. I ran the spec file with the below command:

rpmbuild -ba SPECS/pem-server.spec

I noticed something odd though. The file had a different checksum than my source!

md5sum BUILD/pem_server-5.0.0-2-linux-x64.run SOURCES/pem_server-5.0.0-2-linux-x64.run BUILDROOT/pem-server-5.0.0-2.x86_64/tmp/pem_server-5.0.0-2-linux-x64.run 
30160ef08742b7db2d452ac8ecc17fe7  BUILD/pem_server-5.0.0-2-linux-x64.run
30160ef08742b7db2d452ac8ecc17fe7  SOURCES/pem_server-5.0.0-2-linux-x64.run
77b9368787e3173f5278a0095082d7b8  BUILDROOT/pem-server-5.0.0-2.x86_64/tmp/pem_server-5.0.0-2-linux-x64.run

If I ran the file command on it, it showed me that the files had a different version of the ELF binary type. The correct file was “version 1 (GNU/Linux),” and the file that was being built was “version 1 (SYSV).”

file BUILD/pem_server-5.0.0-2-linux-x64.run SOURCES/pem_server-5.0.0-2-linux-x64.run BUILDROOT/pem-server-5.0.0-2.x86_64/tmp/pem_server-5.0.0-2-linux-x64.run  
BUILD/pem_server-5.0.0-2-linux-x64.run:                                   ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, stripped
SOURCES/pem_server-5.0.0-2-linux-x64.run:                                 ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, stripped
BUILDROOT/pem-server-5.0.0-2.x86_64/tmp/pem_server-5.0.0-2-linux-x64.run: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped

I added the -v flag to rpmbuild and the output from my build looked like this:

rpmbuild -ba -v SPECS/pem-server.spec 
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.ZNzowH
+ umask 022
+ cd /home/vagrant/rpmbuild/BUILD
+ LANG=C
+ export LANG
+ unset DISPLAY
+ exit 0
Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.IY0jEd
+ umask 022
+ cd /home/vagrant/rpmbuild/BUILD
+ LANG=C
+ export LANG
+ unset DISPLAY
+ exit 0
Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.IDkyNJ
+ umask 022
+ cd /home/vagrant/rpmbuild/BUILD
+ '[' /home/vagrant/rpmbuild/BUILDROOT/pem-server-5.0.0-2.x86_64 '!=' / ']'
+ rm -rf /home/vagrant/rpmbuild/BUILDROOT/pem-server-5.0.0-2.x86_64
++ dirname /home/vagrant/rpmbuild/BUILDROOT/pem-server-5.0.0-2.x86_64
+ mkdir -p /home/vagrant/rpmbuild/BUILDROOT
+ mkdir /home/vagrant/rpmbuild/BUILDROOT/pem-server-5.0.0-2.x86_64
+ LANG=C
+ export LANG
+ unset DISPLAY
+ rm -rf /home/vagrant/rpmbuild/BUILDROOT/pem-server-5.0.0-2.x86_64/tmp
+ mkdir -p /home/vagrant/rpmbuild/BUILDROOT/pem-server-5.0.0-2.x86_64/tmp
+ cp -rp pem_server-5.0.0-2-linux-x64.run /home/vagrant/rpmbuild/BUILDROOT/pem-server-5.0.0-2.x86_64/tmp
+ /usr/lib/rpm/check-buildroot
+ /usr/lib/rpm/redhat/brp-compress
+ /usr/lib/rpm/redhat/brp-strip /usr/bin/strip
+ /usr/lib/rpm/redhat/brp-strip-static-archive /usr/bin/strip
+ /usr/lib/rpm/redhat/brp-strip-comment-note /usr/bin/strip /usr/bin/objdump
+ /usr/lib/rpm/brp-python-bytecompile
+ /usr/lib/rpm/redhat/brp-python-hardlink
+ /usr/lib/rpm/redhat/brp-java-repack-jars
Processing files: pem-server-5.0.0-2.x86_64
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/vagrant/rpmbuild/BUILDROOT/pem-server-5.0.0-2.x86_64
Wrote: /home/vagrant/rpmbuild/SRPMS/pem-server-5.0.0-2.src.rpm
Wrote: /home/vagrant/rpmbuild/RPMS/x86_64/pem-server-5.0.0-2.x86_64.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.uZXa7K
+ umask 022
+ cd /home/vagrant/rpmbuild/BUILD
+ exit 0

I searched for a variety of things regarding the ELF version and eventually noticed some of the brp-strip commands that were in the output of the build. It made me realize that rpmbuild must be doing something to “help” me. I eventually found this page, which held the answer as to what was happening and how to fix it!

It turns out that “When we create an RPM using rpmbuild, the binary files are stripped. The intention is to reduce the file size, without affecting the functionality. This is the default setting, configured using the rpm macro __os_install_post.” When I tried to run this stripped binary file, I was experiencing issues, so it was apparent that I needed to disable this feature.

There are three ways to turn this feature off:

  • A single RPM
  • RPMs created by a specific user
  • RPMs created by all users
A single RPM

To prevent binary stripping for specific rpm, we can add following line at the top of any rpm spec file:

%global __os_install_post %{nil}
RPMs created by a specific user

Add the following line in the ~/.rpmmacros file:

%__os_install_post %{nil}
RPMs created by all users

Add the following line in the /etc/rpm/macros file:

%__os_install_post %{nil}

I chose to go with a single RPM. I added that line as the first line in my spec file, re-ran the rpmbuild -ba against the spec, and now all of the checksums matched. It took me a long time to find that page, and I hope that this blog may help someone find the answer sooner if they come up with the same problem or use case.

Now that I have this problem out of my way, I’m working to continue the process of building PEM into an RPM.

Write a Comment

Comment