RedHat Package Manager (RPM)
A lot of the RPM ecosystem is defined by what’s in /usr/lib/rpm:
[root@mawenzi-04 ~]# ls /usr/lib/rpm
brp-compress              check-buildroot      debuginfo.prov     fontconfig.prov  macros.python           perl.req             rpm.daily      rpmdeps
brp-java-gcjcompile       check-files          desktop-file.prov  kabi.sh          metainfo.prov           pkgconfigdeps.sh     rpmdb_dump     rpm.log
brp-python-bytecompile    check-prereqs        elfdeps            kmod.prov        mkinstalldirs           platform             rpmdb_load     rpmpopt-4.14.3
brp-python-hardlink       check-rpaths         fileattrs          libtooldeps.sh   mono-find-provides      pythondeps.sh        rpmdb_loadcvt  rpmrc
brp-strip                 check-rpaths-worker  find-debuginfo.sh  macros           mono-find-requires      pythondistdeps.py    rpmdb_recover  rpm.supp
brp-strip-comment-note    config.guess         find-lang.sh       macros.d         ocaml-find-provides.sh  python-macro-helper  rpmdb_stat     script.req
brp-strip-shared          config.sub           find-provides      macros.perl      ocaml-find-requires.sh  redhat               rpmdb_upgrade  sepdebugcrcfix
brp-strip-static-archive  debugedit            find-requires      macros.php       perl.prov               rpm2cpio.sh          rpmdb_verify   tgpgYou can see what’s in the macros file: cat /usr/lib/rpm/macros
SPEC Files
From the Wiki, "The "Recipe" for creating an RPM package is a spec file. Spec files end in the ".spec" suffix and contain the package name, version, RPM revision number, steps to build, install, and clean a package, and a changelog. Multiple packages can be built from a single RPM spec file, if desired. RPM packages are created from RPM spec files using the rpmbuild tool.
Spec files are usually distributed within SRPM files, which contain the spec file packaged along with the source code."
Spec files can build multiple RPMs, as defined by the %package directive.
When you install a SRPM, while it does look at the database for dependencies, it doesn’t update the database with your SRPM info. Instead, it deposits the files into a directory tied to your user. Being able to define that directory is important.
rpm --showrc | lessInspecting RPM File
Use rpm -q [OPTIONS] to query the RPM file against the installed RPM database on the system.
View list of files in RPM
[root@mawenzi-04 ~]# rpm -qlp vim-common-9.0.1677-2.fc39.x86_64.rpm
warning: vim-common-9.0.1677-2.fc39.x86_64.rpm: Header V4 RSA/SHA256 Signature, key ID 18b8e74c: NOKEY
/etc/vimrc
/usr/share/doc/vim-common
/usr/share/doc/vim-common/README.md
/usr/share/doc/vim-common/README.txt
/usr/share/doc/vim-common/README_VIM9.md
/usr/share/doc/vim-common/README_ami.txt
/usr/share/doc/vim-common/README_amibin.txt
/usr/share/doc/vim-common/README_amisrc.txt
/usr/share/doc/vim-common/README_bindos.txt
/usr/share/doc/vim-common/README_dos.txt
/usr/share/doc/vim-common/README_extra.txt
/usr/share/doc/vim-common/README_mac.txt
/usr/share/doc/vim-common/README_ole.txt
/usr/share/doc/vim-common/README_os2.txt
/usr/share/doc/vim-common/README_os390.txt
/usr/share/doc/vim-common/README_src.txt
/usr/share/doc/vim-common/README_srcdos.txt
/usr/share/doc/vim-common/README_unix.txt
/usr/share/doc/vim-common/README_vms.txt
/usr/share/doc/vim-common/README_w32s.txt
/usr/share/doc/vim-common/docs
...View requirements/dependencies of RPM
[root@mawenzi-04 ~]# rpm -qp --requires vim-common-9.0.1677-2.fc39.x86_64.rpm
warning: vim-common-9.0.1677-2.fc39.x86_64.rpm: Header V4 RSA/SHA256 Signature, key ID 18b8e74c: NOKEY
/bin/sh
/usr/bin/sh
config(vim-common) = 2:9.0.1677-2.fc39
rpmlib(CaretInVersions) <= 4.15.0-1
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(FileDigests) <= 4.6.0-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rpmlib(PayloadIsZstd) <= 5.4.18-1
vim-data = 2:9.0.1677-2.fc39
vim-filesystem
xxdView what this RPM provides after it’s installed
[root@mawenzi-04 ~]# rpm -qp --provides vim-common-9.0.1677-2.fc39.x86_64.rpm
warning: vim-common-9.0.1677-2.fc39.x86_64.rpm: Header V4 RSA/SHA256 Signature, key ID 18b8e74c: NOKEY
config(vim-common) = 2:9.0.1677-2.fc39
vim-common = 2:9.0.1677-2.fc39
vim-common(x86-64) = 2:9.0.1677-2.fc39
vim-toml = 2:9.0.1677-2.fc39Building RPMs
Install build deps:
zypper install -y rpmdevtools rpmlintCreate our source code package:
#!/bin/bash
echo "hello"Create the following directory structure:
➜  rpm_learning tree hello-0.1
hello-0.1
├── hello
└── LICENSE
0 directories, 2 filesCreate source tarball from directory:
➜  rpm_learning tar -czvf hello-0.1.tar.gz hello-0.1/
hello-0.1/
hello-0.1/hello
hello-0.1/LICENSEdnf install -y rpmdevtools rpmlintSet %packager macro locally:
echo '%packager Caleb Carlson <caleb.carlson@hpe.com>' >> ~/.rpmmacrosSet up build environment:
rpmdev-setuptreeThis should create the following:
➜  rpm_learning tree ~/rpmbuild
/home/ccarlson/rpmbuild
├── BUILD
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS
5 directories, 0 filesCopy source tarball to SOURCES/:
cp hello-0.1.tar.gz ~/rpmbuild/SOURCES/Create an RPM specfile:
Name:           hello
Version:        0.1
Release:        1%{?dist}
Summary:	Example Summary
License:        GPLv3+
Source:		hello-0.1.tar.gz
BuildArch:      noarch
%description
Long description for hello package
%prep
%autosetup -p1
%build
%install
install -D -p -m 0755 hello %{buildroot}%{_bindir}/hello
%check
%files
%license LICENSE
%{_bindir}/hello
%changelogCopy your new .spec file to SPECS/:
cp hello.spec ~/rpmbuild/SPECS/Build the specfile:
➜  rpm_learning rpmbuild -ba ~/rpmbuild/SPECS/hello.spec
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.hlf7Q1
+ umask 022
+ cd /home/ccarlson/rpmbuild/BUILD
+ cd /home/ccarlson/rpmbuild/BUILD
+ rm -rf hello-0.1
+ /usr/bin/gzip -dc /home/ccarlson/rpmbuild/SOURCES/hello-0.1.tar.gz
+ /usr/bin/tar -xof -
+ STATUS=0
+ '[' 0 -ne 0 ']'
+ cd hello-0.1
+ /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w .
+ exit 0
Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.uPr4jR
+ umask 022
+ cd /home/ccarlson/rpmbuild/BUILD
+ /usr/bin/rm -rf /home/ccarlson/rpmbuild/BUILDROOT/hello-0.1-1.x86_64
++ dirname /home/ccarlson/rpmbuild/BUILDROOT/hello-0.1-1.x86_64
+ /usr/bin/mkdir -p /home/ccarlson/rpmbuild/BUILDROOT
+ /usr/bin/mkdir /home/ccarlson/rpmbuild/BUILDROOT/hello-0.1-1.x86_64
+ cd hello-0.1
+ exit 0
Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.FKlXB8
+ umask 022
+ cd /home/ccarlson/rpmbuild/BUILD
+ cd hello-0.1
+ install -D -p -m 0755 hello /home/ccarlson/rpmbuild/BUILDROOT/hello-0.1-1.x86_64/usr/bin/hello
+ '[' noarch = noarch ']'
+ case "${QA_CHECK_RPATHS:-}" in
+ /usr/lib/rpm/check-buildroot
+ /usr/lib/rpm/brp-compress
+ /usr/lib/rpm/brp-suse
Executing(%check): /bin/sh -e /var/tmp/rpm-tmp.Lfi31a
+ umask 022
+ cd /home/ccarlson/rpmbuild/BUILD
+ cd hello-0.1
+ exit 0
Processing files: hello-0.1-1.noarch
Executing(%license): /bin/sh -e /var/tmp/rpm-tmp.72PFur
+ umask 022
+ cd /home/ccarlson/rpmbuild/BUILD
+ cd hello-0.1
+ LICENSEDIR=/home/ccarlson/rpmbuild/BUILDROOT/hello-0.1-1.x86_64/usr/share/licenses/hello
+ export LC_ALL=C
+ LC_ALL=C
+ export LICENSEDIR
+ /usr/bin/mkdir -p /home/ccarlson/rpmbuild/BUILDROOT/hello-0.1-1.x86_64/usr/share/licenses/hello
+ cp -pr LICENSE /home/ccarlson/rpmbuild/BUILDROOT/hello-0.1-1.x86_64/usr/share/licenses/hello
+ exit 0
Provides: hello = 0.1-1
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires: /bin/bash
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/ccarlson/rpmbuild/BUILDROOT/hello-0.1-1.x86_64
Wrote: /home/ccarlson/rpmbuild/SRPMS/hello-0.1-1.src.rpm
Wrote: /home/ccarlson/rpmbuild/RPMS/noarch/hello-0.1-1.noarch.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.Wzvpwb
+ umask 022
+ cd /home/ccarlson/rpmbuild/BUILD
+ cd hello-0.1
+ /usr/bin/rm -rf /home/ccarlson/rpmbuild/BUILDROOT/hello-0.1-1.x86_64
+ exit 0At this point, your ~/rpmbuild directory should look like this:
➜  rpm_learning tree ~/rpmbuild
/home/ccarlson/rpmbuild
├── BUILD
│   └── hello-0.1
│       ├── hello
│       └── LICENSE
├── BUILDROOT
├── RPMS
│   └── noarch
│       └── hello-0.1-1.noarch.rpm
├── SOURCES
│   └── hello-0.1.tar.gz
├── SPECS
│   └── hello.spec
└── SRPMS
    └── hello-0.1-1.src.rpm
8 directories, 6 filesNotice how it created SRPM hello-0.1-1.src.rpm and RPM hello-0.1-1.noarch.rpm.
Now, we can install it:
➜  rpm_learning sudo rpm -ivh ~/rpmbuild/RPMS/noarch/hello-0.1-1.noarch.rpm
[sudo] password for ccarlson:
Preparing...                          ################################# [100%]
Updating / installing...
   1:hello-0.1-1                      ################################# [100%]Just like magic, we’ve got our script in place:
➜  rpm_learning which hello
/usr/bin/hello
➜  rpm_learning hello
helloCreating a Repo
Create a top level directory for your repo: sudo mkdir /mnt/images/daos
Create the following directory structure:
/mnt/images/daos
├── noarch
├── src
└── x86_64Put the .noarch.rpm files in noarch/, src.rpm files in src, and
 x86_64.rpm files in x86_64. Then, from daos/ run:
`createrepo -v --database --xz .`
You should now have a repodata/ directory:
sp06 images/daos » tree repodata
repodata
├── 23b820a8844abc23a5b283c9ff941782320a9a3b333c4a3c1ca94e4c65b5a361-filelists.xml.gz
├── 31a838eeb46d082f280461ae2190e62d892cb53f05afe567edbdda441a322025-other.sqlite.xz
├── 33c1ac96bb0ecd5e3767620b62ff59bab37112341a031320c7e0c47849190808-filelists.sqlite.xz
├── 858d4bfcf1c5f862cabb5a616303f39f5bb3f10a86b5867807070c524b5a90ab-primary.sqlite.xz
├── 9855b31aa757ccf244bd963acd26581075ea3c45739f23ff027b423c3c49e435-other.xml.gz
├── a37e0e07c1e8fd7560ead2a4ff57497472d86dd730ae245787e83b00e15c1234-primary.xml.gz
└── repomd.xmlSince /mnt/images is a web-hosted destination, we should be able to add it
to a .repo file for yum:
[daos]
name=DAOS 2.6.2
baseurl=http://sp06.hpc.amslabs.hpecorp.net:8080/daos/
enabled=1
gpgcheck=0See that it works:
[root@mawenzi-admin yum.repos.d]# dnf search -v daos
DAOS 2.6.2                                                                                                                                 6.8 MB/s |  37 kB     00:00
====================================================================== Name & Summary Matched: daos =======================================================================
daos.x86_64 : DAOS Storage Engine
Repo        : daos
Matched from:
Provide    : daos = 2.6.2-2.el9
daos-admin.x86_64 : DAOS admin tools
Repo        : daos
Matched from:
Provide    : daos-admin = 2.6.2-2.el9
daos-client.x86_64 : The DAOS client
Repo        : daos
Matched from:
Provide    : daos-client = 2.6.2-2.el9
daos-devel.x86_64 : The DAOS development libraries and headers
Repo        : daos
Matched from:
Provide    : daos-devel = 2.6.2-2.el9
daos-server.x86_64 : The DAOS server
Repo        : daos
Matched from:
Provide    : daos-server = 2.6.2-2.el9