Sometimes you might have access to an open source application source code but might not have the RPM file to install it on your system.
In that situation, you can either compile the source code and install the application from source code, or build a RPM file from source code yourself, and use the RPM file to install the application.
There might also be a situation where you want to build a custom RPM package for the application that you developed.
This tutorial explains how to build a RPM package from the source code.
In order to build RPMs, you will need source code, which usually means a compressed tar file that also includes the SPEC file.
The SPEC file typically contains instructions on how to build RPM, what files are part of package and where it should be installed.
The RPM performs the following tasks during the build process.
- Executes the commands and macros mentioned in the prep section of the spec file.
- Checks the content of the file list
- Executes the commands and macros in the build section of the spec file. Macros from the file list is also executed at this step.
- Creates the binary package file
- Creates the source package file
Once the RPM executes the above steps, it creates the binary package file and source package file.
The binary package file consists of all source files along with any additional information to install or uninstall the package.
It is usually enabled with all the options for installing the package that are platform specific. Binary package file contain complete applications or libraries of functions compiled for a particular architecture. The source package usually consists of the original compressed tar file, spec file and the patches which are required to create the binary package file.
Let us see how to create a simple source and BIN RPM packages using a tar file.
If you are new to rpm package, you may first want to understand how to use rpm command to install, upgrade and remove packages on CentOS or RedHat.
1. Install rpm-build Package
To build an rpm file based on the spec file that we just created, we need to use rpmbuild command.
rpmbuild command is part of rpm-build package. Install it as shown show below.
# yum install rpm-build
rpm-build is dependent on the following package. If you don’t have these installed already, yum will automatically install these dependencies for you.
elfutils-libelf rpm rpm-libs rpm-python
2. RPM Build Directories
rpm-build will automatically create the following directory structures that will be used during the RPM build.
# ls -lF /root/rpmbuild/ drwxr-xr-x. 2 root root 4096 Feb 4 12:21 BUILD/ drwxr-xr-x. 2 root root 4096 Feb 4 12:21 BUILDROOT/ drwxr-xr-x. 2 root root 4096 Feb 4 12:21 RPMS/ drwxr-xr-x. 2 root root 4096 Feb 4 12:21 SOURCES/ drwxr-xr-x. 2 root root 4096 Feb 4 12:21 SPECS/ drwxr-xr-x. 2 root root 4096 Feb 4 12:21 SRPMS/
Note: The above directory structure is for both CentOS and RedHat when using rpmbuild package. You can also use /usr/src/redhat directory, but you need to change the topdir parameter accordingly during the rpm build. If you are doing this on SuSE Enterprise Linux, use /usr/src/packages directory.
If you want to use your own directory structure instead of the /root/rpmbuild, you can use one of the following option:
- Use –buildroot option and specify the custom directory during the rpmbuild
- Specify the topdir parameter in the rpmrc file or rpmmacros file.
3. Download Source Tar File
Next, download the source tar file for the package that you want to build and save it under SOURCES directory.
For this example, I’ve used the source code of icecase open source application, which is a server software for streaming multi-media. But, the steps are exactly the same for building RPM for any other application. You just have to download the corresponding source code for the RPM that you are trying to build.
# cd /root/rpmbuild/SOURCES/ # wget http://downloads.xiph.org/releases/icecast/icecast-2.3.3.tar.gz # ls -l -rw-r--r--. 1 root root 1161774 Jun 11 2012 icecast-2.3.3.tar.gz
4. Create the SPEC File
In this step, we direct RPM in the build process by creating a spec file. The spec file usually consists of the following eight different sections:
- Preamble – The preamble section contains information about the package being built and define any dependencies to the package. In general, the preamble consists of entries, one per line, that start with a tag followed by a colon, and then some information.
- %prep – In this section, we prepare the software for building process. Any previous builds are removed during this process and the source file(.tar) file is expanded, etc.
- One more key thing is to understand there are pre-defined macros available to perform various shortcut options to build rpm. You may be using this macros when you try to build any complex packages. In the below example, I have used a macro called %setup which removes any previous builds, untar the source files and changes the ownership of the files. You can also use sh scripts under %prep section to perform this action but %setup macro simplifies the process by using predefined sh scripts.
- %description – the description section usually contains description about the package.
- %build – This is the section that is responsible for performing the build. Usually the %build section is an sh script.
- %install – the % install section is also executed as sh script just like %prep and %build. This is the step that is used for the installation.
- %files – This section contains the list of files that are part of the package. If the files are not part of the %files section then it wont be available in the package. Complete paths are required and you can set the attributes and ownership of the files in this section.
- %clean – This section instructs the RPM to clean up any files that are not part of the application’s normal build area. Lets say for an example, If the application creates a temporary directory structure in /tmp/ as part of its build, it will not be removed. By adding a sh script in %clean section, the directory can be removed after the build process is completed.
Here is the SPEC file that I created for the icecast application to build an RPM file.
# cat /root/rpmbuild/SPECS/icecast.spec Name: icecast Version: 2.3.3 Release: 0 Summary: Xiph Streaming media server that supports multiple formats. Group: Applications/Multimedia License: GPL URL: http://www.icecast.org/ Vendor: Xiph.org Foundation team@icecast.org Source: http://downloads.us.xiph.org/releases/icecast/%{name}-%{version}.tar.gz Prefix: %{_prefix} Packager: Karthik BuildRoot: %{_tmppath}/%{name}-root %description Icecast is a streaming media server which currently supports Ogg Vorbis and MP3 audio streams. It can be used to create an Internet radio station or a privately running jukebox and many things in between. It is very versatile in that new formats can be added relatively easily and supports open standards for commuincation and interaction. %prep %setup -q -n %{name}-%{version} %build CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{_prefix} --mandir=%{_mandir} --sysconfdir=/etc make %install [ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT make DESTDIR=$RPM_BUILD_ROOT install rm -rf $RPM_BUILD_ROOT%{_datadir}/doc/%{name} %clean [ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc README AUTHORS COPYING NEWS TODO ChangeLog %doc doc/*.html %doc doc/*.jpg %doc doc/*.css %config(noreplace) /etc/%{name}.xml %{_bindir}/icecast %{_prefix}/share/icecast/* %changelog In this file, under % prep section you may noticed the macro “%setup -q -n %{name}-%{version}”. This macro executes the following command in the background. cd /usr/src/redhat/BUILD rm -rf icecast gzip -dc /usr/src/redhat/SOURCES/icecast-2.3.3.tar.gz | tar -xvvf - if [ $? -ne 0 ]; then exit $? fi cd icecast cd /usr/src/redhat/BUILD/icecast chown -R root.root . chmod -R a+rX,g-w,o-w .
In %build section, you will see the CFLAGS with configure options that defines the options that can be using during RPM installation and the prefix option , mandatory directory to be present for the installation and sysconfig directory under which the system files needs to be copied over.
Below that line, you will see the make utility which determines the list of files needs to be compiled and compiles them appropriately.
In % install section, the line below the %install that says “make install” is used to take the binaries compiled from the previous step and installs or copies them to the appropriate locations so they can be accessed.
5. Create the RPM File using rpmbuild
Once the SPEC file is ready, you can start building your rpm with rpm –b command. The –b option is used to perform all the phases of the build process. If you see any errors during this phase, then you need to resolve it before re-attempting again. The errors will be usually of library dependencies and you can download and install it as necessary.
# cd /root/rpmbuild/SPECS # rpmbuild -ba icecast.spec Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.Kohe4t + umask 022 + cd /root/rpmbuild/BUILD + cd /root/rpmbuild/BUILD + rm -rf icecast-2.3.3 + /usr/bin/gzip -dc /root/rpmbuild/SOURCES/icecast-2.3.3.tar.gz + /bin/tar -xf - + STATUS=0 + '[' 0 -ne 0 ']' + cd icecast-2.3.3 + /bin/chmod -Rf a+rX,u+w,g-w,o-w . + exit 0 Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.ynm7H7 + umask 022 + cd /root/rpmbuild/BUILD + cd icecast-2.3.3 + CFLAGS='-O2 -g' + ./configure --prefix=/usr --mandir=/usr/share/man --sysconfdir=/etc checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes checking for a thread-safe mkdir -p... /bin/mkdir -p checking for gawk... gawk checking whether make sets $(MAKE)... yes checking whether to enable maintainer-specific portions of Makefiles... no checking for gcc... gcc .. .. .. Wrote: /root/rpmbuild/SRPMS/icecast-2.3.3-0.src.rpm Wrote: /root/rpmbuild/RPMS/x86_64/icecast-2.3.3-0.x86_64.rpm Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.dzahrv + umask 022 + cd /root/rpmbuild/BUILD + cd icecast-2.3.3 + '[' /root/rpmbuild/BUILDROOT/icecast-2.3.3-0.x86_64 '!=' / ']' + rm -rf /root/rpmbuild/BUILDROOT/icecast-2.3.3-0.x86_64 + exit 0
Note: If you are using SuSE Linux, if rpmbuild is not available, try using “rpm -ba” to build the rpm package.
During the above rpmbuild install, you might notice the following error messages:
Error 1: XSLT configuration could not be found
checking for xslt-config... no configure: error: XSLT configuration could not be found error: Bad exit status from /var/tmp/rpm-tmp.8J0ynG (%build) RPM build errors: Bad exit status from /var/tmp/rpm-tmp.8J0ynG (%build)
Solution 1: Install libxstl-devel
For the xslt-config, you need to install libxstl-devel package as shown below.
yum install libxstl-devel
This will also install the following dependencies:
- libgcrypt
- libgcrypt-devel
- libgpg-error-devel
Error 2: libvorbis Error
checking for libvorbis... configure: error: must have Ogg Vorbis v1.0 or above installed error: Bad exit status from /var/tmp/rpm-tmp.m4Gk3f (%build)
Solution 2: Install libvorbis-devel
For the Ogg Vorbis v1.0, install the libvorbis-devel package as shown below:
yum install libvorbis-devel
This will also install the following dependencies:
- libogg
- libogg-devel
- libvorbis
6. Verify the Source and Binary RPM Files
Once the rpmbuild is completed, you can verify the source rpm and binary rpm is created in the below directories.
# ls -l /root/rpmbuild/SRPMS/ -rw-r--r-- 1 root root 1162483 Aug 25 15:46 icecast-2.3.3-0.src.rpm # ls -l /root/rpmbuild/RPMS/x86_64/ -rw-r--r--. 1 root root 349181 Feb 4 12:54 icecast-2.3.3-0.x86_64.rpm
7. Install the RPM File to Verify
As a final step, you can install the binary rpm to verify that it installs successfully and all the dependencies are resolved.
# rpm -ivvh /root/rpmbuild/RPMS/x86_64/icecast-2.3.3-0.x86_64.rpm D: ============== /root/rpmbuild/RPMS/x86_64/icecast-2.3.3-0.x86_64.rpm D: loading keyring from pubkeys in /var/lib/rpm/pubkeys/*.key D: couldn't find any keys in /var/lib/rpm/pubkeys/*.key D: loading keyring from rpmdb D: opening db environment /var/lib/rpm cdb:mpool:joinenv D: opening db index /var/lib/rpm/Packages rdonly mode=0x0 D: read h# 210 Header sanity check: OK D: added key gpg-pubkey-c105b9de-4e0fd3a3 to keyring D: Using legacy gpg-pubkey(s) from rpmdb D: Expected size: 349181 = lead(96)+sigs(180)+pad(4)+data(348901) D: Actual size: 349181 D: ========== relocations D: added binary package [0] D: found 0 source and 1 binary packages D: ========== +++ icecast-2.3.3-0 x86_64/linux 0x2 .. ..
After the above installation, you can verify that your custom created rpm file was installed successfully as shown below.
# rpm -qa icecast icecast-2.3.3-0.x86_64
Comments on this entry are closed.
Just keep in mind that : “You should NEVER create your packages as the root user.”
https://fedoraproject.org/wiki/How_to_create_an_RPM_package#Preparing_your_system
Hi,
Really very nice article
Thanks a lot..
While this is valid tutorial, building RPMs this way is going to make the people’s live miserable.
I’m saying this because after just a few built packages, users will install all kind of dependent packages on their systems which is very bad. Primarily because they might forget to add to spec file (or even fail to notice) the exact dependencies that are needed for build process. Even though the dependencies aren’t explicitly defined in spec file, the build process will complete successfully, just because the depenent packages are already installed on the machine used for building the package.
Secondly, the machine used for building RPMs will eventually become bloated with all those packages that were installed as dependency for the packages that were being built.
The correct, best and easiest way to RPMs is using Mock (https://fedorahosted.org/mock/) – simple chroot environment designed for building RPMs in isolated, clean environment where is impossible to overlook missing dependencies and where’s no way to bloat the underlying system.
You should write a followup tutorial, there’s way too much tutorials which promote this kind of approach to RPM building anyway 🙂
the steps given are not working as it is in centos 6.5. It is neither creating the rpmbuild directory structure nor does the rpmbuild -ba icecast.spec command is working.
Nice Article..Thanks
Very Useful info.
Thanks!
Nice Tutorial,thanks……….
Your icecast.spec does not work and rpm-build is not correct.
There is quite a few miss representation in this write up.
nice tutorial,Thanks
Hii
need to build NAXSI in rpm file. Please-me!!
Hello, especially to Kert, two suggestions:
1) If you want to build a full-fledged RPM with the “original” RH/Fedora toolchain, I suggest you take a look at docker-rpm-builder:
https://github.com/alanfranz/docker-rpm-builder
it’s easier to use than rpmbuild and mock.
2) If you just want to build an rpm without much fuss, take a look at FPM and its dockerized version (for native packages):
https://github.com/alanfranz/fpm-within-docker
disclaimer: I’m the author of both tools.
Very good tutorial.
Just a package name fix:
it is “libxslt-devel” not “libxstl-devel”
I encountered this problem.
+ cp -pr doc/style.css /home/rpmbuild/rpmbuild/BUILDROOT/icecast-2.3.3-0.x86_64/usr/share/doc/icecast-2.3.3
+ exit 0
RPM build errors:
File must begin with “/”: *%changelog
File must begin with “/”: In
File must begin with “/”: this
File must begin with “/”: file,
File must begin with “/”: under
File must begin with “/”: %
File must begin with “/”: prep
File must begin with “/”: section
File must begin with “/”: you
File must begin with “/”: may
File must begin with “/”: noticed
File must begin with “/”: the
File must begin with “/”: macro
File must begin with “/”: “%setup
File must begin with “/”: -q
File must begin with “/”: -n
File must begin with “/”: icecast-2.3.3”.
File must begin with “/”: This
File must begin with “/”: macro
File must begin with “/”: executes
File must begin with “/”: the
File must begin with “/”: following
File must begin with “/”: command
File must begin with “/”: in
File must begin with “/”: the
File must begin with “/”: background.
File must begin with “/”: cd
File must begin with “/”: rm
File must begin with “/”: -rf
File must begin with “/”: icecast
File must begin with “/”: gzip
File must begin with “/”: -dc
Two files on one line: /usr/src/redhat/SOURCES/icecast-2.3.3.tar.gz
File must begin with “/”: |
Two files on one line: /usr/src/redhat/SOURCES/icecast-2.3.3.tar.gz
File must begin with “/”: tar
Two files on one line: /usr/src/redhat/SOURCES/icecast-2.3.3.tar.gz
File must begin with “/”: -xvvf
Two files on one line: /usr/src/redhat/SOURCES/icecast-2.3.3.tar.gz
File must begin with “/”: –
File must begin with “/”: if
File must begin with “/”: [
File must begin with “/”: $?
File must begin with “/”: -ne
File must begin with “/”: 0
File must begin with “/”: ];
File must begin with “/”: then
File must begin with “/”: exit
File must begin with “/”: $?
File must begin with “/”: fi
File must begin with “/”: cd
File must begin with “/”: icecast
File must begin with “/”: cd
File must begin with “/”: chown
File must begin with “/”: -R
File must begin with “/”: root.root
File must begin with “/”: .
File must begin with “/”: chmod
File must begin with “/”: -R
File must begin with “/”: a+rX,g-w,o-w
File must begin with “/”: .
Wanted to let you know,Under “error I”, the package to be installed that you have shown is
sudo yum install libxstl-devel
but what you need is:
sudo yum install libxslt-devel.
The firs package apparently exists as well, the typo got me scratching my head for a few mins.
Thank you for the help Ramesh
the document is fantastic only prob is its “yum install libxslt-devel” not “yum install libxstl-devel”
Is it possible to execute for loop inside in the %build, %install and %files section?
I have a bunch of locations to play around with using RPM. If I am running for loop over the locations, the script is not able to identify.
Hello, is it safe if I create an rpm file on a vps server, then install it to another vps server?
Thanks