10. Create RPM package

最後更新: 2020-08-20

 

目錄

  • Step1: 安裝所需的 tools
  • Step2: 建立 Folder 及 設定檔
  • Step3: Get Source & Build
  • Step4: 將 compile 好的 binary, so file 安放好
  • Step5: Create spec file
  • Step6: verify & test a spec file
  • Step7: build the source and the binary rpm
  • Step8: Installation test (這步驟很重要)
  • Macro
  • Spec file
  • Add Program to PATH
  • Install Package
  • Troubleshoot
  • Doc

 


Step1: 安裝所需的 tools

 

# rpm-build: Tool will use to build RPMs from specfiles or SRPM packages

yum install -y rpm-build

Checking:

rpmbuild --version

RPM version 4.11.1

查看 rpmbuild 的 Default setting

rpmbuild --showrc

# rpmlint: spec file checking tools

yum install -y rpmdevtools rpmlint

# redhat-rpm-config: rpmbuild build macros and helper scripts

yum install -y redhat-rpm-config

# Other tools you may need

yum -y groupinstall "Development Tools"

yum -y install unzip wget screen vim

 


Step2: 建立 Folder 及 設定檔

 

RPM Build Directories Tree

mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}

OR

mkdir -p ~/rpmbuild; cd ~/rpmbuild

rpmdev-setuptree                               # rpmdevtools 提供

執行完它後就會建立

  • RPMS: The binary package created by rpmbuild will be stored here
  • BUILD: The place where rpmbuild will build the package
  • SOURCES: The place where to keep the original software sources
  • SPECS: This is where the .spec file will be stored

修改 rpmbuild 的設定檔:

~/.rpmmacros

%_topdir   %(echo $HOME)/rpmbuild
...

More info.

Directory Tree

  • BUILD            # uncompresses source packages and compiles the binaries
  • SOURCES       # Source files and )atches
  • BUILDROOT    # temporary software installation directory. ($RPM_BUILD_ROOT = %{buildroot})
  • SRPMS           # directory contains all the source RPM packages that are built.
  • RPMS             # directory contains subdirectories with various build architectures

Directory macros

The macros are usually used with rpmbuild --define to specify which directories rpmbuild should use

It is unusual to use them within SPEC files

  • %{_topdir}           %{getenv:HOME}/rpmbuild
  • %{_builddir}         %{_topdir}/BUILD
  • %{_rpmdir}          %{_topdir}/RPMS
  • %{_sourcedir}      %{_topdir}/SOURCES
  • %{_specdir}         %{_topdir}/SPECS
  • %{_srcrpmdir}      %{_topdir}/SRPMS
  • %{_buildrootdir}   %{_topdir}/BUILDROOT
  • %{buildroot}         %{_buildrootdir}/%{name}-%{version}-%{release}.%{_arch}     # same as $BUILDROOT

 


Step3: Get Source & Build

 

Example: google-authenticator

yum install pam-devel

cd /usr/src

wget https://github.com/google/google-authenticator-libpam/archive/refs/heads...

unzip master.zip

cd google-authenticator-libpam-master

./bootstrap.sh

./configure

 ...
  google-authenticator version 1.09
  Prefix.........: /usr/local
  Debug Build....:
  C Compiler.....: gcc -std=gnu99 -g -O2 -Wall
  Linker.........: /usr/bin/ld -m elf_x86_64  -ldl

make -j        # 獲得 .libs/pam_google_authenticator.so

 


Step4: 將 compile 好的 binary, so file 安放好

 

cd ~/rpmbuild

mkdir myfile

cp -a /usr/src/google-authenticator*/.libs/pam_google_authenticator.so myfile

cp -a /etc/pam.d/sshd myfile

 


Step5: Create spec file

 

spec 一共有 7 個 sections, 它們分別是:

  • Introduction
  • Prep
  • Build
  • Install
  • Clean
  • Files
  • Changelog (必須)

cd ~/rpmbuild/SPECS

rpmdev-newspec pam_google_authenticator

vi pam_google_authenticator.spec

# This is a comment (just as example)

Name:           pam_google_authenticator
Version:        1                  # 原本 software 的主 Version
Release:        1%{?dist}          # rpm relase 的 version, output rpm file"-1.el7."
Summary:        The google_authenticator (first must be uppercase)

License:        Apache License 2.0
URL:            https://github.com/google/google-authenticator-libpam
Source0:        .... # "rpmbuild -bs .." 會用到它

BuildRequires: gettext
BuildRequires: libtool
Requires:

%description
Description with almost 79 characters (first char must be uppercase)

%prep

%build

%install
install -m 0755 -d $RPM_BUILD_ROOT/usr/lib64/security
install -m 0755 -d $RPM_BUILD_ROOT/etc/pam.d
install -m 0755 %{_builddir}/pam_google_authenticator.so $RPM_BUILD_ROOT/usr/lib64/security
install -m 0755 %{_builddir}/sshd $RPM_BUILD_ROOT/etc/pam.d

%clean
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root,-)
/usr/lib64/security/pam_google_authenticator.so

%config(noreplace)
/etc/pam.d/sshd

%changelog
* Date Name <E-Mail> version-revision
- Summary of changes

說明

Version:        2.0.52                  # 原本 software 的主 Version

Release:        1%{?dist}            # package's version number, output rpm file 有 "-1.el7."

P.S.

%changelog

%changelog 的 Date 是必須填的 ( Format: Fri Aug 28 2015 )

沒填就會有 Error

SPECS/pam_google_authenticator.spec: E: specfile-error error: 
bad date in %changelog: Date Name <E-Mail> version-revision

用 rpmdev-bumpspec 去建立/更新 spec 內的 %changelog section

rpmdev-bumpspec      # bumps release tags in specfiles.

i.e.

SPECS/pam_google_authenticator.spec 不填以下內容

* Date Name <E-Mail> version-revision
- Summary of changes

純 Run 以下 command

rpmdev-bumpspec \
  --comment="Initial RPM release" \
  --userstring="datahunter <[email protected]>" \
  SPECS/pam_google_authenticator.spec

$RPM_BUILD_ROOT

相當於 "Buildroot" Folder. Macro: %{buildroot}

 


Step6: verify & test a spec file

 

rpmlint - check common problems in rpm packages

# rpmlint

rpmlint SPECS/pam_google_authenticator.spec

SPECS/pam_google_authenticator.spec: W: no-%prep-section
SPECS/pam_google_authenticator.spec: W: no-%build-section
SPECS/pam_google_authenticator.spec: W: no-%install-section
0 packages and 1 specfiles checked; 0 errors, 3 warnings.

# 查看有什麼 warning

# -i, --info          # Display explanations for reported messages

rpmlint -i SPECS/pam_google_authenticator.spec

W: no-%prep-section
W: no-%build-section
W: no-%install-section

 


Step7: build the source and the binary rpm

 

# -bb : build only the binary RPM

# -bs : build only the source RPM

rpmbuild -bb SPECS/pam_google_authenticator.spec

Build 好後的 rpm 會放在 ./RPMS/x86_64

P.S.

rpmbuild -b<stage> fileN.spec

  • p     Execute %prep
  • c     Execute %prep, %build
  • i     Execute %prep, %build, %install, %check
  • b     Execute %prep, %build, %install, %check, package (bin)
  • a     Execute %prep, %build, %install, %check, package (bin, src)
  • l     Check %files list

 


Step8: Installation test (這步驟很重要)

 

# List File

rpm -qlp RPMS/x86_64/pam_google_authenticator-1.0-5.x86_64.rpm

/etc/pam.d/sshd
/usr/lib64/security/pam_google_authenticator.so

# Install

rpm -ivh RPMS/x86_64/pam_google_authenticator-1.0-5.x86_64.rpm

 * 當有檔案與其他 rpm package 檔案相同時就會出 conflict

file /etc/pam.d/sshd from install of pam_google_authenticator-1.0-2.x86_64 
conflicts with file from package openssh-server-6.4p1-8.el7.x86_64

 


Macro

 

%prep

For prepare(download & unzip & patch) the software source code for building process.

ie. unpacking the archive in Source0

如果自己 compile, 那可以略過此 section

%build

This is the section that is responsible for performing the build.

i.e. make

如果自己 compile, 那可以略過此 section

%install

It executed as sh script just like %prep and %build.

This is the step that is used for the installation. 類似 make install

%builddir -copying-> %buildroot

i.e. Script of the .spec file

%install
mkdir -p %{buildroot}/{/etc,/usr/bin}
install -m755 ???? %{buildroot}/myprogram

%files

The list of files that will be installed(picked) in the end user 's system.

when you list files in %files section these files are expected to reside within %{buildroot} directory.

Here we consider every file in the BUILD directory to be a part of the package. This is done by placing /* under %files.

%files
/*

It also specifies the file attributes and the owner and group owner for each file to be installed.

%defattr

%defattr(<file mode>, <user>, <group>, <dir mode>)

For example:

%files myfile
%defattr(-,root,root,755)
%{prefix}/bin/*

P.S.

"-" Means: keep the file mode of the file as it was installed

%attr

%attr(<mode>, <user>, <group>) file

Similar to the %defattr macro except that it pertains specifically to the file listed

ie.

[1]

%attr(0755,root,mail) /usr/bin/mutt_dotlock

%clean

Bash script performs cleanup after the rpm build process.

 

%config 與 %config(noreplace)

To specify configuration files for this package

%config                     # File from update, edited file in .rpmsave

 * %config(noreplace)  # rpm command will store the new file with a "rpmnew" extension

For example:

%config
/etc/rpmproc.conf

 

%pre, %post, %preun, and %postun

scripts if you need to have different actions upon installation or uninstallation

 


Spec file

 

Requires

Syntax

Set Required: somepackage

i.e.

Requires: somepackage >= 0.5.0, somepackage < 0.6.0

Release

%{dist}

  • RHEL 6              .el6.centos
  • RHEL 7              .el7.centos
  • Fedora 26          .fc26
  • Fedora 27          .fc27

i.e.

Release:        1%{?dist}

Output

burp-2.0.52-1.el7.centos.x86_64.rpm

Obsoletes

Obsoletes alter the way updates work.

RPM removes all packages matching obsoletes of packages being installed

rpm -i does not do updates and therefore treats Obsoletes: as Conflicts

For most cases rpm -i should be avoided and "rpm -U" should be used

 


Add Program to PATH

 

[方法1]

Adding the PATH in the RPM's post-script,

* script file 必須要是 .sh 尾

* Permission 644 也可以

# cat /etc/profile.d/custom.sh

#!/bin/bash
PATH=$PATH:/opt/git/bin
export PATH

[方法1]

ln -s /opt/myprog/bin/prog /usr/bin/prom

 


Install Package

 

# 用 rpm 安裝唔到有依賴的包

yum install mygit-2.25.4-2.el7.x86_64.rpm

 


Example: mygit.spec

 

Name:           mygit
Version:        2.25.4
Release:        2%{?dist}
Summary:        Fast Version Control System

License:        GPLv2
URL:            http://git-scm.com/
Source0:        https://github.com/git/git/archive/v2.25.4.zip

Requires:       less
Requires:       openssh-clients
Requires:       rsync
Requires:       zlib >= 1.2

%description
Create by Datahunter

%prep

%build

%install
mkdir %{buildroot}/opt
cp -a /opt/git %{buildroot}/opt

%files
%defattr(-,root,root,755)
/opt/git/*

%post
# add git to PATH
cat > /etc/profile.d/mygit.sh <<'EOF'
#!/bin/bash
PATH=/opt/git/bin:$PATH
EOF

%changelog
* Thu Aug 20 2020 datahunter <[email protected]>
- Initial RPM release

 


Sign package with gpg

 

Developer

# generate a gpg key pair

# select: (4) RSA (sign only), key expires in: 3y

gpg --gen-key                            # gpg --list-keys [email protected]

Real name: MyPackage
Email address: [email protected]
Comment: RPM Signing Key
You selected this USER-ID:
    "MyPackage (RPM Signing Key) <[email protected]>"

# Export the Public key

# public key file available online so others can verify RPMs

# -a     Create  ASCII  armored  output.

gpg --export -a a@b > RPM-GPG-KEY

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.22 (GNU/Linux)

...

-----END PGP PUBLIC KEY BLOCK-----

#Sign rpm package

# You must set "%_gpg_name" in your macro file(~/.rpmmacros)

# echo "%_gpg_name REALNAME" >> ~/.rpmmacros

rpm --addsign test-1-0.x86_64.rpm

Enter pass phrase:
Pass phrase is good.
test-1-0.x86_64.rpm.rpm:

# Verify the list of gpg public keys in RPM DB

rpm --import RPM-GPG-KEY

rpm --checksig test-1-0.x86_64.rpm

rpm -q gpg-pubkey --qf '%{name}-%{version}-%{release} --> %{summary}\n'

...
gpg-pubkey-?-? --> gpg(Real name (Comment) <e-mail>)

End-User

yum.repos.d/MyRepo.repo

...
gpgkey=https://URL/gpg.key

OR

rpm --import RPM-GPG-KEY

 


Troubleshoot

 

WARNING: 'check-rpaths' detected a broken RPATH and will cause 'rpmbuild' to fail.

To ignore these errors, you can set the '$QA_RPATHS'

Fix: 清了這一段

cat ~/.rpmmacros

...

%__arch_install_post \
    [ "%{buildarch}" = "noarch" ] || QA_CHECK_RPATHS=1 ; \
    case "${QA_CHECK_RPATHS:-}" in [1yY]*) /usr/lib/rpm/check-rpaths ;; esac \
    /usr/lib/rpm/check-buildroot

 


Doc

 

http://rpm-guide.readthedocs.io/en/latest/rpm-guide.html

 

 

 

 

Creative Commons license icon Creative Commons license icon