Skip to main content
RPM SPEC files define how packages are built, installed, and distributed in Azure Linux. This guide covers the essential components and best practices for creating SPEC files.

SPEC File Structure

A SPEC file is divided into several sections, each serving a specific purpose:
┌─────────────────────────────┐
│ Preamble (Metadata)         │  ← Package info, dependencies
├─────────────────────────────┤
│ %description                │  ← What the package does
├─────────────────────────────┤
│ %prep                       │  ← Unpack and patch sources
├─────────────────────────────┤
│ %build                      │  ← Compile the software
├─────────────────────────────┤
│ %install                    │  ← Install into buildroot
├─────────────────────────────┤
│ %check                      │  ← Run test suite
├─────────────────────────────┤
│ %files                      │  ← List installed files
├─────────────────────────────┤
│ %changelog                  │  ← Version history
└─────────────────────────────┘

Preamble Section

The preamble contains package metadata and dependencies.

Basic Metadata

Summary:        Access control list utilities
Name:           acl
Version:        2.3.1
Release:        2%{?dist}
License:        GPLv2+
Vendor:         Microsoft Corporation
Distribution:   Azure Linux
Group:          System Environment/Base
URL:            https://savannah.nongnu.org/projects/acl/
Source0:        https://download.savannah.nongnu.org/releases/%{name}/%{name}-%{version}.tar.gz

BuildRequires:  attr-devel
Requires:       libacl = %{version}-%{release}

%description
This package contains the getfacl and setfacl utilities needed for
manipulating access control lists.

Key Fields Explained

A one-line description of the package (max 80 characters). Should be concise and informative.
The package name. Must be lowercase, no spaces. Use hyphens for multi-word names.
The upstream software version. Should match the upstream release exactly.
Package release number. Start at 1%{?dist} and increment for packaging changes. Reset to 1 when Version changes.
The software license. Use SPDX identifiers when possible (e.g., MIT, GPL-2.0-or-later, Apache-2.0).
URLs or filenames of source archives. Use %{name} and %{version} macros for clarity.
Patch files to apply to sources. Name patches descriptively (e.g., CVE-2025-0665.patch).
Packages needed to compile the software. Each on a separate line for clarity.
Packages needed at runtime. Often auto-detected by RPM, but specify explicitly for clarity.

Subpackages

Many packages split functionality into multiple RPMs using subpackages.
%package libs
Summary:        Libraries for curl
Group:          System Environment/Libraries
Provides:       libcurl = %{version}-%{release}

%description libs
This package contains minimal set of shared curl libraries.

# Later in the file...
%files libs
%{_libdir}/libcurl.so.*

Build Sections

%prep - Prepare Sources

The %prep section unpacks sources and applies patches.
%prep
%autosetup
This macro automatically:
  • Unpacks Source0
  • Changes to the unpacked directory
  • Applies all patches in order

%build - Compile Software

The %build section compiles the software.
%build
%configure \
    --disable-static \
    --enable-threaded-resolver \
    --with-ssl \
    --with-gssapi
%make_build
Common for projects using ./configure && make

%install - Install Files

The %install section copies built files to the buildroot.
%install
%make_install
find %{buildroot} -type f -name "*.la" -delete -print
%{_fixperms} %{buildroot}/*

%check - Run Tests

The %check section runs the package test suite.
%check
make test

File Listings

The %files section declares which files belong to each package.

Path Macros

Use RPM macros for standard paths:
MacroPathUsage
%{_bindir}/usr/binUser executables
%{_sbindir}/usr/sbinSystem executables
%{_libdir}/usr/lib64 or /usr/libLibraries
%{_includedir}/usr/includeHeader files
%{_datadir}/usr/shareArchitecture-independent data
%{_mandir}/usr/share/manMan pages
%{_sysconfdir}/etcConfiguration files
%{_localstatedir}/varVariable data

File Attributes

%files
%defattr(-,root,root)
%license COPYING
%{_bindir}/*
%{_mandir}/man1/*

Changelog

The %changelog section tracks package history in reverse chronological order.
%changelog
* Fri Jan 09 2026 Azure Linux Security Servicing Account <[email protected]> - 8.11.1-5
- Patch for CVE-2025-14017

* Thu Sep 11 2025 Azure Linux Security Servicing Account <[email protected]> - 8.11.1-4
- Patch for CVE-2025-10148

* Thu Feb 13 2025 Kanishk Bansal <[email protected]> - 8.11.1-3
- Fix CVE-2025-0665, CVE-2025-0167, CVE-2025-0725

* Wed Feb 26 2025 Tobias Brick <[email protected]> - 8.11.1-2
- Add check section

* Fri Feb 07 2025 Himaja Kesari <[email protected]> - 8.11.1-1
- Bump version to 8.11.1 to address CVE-2024-11053

Changelog Format

* Day Month DD YYYY Name <email> - Version-Release
- Change description
- Another change
Date format must be: DayOfWeek MonthName DD YYYY (e.g., Fri Jan 09 2026)

Complete Examples

Summary:        Access control list utilities
Name:           acl
Version:        2.3.1
Release:        2%{?dist}
License:        GPLv2+
Vendor:         Microsoft Corporation
Distribution:   Azure Linux
Group:          System Environment/Base
URL:            https://savannah.nongnu.org/projects/acl/
Source0:        https://download.savannah.nongnu.org/releases/%{name}/%{name}-%{version}.tar.gz
BuildRequires:  attr-devel
Requires:       libacl = %{version}-%{release}

%description
This package contains the getfacl and setfacl utilities needed for
manipulating access control lists.

%prep
%autosetup

%build
%configure
%make_build LIBTOOL="libtool --tag=CC"

%install
%make_install
find %{buildroot} -type f -name "*.la" -delete -print
chmod 0755 %{buildroot}%{_libdir}/libacl.so.*.*.*
%find_lang %{name}

%check
make test

%files -f %{name}.lang
%license doc/COPYING*
%{_bindir}/chacl
%{_bindir}/getfacl
%{_bindir}/setfacl
%{_mandir}/man1/chacl.1*

%changelog
* Wed Sep 20 2023 Jon Slobodzian <[email protected]> - 2.3.1-2
- Recompile with stack-protection fixed gcc version

* Wed Nov 24 2021 Pawel Winogrodzki <[email protected]> - 2.3.1-1
- Updating to version 2.3.1

Best Practices

Use Macros

Always use RPM macros like %{_bindir} instead of hardcoded paths

Clean Buildroot

Remove .la files and fix permissions in %install

License Files

Mark license files with %license directive

Config Files

Use %config(noreplace) for user-editable configs

Test Coverage

Always include a %check section when tests are available

Detailed Changelog

Write clear, descriptive changelog entries

Common Pitfalls

Don’t hardcode paths - Use macros like %{_bindir} instead of /usr/bin
Don’t include buildroot in files - The %{buildroot} is stripped automatically
Don’t forget %defattr - Always set default file attributes in %files
Don’t skip changelog - Every package change needs a changelog entry

Next Steps

Package Repository

Learn about repository structure and organization

SPECS vs SPECS-EXTENDED

Understand package support levels

Build docs developers (and LLMs) love