search
top

How To Build RPMS on CentOS 7

Introduction

Building RPMS brings fear to new Linux system administrators. The uncertainty of setting up the build environment and the SPEC file definitions and usage can be daunting. In this post we will hope to alleviate those fears and show how you can create RPMS for applications and other items on CentOS / RHEL 7.

The RPM Package Manager (RPM) is a powerful command line driven package management system capable of installing, uninstalling, verifying, querying, and updating computer software packages. Each software package consists of an archive of files along with information about the package like its version, a description, and the like. There is also a library API, permitting advanced developers to manage such transactions from programming languages such as C or Python.

Build Environment Preparation

Open a terminal and install the Development tools, Server Platform Development, Additional Development and Compatibility libraries. Run the following command to perform a group install. You will also need to install epel-release and rpm-build and rpmdevtools.

$ sudo yum install epel-release rpm-build rpmdevtools
$ sudo yum groupinstall "Development tools" "Server Platform Development" "Additional Development" “Compatibility libraries”

Now we are ready to setup the RPM Build directory environment. We can achieve this by using rpmdev-setuptree command. From the terminal type.

$ rpmdev-setuptree

This will create rpmbuild directory with the sub-directories BUILD, RPMS, SOURCES, SPECS, SRPMS. Our environment is ready to go on CentOS 7.

We are now ready to start creating packages, our environment is set.

Build a Package

So we are ready to start creating a package, what do we need to get started. At a minimum a tarball of the files / application and a spec file. The spec file is the piece that tells rpmbuild what to do and where to go. In this example we are using an application called UC4 to create an RPM package that will extract a tarball and execute a script.

Spec File
The spec file used for the RPM build layout used listed below. There are several fields to modify for each of the instances we will be creating.

Name: uc4g5v9
Version: 9.00A506
Release: 1%{?dist}
Summary: UC4 is a scheduler application.
Vendor: Atomic
License: GPL
URL: None
Group: Applications/Editors
Source: uc4g5v9.tar.gz
BuildRoot: /home/builder/rpmbuild/%{name}-{%{version}
Packager: myname@company.com

%description
UC4 is a scheduler application.

%prep
%setup -n uc4g5.A506

%install
rm -rf “$RPM_BUILD_ROOT”
mkdir -p “$RPM_BUILD_ROOT/opt/uc4g5”
cp -R -f * “$RPM_BUILD_ROOT/opt/uc4g5”

%files
/opt/uc4g5/

%clean
rm -rf $RPM_BUILD_ROOT

%post -p /opt/uc4g5/install/setupuc4.sh

%postun
if [ “$1” = 0 ]; then
rm -f /etc/init.d/uc4g5 2> /dev/null; true
rm -rf /opt/uc4g5 2> /dev/null; true
fi

%changelog
* Wed Mar 08 2017 Me<myname@company.com>
– Initial rpm build

So let’s discuss the fields.

Name – This the name of the completed RPM in which we re tagging the version number. This also our directory name used for all of the custom RPM’s we will be creating.
Version – This value should be the version of the program.
• 9.00A506

Release – this number will increment as you create new releases with change. The %{?dist} will add .el(5,6,7) in the filename.

Summary – Brief summary of the application, will not really change.
Vendor – Set to Atomic in this case, the developer of UC4.
License – Currently set to GPL, change if needed
URL – Set to none unless you want to point to Atomic website.
Group – This is set to Applications/Editors, can be anything. Reason is RHEL 5 requires it.
Source – This is set to the source tarball used by rpmbuild. This is covered later in the document on creating.
• uc4g5v9.tar.gz

BuildRoot – This is your rpmbuild environment. /home/builder/rpmbuild/%{name}-{%{version}
Packager – Your email address

%description – A short description of the application, using UC4 is a scheduler application.
%prep – in this section we are running %setup and setting it to the extracted directory from the tarball. Example: %setup -n uc4g5.A506
%install – Here we are creating the RPM_BUILD_ROOT and setting up the directory structure we want for our application. For UC4 our installation is set to /opt/uc4g5, it will change for the other environments. Example:

%install
rm -rf “$RPM_BUILD_ROOT”
mkdir -p “$RPM_BUILD_ROOT/opt/uc4g5”
cp -R -f * “$RPM_BUILD_ROOT/opt/uc4g5”

%files – Location of final application destination. Will change with environment.
Example
%files
/opt/uc4g5/

%clean – just as the name states. Here we are cleaning up our build environment.
Example:

%clean
rm -rf $RPM_BUILD_ROOT

%post – In this section we are running any scripts or processes after install. In UC4 case, we are running the setupuc4.sh script. Script described below.
Example:

%post -p /opt/uc4g5/install/setupuc4.sh

%postun – He we define any post commands for after uninstallation. Currently we are removing uc4 startup script and deleting the directory we extracted our files to.
Example:

if [ “$1” = 0 ]; then
rm -f /etc/init.d/uc4g5 2> /dev/null; true
rm -rf /opt/uc4g5 2> /dev/null; true
fi

%changelog – Here is where we keep track of the changes made to the spec file. Format is specific. Day Mon Day Year Name Email. On first line. On second line put – and comment.

Spec file is ready. Save the changes in rpmbuild/SPECS.

At this time we need to create a our source file and create the tarball. Once you have done that copy it to ~/rpmbuild/SOURCES. We are now ready to create our RPM.

Open a terminal. It is time to run the rpmbuild command, specify a few options and point it to the SPEC file.

We have a few options with rpmbuild to tell what we want for ending packages.

ba – Build binary and source packages
bb – Build binary package
bp – Do the prep stage from the spec file
bc – Do the build stage from the spec file.
bi – Do the install stage from the spec file
bl – Do the list check in the files section of the spec file
bs – Build source package

For our example we want to use the ba option to build the binary and source packages  and using the -v flag for vebose output.

$ rpmbuild -v -ba uc4g5v9.spec
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.HCFbsL
+ umask 022
+ cd /home/builder/rpmbuild/BUILD
+ LANG=C
+ export LANG
+ unset DISPLAY
+ cd /home/builder/rpmbuild/BUILD
+ rm -rf uc4g5v9
+ /bin/tar -xvvf /home/builder/rpmbuild/SOURCES/uc4g5v9.tar.gz
drwxrwxr-x builder/builder 0 2017-02-16 14:38 uc4g5v9/
drwxrwxrwx builder/builder 0 2017-02-16 14:33 uc4g5v9/install/
-rwxrwxrwx builder/builder 1007 2017-02-16 14:17 uc4g5v9/install/uc4g5_init_script
-rwxrwxrwx builder/builder 408 2017-02-17 10:42 uc4g5v9/install/file_permissions
-rw-rw-r– builder/builder 13 2017-01-24 14:34 uc4g5v9/install/version.txt
-rwxrwxrwx builder/builder 2787 2017-02-16 14:33 uc4g5v9/install/setupuc4.sh
drwxrwxrwx builder/builder 0 2014-01-29 08:35 uc4g5v9/out/
drwxrwxrwx builder/builder 0 2014-01-29 08:35 uc4g5v9/temp/
drwxrwxrwx builder/builder 0 2017-02-16 14:33 uc4g5v9/bin/
-rwxrwxrwx builder/builder 56619 2015-03-05 08:25 uc4g5v9/bin/UCXELI3F
-rwxrwxrwx builder/builder 4513 2017-02-16 14:29 uc4g5v9/bin/blank.ini
-rwxrwxrwx builder/builder 92922 2015-03-05 08:25 uc4g5v9/bin/UCXJLI3M
-rwxrwxrwx builder/builder 2062978 2015-03-05 08:25 uc4g5v9/bin/UCXJLI3
-rwxrwxrwx builder/builder 1459450 2015-03-05 08:25 uc4g5v9/bin/ucx.msl
drwxrwxr-x builder/builder 0 2017-02-16 14:38 uc4g5v9/backup/
+ cd uc4g5v9
+ /bin/chmod -Rf a+rX,u+w,g-w,o-w .
+ exit 0
Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.ZqKAoj
+ umask 022
+ cd /home/builder/rpmbuild/BUILD
+ ‘[‘ /home/builder/rpmbuild/BUILDROOT/uc4g5v9-9.00A506-1.el7.x86_64 ‘!=’ / ‘]’
+ rm -rf /home/builder/rpmbuild/BUILDROOT/uc4g5v9-9.00A506-1.el7.x86_64
++ dirname /home/builder/rpmbuild/BUILDROOT/uc4g5v9-9.00A506-1.el7.x86_64
+ mkdir -p /home/builder/rpmbuild/BUILDROOT
+ mkdir /home/builder/rpmbuild/BUILDROOT/uc4g5v9-9.00A506-1.el7.x86_64
+ cd uc4g5v9
+ LANG=C
+ export LANG
+ unset DISPLAY
+ rm -rf /home/builder/rpmbuild/BUILDROOT/uc4g5v9-9.00A506-1.el7.x86_64
+ mkdir -p /home/builder/rpmbuild/BUILDROOT/uc4g5v9-9.00A506-1.el7.x86_64/opt/uc4g5
+ cp -R -f backup bin install out temp /home/builder/rpmbuild/BUILDROOT/uc4g5v9-9.00A506-1.el7.x86_64/opt/uc4g5
+ /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/bin/python
+ /usr/lib/rpm/redhat/brp-python-hardlink
+ /usr/lib/rpm/redhat/brp-java-repack-jars
Processing files: uc4g5v9-9.00A506-1.el7.x86_64
Requires(interp): /bin/sh /opt/uc4g5/install/setupuc4.sh
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires(post): /opt/uc4g5/install/setupuc4.sh
Requires(postun): /bin/sh
Requires: /bin/bash libc.so.6 libc.so.6(GCC_3.0) libc.so.6(GLIBC_2.0) libc.so.6(GLIBC_2.1) libc.so.6(GLIBC_2.1.2) libc.so.6(GLIBC_2.2) libc.so.6(GLIBC_2.2.4) libc.so.6(GLIBC_2.3) libcrypt.so.1 libcrypt.so.1(GLIBC_2.0) libdl.so.2 libdl.so.2(GLIBC_2.0) libdl.so.2(GLIBC_2.1) libpthread.so.0 libpthread.so.0(GLIBC_2.0) libpthread.so.0(GLIBC_2.1) libpthread.so.0(GLIBC_2.2)
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/builder/rpmbuild/BUILDROOT/uc4g5v9-9.00A506-1.el7.x86_64
Wrote: /home/builder/rpmbuild/SRPMS/uc4g5v9-9.00A506-1.el7.src.rpm
Wrote: /home/builder/rpmbuild/RPMS/x86_64/uc4g5v9-9.00A506-1.el7.x86_64.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.4LgNC2
+ umask 022
+ cd /home/builder/rpmbuild/BUILD
+ cd uc4g5v9
+ rm -rf /home/builder/rpmbuild/BUILDROOT/uc4g5v9-9.00A506-1.el7.x86_64
+ exit 0

No errors with the build and we see that the RPM was created and found in /home/builder/rpmbuild/RPMS/x86_64/uc4g5v9-9.00A506-1.el7.x86_64.rpm and the RPM located in /home/builder/rpmbuild/SRPMS/uc4g5v9-9.00A506-1.el7.src.rpm.

Conclusion

We have covered the basics of building an RPM package on CentOS 7, there are many more options available that can handle more complex applications available. Explore and create.

5 Responses to “How To Build RPMS on CentOS 7”

  1. Jon V says:

    Something curious I’ve noticed – in:
    Release: 1%{?dist}
    I’ve found that on Centos 7, it appends el7.centos not just el7 on my builds. So my RPM’s look like:
    myapp-1.2.3-1.el7.centos.x86_64.rpm
    instead of
    myapp-1.2.3-1.el7.x86_64.rpm
    This does not happen if I’m building in my centos6 box.
    Is that the expected behavior?

  2. Ed says:

    %prep
    %setup -n uc4g5.A506

    I don’t see any directory created under this name, uc4g5.A506, under rpmbuild output.

    %setup -n uc4g5.A506 is supposed to create a subdirectory, uc4g5.A506, under the buildroot (/home/builder/rpmbuild/BUILD). But based on the output of rpmbuild, the subdirectory name is uc4g5v9, not uc4g5.A506. Therefore, I am a bit confused with the rpmbuild output.

    If you can clarify my confusion, it would be very much appreciated.

  3. Bob says:

    Crazy, I searched for the latest way to build and rpm and found this page. Started reading and realized it was for uc4! That’s what I need to build it for, but in this case it’s the agent.

    • newlife007 says:

      I used this process to create UC4 RPM’s, one thing I have done is created init.d and systemd scripts for start and stop of the service with a user account. Ths process we have also created installs that modifys the parameters to go to specific instances and change name parameters and other information. The UC4 standard tarball lacks alot, over the years have been creating it to be able to be upgraded easily.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

top