#navi_header|技術| [[493]] で簡単ながらパッケージ作成時のTipsをまとめているが、今回はビルドを伴わないパッケージの作成方法について勉強してみた。 今回の「ビルドを伴わないパッケージ」というのは、リポジトリやtarボールから展開して適切な場所にファイル・ディレクトリを配置するだけで良いファイルセットをRPMパッケージにすることを指す。PHPスクリプトや、設定ファイルなどでこのようなケースが該当する。 サンプルを作成してみたので、ポイントとなる箇所を解説していく。 サンプル: - msakamoto-sf/rpmbuild-demo-without-compilation -- https://github.com/msakamoto-sf/rpmbuild-demo-without-compilation 今回の練習環境: CentOS 6.5 x86_64版 $ rpm --version RPM version 4.8.0 $ rpmbuild --version RPM version 4.8.0 ソース構成: #pre||> rpmbuild-demo-without-compilation/ ├── buildrpm.sh ... ビルド時の一時的なtarボールの生成とrpmbuildの実行スクリプト ├── helloworld/ ... 設定ファイルのセットで、これを"/etc"以下にインストールするRPMを作成する │   ├── auto_include_child/ │   │   ├── regular1.txt │   │   └── regular2.txt │   ├── dir_only │   │   └── ignored.txt │   ├── greet.conf │   ├── greet-noreplace.conf │   ├── greet.sh │   ├── p0600.txt │   ├── p0705.txt │   └── regular.txt ├── helloworld.spec ... SPECファイル ├── LICENSE └── README.md ||< ビルド方法 #pre||> # yum install rpm-build $ cd /home/msakamoto/work $ git clone git@github.com:msakamoto-sf/rpmbuild-demo-without-compilation.git # 以下はJenkinsなどCI環境からのビルドを意識して、サブシェルによりcdしてから buildrpm.sh を起動する例 $ cd / $ (cd /home/msakamoto/work/rpmbuild-demo-without-compilation && ./buildrpm.sh) ||< * buildrpm.shのポイント - specファイルが参照するtarボールを、スクリプト実行時に動的に生成する。 -- スクリプトの簡略化のためと、一時的なものであるため、tarボールのファイル名にバージョン情報等は含めない。極端な話、プロジェクトとは何の関係のない "foo.tar.gz" とかでも spec ファイルの SourceN と一致していれば問題ない。 - buildrpm.sh と同じディレクトリをカレントディレクトリとして実行することを前提とする。 -- tarボールを作成するときのアーカイブ内のファイルパスの調整のため。 -- もちろん、tarをサブシェルに押し込んで、"(cd /xxx/yyy/zzz && /bin/tar czf ...)" とすれば、カレントディレクトリの依存性を排除することも可能だろう。 - rpmbuildで重要な "_topdir" マクロを、rpmbuildコマンドの "--define" により動的に指定。 -- これにより、 "$HOME/.rpmmacros" への依存性を排除できる。JenkinsなどのCI環境でのビルドにも柔軟に対応できる。 #pre||> #!/bin/sh WORK_DIR=`pwd` BUILD_NAME=helloworld BUILD_SPEC=${BUILD_NAME}.spec BUILD_TAR=${BUILD_NAME}.tar.gz BUILD_DIR=${WORK_DIR}/rpmbuild BUILD_TAR_PATH=${WORK_DIR}/rpmbuild/SOURCES/${BUILD_TAR} /bin/rm -rf ${BUILD_DIR} # rpmbuildが使用する各種ビルドディレクトリを作成 /bin/mkdir -p ${BUILD_DIR}/{BUILD,RPMS,SOURCES,SPECS,SRPMS} # rpmbuildのためだけの、一時的なtarボールを生成してSOURCESに配置 /bin/tar czf ${BUILD_TAR} ${BUILD_NAME}/ /bin/mv ${BUILD_TAR} ${BUILD_TAR_PATH} # "$HOME/.rpmmacros" に依存せずに rpmbuild を実行 /usr/bin/rpmbuild --define "_topdir ${BUILD_DIR}" -bb ${BUILD_SPEC} ||< * helloworld.specファイルのポイント 今回のspecファイルとソースツリーについては、以下の記事を参考にさせて頂いております。helloworldのパッケージ名やディレクトリ構成など、丸パクリさせてもらいました。 - SPEC ファイルを書いて RPM をビルドしてみた | CUBE SUGAR STORAGE -- http://momijiame.tumblr.com/post/32458077768/spec-rpm "Name", "Version", "Release" については難しく無い。"Group"については、可能であれば既に存在するグループ名を指定する方が良いらしい。CentOSであれば、"yum grouplist" でCentOSで利用可能なグループ名の一覧を取得できる。 Name: helloworld Version: 1.0 Release: 1 Group: Security Tools 参考: - YumGroups - yum - Trac -- http://yum.baseurl.org/wiki/YumGroups "Vendor"は、個人ではなく会社等でパッケージを開発する際は入れておいたほうが良いだろう。"URL", "License", "Summary"はそのまま。"BuildArch" については、今回は単なる設定ファイルのパッケージングなので "noarch" を指定した。 Vendor: Example Company Inc. URL: http://www.example.com/ License: Custom License Summary: Example RPM Plain File Packaging. BuildArch: noarch ソースの指定で、ここでrpmbuild.shが一時的に生成したtarボール名を指定している。 # use build-time generated tar ball. Source0: %{name}.tar.gz "BuildRoot"については、最近のRHEL系rpmbuildでは無視されるようだ。RHEL5系以前との互換性のために、一つのシステム上で複数人 or 複数ジョブが同時にビルドしても衝突しないよう、mktempでユニークな一時ファイル名を生成している。なお、今回実験した環境では "rpmbuild/BUILDROOT" というディレクトリが自動的に作成され、それが "%{buildroot}" として参照できていた。 # (only create temporary directory name, for RHEL5 compat environment) # see : http://fedoraproject.org/wiki/Packaging:Guidelines#BuildRoot_tag BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) BuildRootの解説と、最近のrpmbuildではdeprecatedになった話についての参考: - rpm: Using a build root -- http://rpm.org/api/4.4.2.2/buildroot.html - rpmbuild picking up default buildroot even after explicitily defining in spec file ? -- http://www.linuxquestions.org/questions/linux-software-2/rpmbuild-picking-up-default-buildroot-even-after-explicitily-defining-in-spec-file-945144/ -- → http://fedoraproject.org/wiki/Packaging:Guidelines#BuildRoot_tag "%install" で指定する、ファイルツリーの展開先。"%{buildroot}" がインストール先のルートディレクトリに相当する。今回は helloworld を "/etc/helloworld" 以下に展開したいため、そのように調整している。 %define INSTALLDIR %{buildroot}/etc/helloworld パッケージの説明以降は、準備とビルド(今回は何もしない)、仮のインストール、クリーニング処理になる。ファイルコピーについては、tarボール中のファイルパス名と、"%prep"でのファイル展開先との兼ね合いで微調整が必要になる。最後に"%{buildroot}"を削除している。 #pre||> %description %{summary} %prep %setup -q -n %{name} %build %install rm -rf %{INSTALLDIR} mkdir -p %{INSTALLDIR} cp -Rp * %{INSTALLDIR} %clean #rm -rf %{buildroot} # Avoid Disastarous Damage : http://dev.tapweb.co.jp/2010/12/273 [ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT ||< "%files"では、属性の付け方や、"%config"の動きを練習してみた。また、正式にドキュメント化はされていないようだが、"%exclude"により、特定のファイルを除外する方式も試している。"%dir"と組み合わせており、「git向けに空ディレクトリとして、無視ファイル1つだけ入れたディレクトリをリポジトリに登録したが、パッケージインストール時はディレクトリだけを作成して終わりにしたい」というユースケースを想定している。 #pre||> %files %defattr(-,root,root) /etc/helloworld/regular.txt # auto include child files under the directory /etc/helloworld/auto_include_child %config %attr(0600,root,root) /etc/helloworld/greet.conf %config(noreplace) /etc/helloworld/greet-noreplace.conf %attr(0700,root,root) /etc/helloworld/greet.sh %attr(0600,root,root) /etc/helloworld/p0600.txt %attr(0705,root,root) /etc/helloworld/p0705.txt # directory only %dir %attr(0770,-,-) /etc/helloworld/dir_only %exclude /etc/helloworld/dir_only/ignored.txt ||< "%files", "%attr"参考: - Directives For the %files list -- http://www.rpm.org/max-rpm/s1-rpm-inside-files-list-directives.html - rpm - How to set owner for directory in the %files? - Stack Overflow -- http://stackoverflow.com/questions/9963488/how-to-set-owner-for-directory-in-the-files "%exclude"について: - New directive for %files section (%exclude) -- http://www.redhat.com/archives/rpm-list/2007-September/msg00005.html - python - excluding file types when packaging an rpm - Stack Overflow -- http://stackoverflow.com/questions/4786101/excluding-file-types-when-packaging-an-rpm 最後に、pre/post, preun/postun についての練習を入れている。 #pre||> %pre if [ "$1" = "1" ]; then echo "pre-install script : Initial installation." elif [ "$1" = "2" ]; then echo "pre-install script : Upgrade installation." fi %post if [ "$1" = "1" ]; then echo "post-install script : Initial installation." elif [ "$1" = "2" ]; then echo "post-install script : Upgrade installation." fi %preun if [ "$1" = "0" ] ; then echo "pre-uninstall script : Uninstall operation." elif [ "$1" = "1" ]; then echo "pre-uninstall script : Upgrade uninstallation process." fi %postun if [ "$1" = "0" ] ; then echo "post-uninstall script : Uninstall operation." elif [ "$1" = "1" ]; then echo "post-uninstall script : Upgrade uninstallation process." fi %changelog ||< * 参考資料 RPMの基本 - http://www.rpm.org/ - http://www.rpm.org/wiki/Docs Fedoraからのドキュメント、パッケージングのガイドライン - http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/index.html - http://fedoraproject.org/wiki/Packaging:Guidelines 今回、かなり参考になった記事 - tap dev blog - 自作RPMの作成とレポジトリ3〜specファイルの書き方〜 -- http://dev.tapweb.co.jp/2010/12/273 - RPM を使ってソフトウェアをパッケージ化する: 第 1 回 パッケージのビルドと配布 -- http://www.ibm.com/developerworks/jp/linux/library/l-rpm1/index.html - RPM を使ってソフトウェアをパッケージ化する: 第 2 回 ソフトウェアのアップグレードとアンインストール -- http://www.ibm.com/developerworks/jp/linux/library/l-rpm2/index.html - RPM を使ってソフトウェアをパッケージ化する: 第 3 回 ソフトウェアの依存関係への対処 -- http://www.ibm.com/developerworks/jp/linux/library/l-rpm3/index.html JenkinsなどCI環境と組み合わせる場合に参考になりそうな記事 - Build RPMs for a Git (Github) project with Jenkins | Simply Me -- http://blog.mornati.net/build-rpms-for-a-git-github-project-with-jenkins/ - Build RPMs using Jenkins/Hudson | Simply Me -- http://blog.mornati.net/build-rpms-using-jenkinshudson/ - Jenkinsを用いた継続的RPMビルド - GeekFactory -- http://int128.hatenablog.com/entry/20130111/1357834690 - Using Hudson to build RPM packages - Stack Overflow -- http://stackoverflow.com/questions/2232921/using-hudson-to-build-rpm-packages Rubyなどのライブラリから、RPMパッケージをプログラマブルに生成するライブラリ - Redline RPM -- http://redline-rpm.org/index.html --- Java製のライブラリ - jordansissel/fpm -- https://github.com/jordansissel/fpm --- Ruby製のライブラリで、RPM以外にもdebなど他の形式も対応している。 その他 - .specファイルの%{?hoge:1}とか%{?!hoge:0}について - きれいさっぱり、逝くぜ! -- http://d.hatena.ne.jp/tksmashiw/20080406 - 簡単なRPMの作り方 -- http://ash.jp/linux/rpm_build.htm - 自分で作るRPMパッケージ(2/3) -- http://www.atmarkit.co.jp/flinux/special/mkrpm/mkrpm02.html - rpmbuild - システム管理コマンドの説明 - Linux コマンド集 一覧表 -- http://kazmax.zpp.jp/cmd/r/rpmbuild.8.html #navi_footer|技術|