rpmパッケージング

#rpmパッケージング
Qiita初投稿です。
今回の記事はrpmパッケージングについての備忘録的なもの、！
大きな枠組みを理解できればなという感じで記述しました。
細かいところはまた別の記事にまとめる！（つもり、、、）
間違っていることがあったらどんどん突っ込んでくださいまし。

##そもそもrpmパッケージングってなにもの、？
rpm -->> RedHat社が開発したソフトウェアのパッケージ管理システム
パッケージング -->> アプリケーション(?)などを開発した時にどのような環境でも使用できるように必要なものをひとまとめにすること
こんな感じですかね。
まぁrpmパッケージングをすることによって作成物を簡単に配布し、どのような環境でも簡単に使用できるという恩恵を受けられる訳ですよ。
これは使ってみるしか、！ということで早速どのような構造になっているのか見てみましょう！

##ディレクトリ構造

[ディレクトリ①]

`````
rpmtest
  ├──BUILD
  ├──BUILDROOT
  ├──Makefile
  ├──README.md
  ├──RPMS
  ├──SOURCES
  ├──SPECS/
        ∟test.spec
  ├──SRPMS
  ├──hello-test-0.9/
　　　 　├ Makefile
        ∟hello.sh
  `````

今回はこんなディレクトリ構造が完成形だったとしましょう。
topdirをrpmtestとした時、この中に自分で作成するのはMakefile README.md SOURCES SPECS hello-test-0.9のみです。
それ以外のディレクトリはとあるコマンドを実行することによって自動的に作成されます。

そのため結局自分で最初に用意するディレクトリ構造は以下のようになります、

[ディレクトリ②]

`````
rpmtest
  ├──Makefile
  ├──README.md
  ├──SOURCES
  ├──SPECS/
        ∟test.spec
  ├──hello-test-0.9/
　　　 　├ Makefile
        ∟hello.sh
  `````
この構造を作成した後にあるコマンドを実行することによって[ディレクトリ②]のようになるということですね。(しつこい、)


それでは完成形の[ディレクトリ①]について上から順に見ていきましょう。
 - BUILD -> rpmパッケージを作成するときに使用する作業ディレクトリ
 - BUILDROOT -> アプリケーションを仮想インストールする際にルートになるディレクトリ
 - Makefile -> トップディレクトリ(ここではrpmtest)でmakeコマンドを使用できて色々楽になる
 - README.md -> パッケージングしたいものの内容説明
 - RPMS -> 完成したrpmパッケージが置かれるディレクトリ
 - SOURCES -> rpmパッケージに含めるソースコードを置くディレクトリ(今回の場合はhello-test-0.9ディレクトリがパッケージングしたいものなのだが、最初からソースコードをSOURCESに置くのではなく、コマンド実行時にhello-test-0.9ディレクトリをまとめたものが置かれるようにしたいため、最初はSOURCESの中身はからにしておく)
 - SPECS -> rpmパッケージ作成に用いるspecファイルを置くディレクトリ(specファイルの書き方は後で記述)
 - SRPMS -> 完成したsrpmファイルが置かれるディレクトリ
 - hello-test-0.9のMakefile -> specファイル起動時の%installセクションで必要となってくる
 - hello-test-0.9のhello.sh -> 今回パッケージングしたいソースコード

だいぶ見にくくなってしまいましたがこんな感じです。(ここ分かりやすく直したい、)


##rpmパッケージングするためにコードを書いてみる
さぁいよいよ本題に入っていきましょう！
前提として今回パッケージングしたいものはhello-world-0.9/hello.shです。
中身は以下、

```
#!usr/bin/env bash

echo "hello world!"
```
実行するとhello world!って出てくるというとてつもなくシンプルなものですね、
そう！そもそも今回のゴールは`make rpm`ってコマンドを実行するとこのシェルスクリプトをパッケージングできちゃうよ！！すごい！！ってとこなんですね！(今更、、、)
こんなhello world!って出てくる簡単なものをあえてパッケージングする必要は全くもってないのですが、パッケージングしたいものがもっと複雑な構成になっていた時`make rpm`のコマンド1つだけでパッケージング完了したらさすがに神すぎるだろ！！ってなわけです。
はい、話をもとに戻します。
rpmtest/hello-world-0.9で ./hello.sh とコマンドを実行すると許可がありませんと出てきてしまいますが、これはこのままで構いません。天才specファイルが後でどーにかこうにかしてくれます。
hello-world-0.9/Makefileについては後々解説していきます。

次にrpmパッケージングをするにあたって主役となるSPEC/test.specを見ていきましょう。
このspecファイルが天才ですごいんです！
今回のspecファイルは以下のようになっています。
[test.spec]

```
Summary: hellocommand
Name: hello-world
Version: 0.9
Release: 1
License: proprietary
Source0: hello-world-%{version}.tar.gz

%description
hello world

%prep
rm -rf %{buildroot}

%setup

%build

%install
echo %{buildroot}
make install BUILDROOT=%{buildroot} BINDIR=%{_bindir}
 
%clean
rm -rf %{buildroot}

%files
%attr(0755,root,root) %{_bindir}/hello

%changelog
* DAY YOUR NAME <YOUR MAIL ADDRESS> - 0.9-1
- Initial release
```
なるべくシンプルなものにしました。
では解説に進みます。

ちなみにspecファイルは以下のような構成になっています。
- 基本情報
- スクリプト部
├prepセクション
├buildセクション
├installセクション
├checkセクション
├cleanセクション
- ファイルリスト部
- 更新履歴
細かく説明するととてつもなく長くなってしまうのでまた今度、(まとめるつもり、、多分、)
ググるといくらでも出てくるので参考にしてみてください。

とりあえずtest.specがどのような動きになっているのかを見てみましょう。
<%prep>
パッケージングする準備。
前バージョンのBUILDROOTが残っていると厄介なので念のためrmで消しておきます。
<%setup>
①Name-Versionのディレクトリの削除(前のバージョンのソースコードが残っている可能性を考えて)
②Source0で指定されているファイルをgzipで解凍しtarで展開(Name-Versionのディレクトリも作成される)
③Name-Versionのディレクトリに移動
④パーミッションの変更(前述したコマンドを実行すると許可がありませんと出てきてしまう問題がここで解決される！！)
***[[じゃあ②の指定されたファイルってどこからきたの！！]]***
いい質問！ここで疑問を解消してくれるのがトップディレクトリにあるMakefile(rpmtest/Makefile)なんですね！！
まだ使わない部分もありますがとりあえず全部書いておきます。
[Makefile]

```
STR    = .
LIB    = /var/lib

.PHONY: deploy
deploy:
    tar zcf hello-world-0.9.tar.gz hello-world-0.9
    mv hello-world-0.9.tar.gz SOURCES

.PHONY: rpm
rpm:
    make deploy
    rpmbuild -ba --define="_topdir ${PWD}" SPEC/test.spec

.PHONY: clean
clean:
    rm -rf RPMS SRPMS BUILD BUILDROOT SOURCES/hello-world*
```

現時点で関係しているのはdeployの部分。
このMakefileでは`make rpm`を実行すると`make deploy`をしてから`rpmbuild`が実行する(specファイルが走る)流れになっています。
さっきの***疑問***なんとdeployが解決してくれます！
では`make deploy`では一体何が行われているのでしょうか？
❶hello-world-0.9というディレクトリをtarで固める
❷固めたtarファイルをSOURCESディレクトリに移動
この2つの作業が行われています。
そう！！これでさっきの疑問は解決しましたね。
`rpmbuild`を実行すると(specファイルが走らせようとしても)、その前に`make deploy`が実行されtarで固めたhello-world-0.9がSOURCESに移動させられるのです！
<%build>
パッケージをビルドする処理を記入します。
先ほどの%setupで展開されたName-Version(hello-world-0.9)に移動するところがここのセクションのスタート地点です。
<%install>
こちらも%build同様、%setupで展開されたName-Version(hello-world-0.9)に移動するところがここのセクションのスタート地点です。さぁ、ここにもmakeを発見してしまいましたね。
またまたMakefileの登場です。今度のMakefileはrpmtest/hello-world-0.9/Makefileです。
[Makefile]

```
BUILDROOT    = .
BINDIR       = /bin

.PHONY: install
install:
    install -d -m 0755 ${BUILDROOT}${BINDIR}/
    install -m 0755 hello.sh ${BUILDROOT}${BINDIR}/hello
```
このinstallとは仮想installです。
最初にも登場したBUILDROOTの説明じゃ意味わからんと思った方も多いことでしょう。
ここのBUILDROOTを実際のrootに見立てているのです。
変数にしているのでここらへんは応用が利いて使い勝手が良いですね。(ここもう少しわかりやすく書き換えたい、)

さぁさぁ！！これでRPMSの中のファイルをpip installすれば全て解決！！
ヤッタァ 
長いのに読んでいただきありがとうございます。
まだ乱暴な部分が多くあるのでそのうち書き換えます、、、