Introduction
RPM (Red Hat Package Manager) is a powerful tool for building, installing, and managing software packages on Linux systems. Understanding how to create RPMs using spec files is an essential skill for any DevOps engineer or Linux administrator. This guide will take you through the steps of writing an RPM spec file, creating an RPM package, and installing it. We'll include practical demos with increasing complexity to reinforce your learning.
What is an RPM Spec File?
A spec file is the heart of an RPM package. It contains all the information needed to build the package, including:
Metadata (e.g., name, version, release, summary)
Source files and patches
Build instructions
File installation paths
Scripts (pre-install, post-install, etc.)
Structure of a Spec File
An RPM spec file is divided into sections:
Header Section: Defines package metadata such as name, version, and release.
Description Section: Provides details about the package.
Preparation Section: Prepares the source code for building.
Build Section: Contains the commands to compile the software.
Install Section: Defines the commands to install files.
File Section: Lists the files to include in the package.
Scriptlets: Contains scripts for pre-installation, post-installation, etc.
Step-by-Step Guide
1. Setting Up the Environment
Ensure you have the necessary tools installed:
sudo dnf -y install rpmdevtools rpmlint
Create the RPM build environment:
rpmdev-setuptree # this command will setup the necessary folder structure to work with rpm
Add the following to your ~/.rpmmacros
file: This file will be used to pick up any macros used in .spec file.
%_topdir %(echo $HOME)/rpmbuild
%packager DurgaPrasadAnanta <your-gmail-here@gmail.com>
2. Writing the Spec File
Create a file named example.spec
under ~/rpmbuild/SPECS/
.
Spec File Example
Name: myapp
Version: 1.0.0
Release: 1%{?dist}
Summary: A simple demo application
License: MIT
URL: https://example.com/myapp
Source0: myapp-1.0.0.tar.gz
BuildRequires: gcc make
Requires: glibc >= 2.17
%description
MyApp is a simple application demonstrating RPM packaging.
%prep
%setup -q
%build
make
%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
%files
%license LICENSE
%doc README.md
/usr/local/bin/myapp
/usr/local/share/myapp/*
%changelog
* Fri Jan 10 2025 Your Name <your.email@example.com> - 1.0.0-1
- Initial RPM release
3. Preparing the Source Code
Place your source code in ~/rpmbuild/SOURCES/
:
tar -czvf ~/rpmbuild/SOURCES/myapp-1.0.0.tar.gz myapp/
Ensure the directory structure matches what you’ve described in the %install
section.
4. Building the RPM
Run the build command:
rpmbuild -ba ~/rpmbuild/SPECS/example.spec
Check the ~/rpmbuild/RPMS/
directory for the generated RPM.
5. Installing and Verifying the RPM
Install the RPM:
sudo rpm -ivh ~/rpmbuild/RPMS/x86_64/myapp-1.0.0-1.x86_64.rpm
Verify the installation:
rpm -ql myapp
Practical Demo 1: Packaging a Simple C Application
For this demo, we will package a simple C application. The application prints "Hello, World!" to the console.
Preparing the Application
Create a directory for the source code:
mkdir -p ~/myapp
cd ~/myapp
Add the following files:
main.c
:
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
Makefile
:
CC=gcc
CFLAGS=-Wall
all: myapp
myapp: main.o
$(CC) -o myapp main.o
main.o: main.c
$(CC) $(CFLAGS) -c main.c
install:
mkdir -p $(DESTDIR)/usr/local/bin
cp myapp $(DESTDIR)/usr/local/bin/
clean:
rm -f *.o myapp
LICENSE
and README.md
: Include these files for completeness.
Packaging the Application
Compress the source code:
tar -czvf ~/rpmbuild/SOURCES/myapp-1.0.0.tar.gz .
Create the spec file (example.spec
) as shown earlier. Build the RPM and install it.
Useful commands
rpm -qa
# This command returns every package installed on your system, quite a few packages.
#The packages are returned one per line, as shown following.
rpm -qi package
#The –i option with an rpm query command tells the rpm command to output descriptive information about the package.
#You can also use the longer option, --info, in place of –i. The basic syntax is:
rpm –ql package
#The –l (ell) option queries all the files in a package.
#You can also use the longer option, --list, in place of –l.
rpm2cpio /home/ec2-user/rpmbuild/SRPMS/myapp-1.0.0-1.amzn2023.src.rpm | cpio -idmv
# This unarchives the source rpm and outputs spec file, source code tarball, patches etc..
Tips and Best Practices
- Validation: Use
rpmlint
to validate your spec files and RPMs.
rpmlint ~/rpmbuild/SRPMS/*.src.rpm ~/rpmbuild/RPMS/x86_64/*.rpm
Macros: Leverage macros like
%{_bindir}
and%{_libdir}
for consistency.Dependencies: Clearly define
BuildRequires
andRequires
to avoid runtime issues.Changelog: Maintain an accurate changelog for version tracking.
Useful Resources
https://rpm-packaging-guide.github.io/#introduction
https://rpm-software-management.github.io/rpm/manual/spec.html
https://jfearn.fedorapeople.org/en-US/RPM/4/html/RPM_Guide/ch-using-rpm-db.html
Conclusion
Creating RPMs using spec files might seem daunting initially, but with practice, it becomes straightforward. By following this guide, you now have a strong foundation to package and distribute software effectively. Explore additional features like patches, advanced scriptlets, and dependency management to enhance your packaging skills.