配布するためのRPMパッケージをビルドする

# はじめに
色々気にして、未だにオンプレミスな環境から抜け出せないプロダクトは存在します。
そのようなプロダクトで自動デプロイしようと思うと色々面倒だったりします。
そこで、デプロイ時に色々するのではなく、ビルド時に作ったものをそのままデプロイして使える状態にすることが求められることがあるかと思います。
そんなとき、RedHatやCentOSのようなRPM系Linuxディストリビューションである場合、RPMパッケージを作成しそれを配布するという手段をとることができます。
ということで、RPMパッケージをビルドして、配布できる状態を作りたいと思います。

この記事のゴールは、実行ファイルをRPMパッケージとして配布できる状態にすることです。
実行ファイルとして、C言語をコンパイルしたものを使用しています。
また、この記事の中での実行環境は `CentOS8 1905` です。

## 必要なパッケージをインストール
以下のものを `dnf` コマンドを使ってインストールします。

- gcc
- rpmbuild

```.sh
sudo dnf install -y gcc rpm-build
```

## サンプルスクリプト
この記事の中で使用するファイルは全て、GitHub上の [walk8243/rpm-hello](https://github.com/walk8243/rpm-hello) に上げてあります。

### C言語
```hello.c
#include <stdio.h>

void main() {
    printf("hello world.\n");
}
```

### RPM SPECファイル
```hello.spec
###############################################################################
# Spec file for utils
################################################################################
# Configured to be built by user develop or other non-root user
################################################################################
#
Summary: Hello scripts for testing RPM creation
Name: hello
Version: 1.0.0
Release: 1
License: GPL
URL: http://www.walk8243.xyz
Group: System
Packager: walk8243


%description
A collection of hello scripts for testing RPM creation.


%prep
################################################################################
# Create the build tree and copy the files from the development directories    #
# into the build tree.                                                         #
################################################################################
echo "BUILDROOT = $RPM_BUILD_ROOT"
mkdir -p $RPM_BUILD_ROOT/usr/local/bin/

cp $SRC_ROOT/hello $RPM_BUILD_ROOT/usr/local/bin

exit


%files
%attr(0755, root, root) /usr/local/bin/*


%clean
rm -rf $RPM_BUILD_ROOT/usr/local/bin

# Build with the following syntax:
# export SRC_ROOT=$(pwd) && rpmbuild -bb hello.spec

```

## RPMのビルド時のディレクトリ構成
ホームディレクトリ直下で [walk8243/rpm-hello](https://github.com/walk8243/rpm-hello) をクローンしたとします。
すると、以下のようなディレクトリ構成になっているはずです（必要最小限のものだけ書いています）。

```
~
 `- rpm-hello
     |- hello.c
     `- hello.spec
```

これで準備はできましたので、実際にビルドしていきます。

# RPMパッケージのビルド
以下のスクリプトを順に実行して、RPMパッケージをビルドします。
このときのカレントディレクトリは、クローンした `rpm-hello` である想定です。

```.sh
# C言語のコンパイル
gcc hello.c -i hello

# RPMパッケージのビルド
export SRC_ROOT=$(pwd) && rpmbuild -bb hello.spec

# RPMパッケージの確認
sudo rpm -ivh $(find ~/rpmbuild/RPMS/ -name "hello*.rpm")
hello
```

上記のコマンドを叩いて、 `hello world.` と出れば成功です。

# RPMパッケージの詳細情報を見る
```.sh
rpm -qpi $(find ~/rpmbuild/RPMS/ -name "hello*.rpm")
```

すると、以下のように内容が表示されると思います。

```.txt
Name        : hello
Version     : 1.0.0
Release     : 1
Architecture: x86_64
Install Date: (not installed)
Group       : System
Size        : 13464
License     : GPL
Signature   : (none)
Source RPM  : hello-1.0.0-1.src.rpm
Build Date  : Sat Oct 12 02:21:35 2019
Build Host  : localhost
Relocations : (not relocatable)
Packager    : walk8243
URL         : http://www.walk8243.xyz
Summary     : Hello scripts for testing RPM creation
Description :
A collection of hello scripts for testing RPM creation.
```

インストール後に `dnf` を使ってパッケージ情報を取得する（ `dnf info hello` ）と、以下のようになります。

```.txt
Name         : hello
Version      : 1.0.0
Release      : 1
Arch         : x86_64
Size         : 13 k
Source       : hello-1.0.0-1.src.rpm
Repo         : @System
Summary      : Hello scripts for testing RPM creation
URL          : http://www.walk8243.xyz
License      : GPL
Description  : A collection of hello scripts for testing RPM creation.
```

# わかったこと
### `rpmbuild` ディレクトリは `rpm-build` が作ってくれる
色んなサイトで `rpmbuild` ディレクトリを作って、その中に適切にファイルを配置してって感じで書いていたが、全然そんなことはありませんでした。
SPECファイルの中で `cp` コマンドを使って配置することができるので、tarに圧縮してなどは考えなくていいです。

### 環境変数が使える
SPECファイル内で環境変数を使うことができます。
`export` をすることを忘れてはいけませんが、環境変数を使うことでビルドの設定は楽になるはずです。

# さいごに
これまでRPMパッケージを作ることはハードルが高いことだと思っていました。
しかし、ビルドして配布するだけなら簡単に行えることを今回知ることができました。
まだオンプレミスな環境から抜け出せないプロダクトもあるので、そのような環境で一括管理するときなどで使っていこうと思います。

ただ、気を付けなければならないのが、作ったものを配布するということは、動作を保証するということになります。
配布する範囲はどの程度なのか、どこまでの環境を担保するのかなどなど、実際に配布する際には気を付けなければなりません。

# 参考
- [How to build rpm packages | Opensource.com](https://opensource.com/article/18/9/how-build-rpm-packages)
- [SPECファイルの記述](https://vinelinux.org/docs/vine6/making-rpm/make-spec.html)
- [RPM Packaging Guide](https://rpm-packaging-guide.github.io/)
- [rpm.org - Macro syntax](https://rpm.org/user_doc/macros.html)