%% -*- coding: utf-8-unix -*-
%#!platex lms201107r-js
% %% && xdvi -watchfile 0.5 -xoffset -1 -yoffset -3.4 -geometry 980x1200-200+0
%% && xdvi -watchfile 0.5 -xoffset 1 -yoffset -1 -geometry 980x1200-200+0
% #LPR dvipdfmx -p a4 -x 0in -y 0in %s && acroread lms201107r.pdf
%#LPR dvipdfmx -p a4 %s && acroread lms201107r-js.pdf
\newif\ifHyperref
\Hyperreftrue
% \Hyperreffalse
%%\documentclass[mentuke,cameraready]{vlart}%mentuke, %Proof,tombo, grayscale
\documentclass{jsarticle}
%%
\usepackage{graphicx}
\usepackage{color}
\definecolor{Xgray}{gray}{0.9}% 10%
\makeatletter
\let\subtitle\@gobble
\let\vlversion\@gobble
\let\decotype\@gobble
\makeatother
%%
\usepackage{mathpazo}
\usepackage{listings,jlisting}%
%%\usepackage{vlart-cameraready}
\title{RPMパッケージ作成ハンズオン\hskip1zw 入門編}
\subtitle{\xkanjiskip.5\xkanjiskip
LILO 2011.07 Monthly Seminar,第6回Vine Linuxユーザの集い}
\author{山本\hskip1zw 宗宏 {\ttfamily }}
\date{2011年7月17日@株式会社グッデイ}
\vlversion{6.0}%
\decotype{B}%
%%
\def\ddash{\hbox to 1.5zw{---\hss ---}}% \let\doubledash\ddash
\def\lstlistingname{リスト}
\lstset{language=bash,%
basicstyle=\small\ttfamily,%
commentstyle=\textsl,%\textit
classoffset=1,%
keywordstyle=\bfseries,%
xrightmargin=2zw,%.5zw
xleftmargin=2zw,%.5zw
numbersep=1zw,%
frame=trbl,framesep=.5zw,%
backgroundcolor=\color{Xgray},
showstringspaces=false,%
breaklines=true,%default: false
breakindent=20pt,%20pt
numbers=left,stepnumber=1,numberstyle=\scriptsize\itshape%
}%
\ifHyperref
\ifnum 42146=\euc"A4A2 %"
\AtBeginDvi{\special{pdf:tounicode EUC-UCS2}}%
\else
\AtBeginDvi{\special{pdf:tounicode 90ms-RKSJ-UCS2}}%
\fi
\usepackage[%
dvipdfmx,%
pdfstartview={FitH -32768},% 描画領域の幅に合わせる[default は全体表示]
bookmarks=true,% しおり付き[default は false]
%%!! bookmarksnumbered=true,% 章や節の番号をふる[default は false]
bookmarkstype=toc,% 目次情報のファイル[拡張子 toc]を参照
colorlinks=false,% ハイパーリンクを色文字ではなく色枠に[default]
linkbordercolor={0 0 1},% link の枠の色 aqua [default は red {1 0 0}]
citebordercolor={0 1 0},% cite の枠の色 lime [default]
urlbordercolor={0 0 1}% url の枠の色 blue [default]
]{hyperref}
\fi
%%
\begin{document}
\maketitle
\begin{abstract}
RPMパッケージになっていないサンプルソフトウェアを通して,
RPMパッケージの作成を体験するセミナーです.
入門編では,RPMパッケージ作成に関わる
パッケージのビルドやテスト,
vbuilderを使ったsrc.rpmのビルドテストなどの一連の作業を学べます.
\end{abstract}
\section*{入門編の流れ}
入門編の進行は,スライドにそって解説しながら1つ1つ作業をしました.
以下のスライドのpdfも合わせてご参考下さい.
{\ttfamily http://trac.vinelinux.org/repos/people/munepi/documents/11/lms201107b.pdf}
\begin{enumerate}
\item
準備
\item
サンプルソフトウェアのコンパイル
\item
雛形specファイルの編集
\item
パッケージのビルド
\item
パッケージのインストール,アンインストール
\item
パッケージのビルドテスト
\end{enumerate}
\section{準備}
手元にVine Linux~5またはVine Linux~6が
インストールされた計算機を用意して下さい.
このレジュメでは,Vine Linux~6 i686を前提として解説しています.
もしppc, x86\_64を用意している方は,
適時読み替えてコマンドを実行して下さい.
\subsection{\~{}/.rpmmacrosの編集}
RPMパッケージを作成するための最低限の設定をしましょう.
適当なテキストエディタを用いて,
{\ttfamily \~{}/.rpmmacros}を開いて下さい.
\subsubsection*{Vine Linux 6}
\begin{lstlisting}
# %packager Your Name
# %packager Munehiro Yamamoto
%packager munepi
# GnuPG によるパッケージ署名を行う
# %_signature gpg
# %_gpg_name Your Name
# ソースファイル置き場をパッケージ別にする
%_sourcedir %{_topdir}/SOURCES/%{name}
\end{lstlisting}
\subsubsection*{Vine Linux 5}
\begin{lstlisting}
%_topdir ${HOME}/rpm
# %packager Your Name
# %packager Munehiro Yamamoto
%packager munepi
# gpg signing
# %_signature gpg
# %_gpg_name Your Name
# more useful macros
%_sourcedir %{_topdir}/SOURCES/%{name}
\end{lstlisting}
\begin{itemize}
\item
{\ttfamily \%packager}:
あなたのID(半角英数字の文字列)を入力して下さい.
あなたのハンドルネームやニックネームで構いません.
特に,そのようなIDをお持ちでない方や分からない方は,
上記の例を参考に,名前とメールアドレスを入力して下さい.
\item
今回は作成していただいたRPMパッケージにGPG署名をしません.
\item
{\ttfamily \%\_sourcedir \%\{\_topdir\}/SOURCES/\%\{name\}}:
パッケージごとにソースやパッチなどの格納ディレクトリを設けます.
パッケージごとにディレクトリを分けておくと,
複数のパッケージをメンテナンスするときに,
それぞれのファイルたちが混ざりません.
デフォルトでは,
{\ttfamily \%\_sourcedir \%\{\_topdir\}/SOURCES}となっています.
\end{itemize}
\subsection{sudoの設定}
{\sffamily sudo}は
一般ユーザに特定のコマンドをroot権限で実行させるためのコマンドです.
{\sffamily su}コマンドからrootになってもよいのですが,
今回は積極的に{\sffamily sudo}を使います.
\subsubsection*{Vine Linux 6}
あなたはおそらく手元の計算機の管理者です.
念のために,{\sffamily id}コマンドを実行して,
wheelグループに所属しているか確認して下さい.
\begin{lstlisting}
$ id
uid=1000(munepi) gid=1000(munepi) groups=1000(munepi),10(wheel)
\end{lstlisting}%$
\subsubsection*{Vine Linux 5}
あなたはおそらく手元の計算機の管理者です.
{\sffamily sudo}をインストールします.
\begin{lstlisting}
$ su -c "apt-get install sudo"
\end{lstlisting}%$
あなたのアカウントをsudoersに追加しましょう.
\begin{lstlisting}
$ su -c /usr/sbin/visudo
\end{lstlisting}%$
{\sffamily vi}の操作に不馴れな方は,
環境変数{\ttfamily EDITOR}に{\sffamily gedit}などの
使いなれたテキストエディタを代入して,以下を実行して下さい.
\begin{lstlisting}
$ EDITOR=gedit su -c /usr/sbin/visudo
\end{lstlisting}%$
以下の例を参考にしながら,
``{\ttfamily \#\# Allow root to run any commands anywhere}''
と書かれた行の下に,自分のアカウントを追加して保存します.
\begin{lstlisting}
## Allow root to run any commands anywhere
root ALL=(ALL) ALL
munepi ALL=(ALL) ALL
\end{lstlisting}
\section{パッケージングしてみよう}
\subsection{サンプルを動かす}
今回のRPMパッケージハンズオンのために,
echowlvlというサンプルソフトウェアを用意しました.
このサンプルソフトウェアをRPMパッケージにしてみましょう.
\subsubsection{サンプルをダウンロード}
{\sffamily wget}コマンドを用いて,
echowlvl-0.1.tar.gzをダウンロードします.
\begin{lstlisting}
$ wget http://trac.vinelinux.org/repos/people/munepi/documents/11/echowlvl-0.1.tar.gz
\end{lstlisting}%$
\subsubsection{サンプルをコンパイル}
ソフトウェアをビルドするための最小限の開発環境を整えます.
\begin{lstlisting}
$ sudo apt-get install build-essential
\end{lstlisting}%$
先ほどダウンロードしたサンプル
echowlvl-0.1.tar.gzを展開して,
``いつもの呪文''%
({\ttfamily ./configure \&\& make \&\& make install}のこと)を
唱えてみましょう.
\begin{lstlisting}
$ tar xvf echowlvl-0.1.tar.gz
$ cd echowlvl-0.1
$ ./configure
$ make
$ ./echowlvl
\end{lstlisting}%$
コンパイルしてできた実行ファイル{\sffamily echowlvl}を実行すると,
どうなったでしょうか?\hskip.5zw
みなさんで一斉に叫んでみましょう!
\subsection{specファイルを書く}
{\sffamily echowlvl}が ``いつもの呪文'' を唱えてビルドできたので,
RPMパッケージを作成するための
ソースコードともいうべきspecファイルを書きましょう.
\subsubsection{雛形specファイルのダウンロード}
echowlvlのRPMパッケージ作成にすぐさまとりかかれるように,
specファイルの雛形を用意しました.
{\sffamily wget}コマンドを用いて,
echowlvl-vl.specをダウンロードして下さい.
\begin{lstlisting}
$ wget http://trac.vinelinux.org/repos/people/munepi/documents/11/echowlvl-vl.spec
\end{lstlisting}%$
ダウンロードしたechowlvl-vl.specを{\ttfamily \~{}/rpm/SPECS/}へ移動します.
\begin{lstlisting}
$ mv echowlvl-vl.spec ~/rpm/SPECS/
\end{lstlisting}%$
\subsubsection{specファイルの構成}
specファイルは主に4つの部分から構成されています.
\begin{enumerate}
\item
パッケージ情報
\item
スクリプト
\item
ファイルリスト
\item
更新履歴
\end{enumerate}
各部を順番に見ながら埋めていきましょう.
\paragraph{パッケージ情報}
パッケージの基本情報はすべてここに凝縮されています.
特にパッケージ依存関係は,
{\sffamily rpm}や{\sffamily apt}に正しい情報を伝えるために重要になります.
\begin{lstlisting}
## -*- coding: utf-8-unix -*-
## This is a template spec file for LILO 2011.07 Monthly Seminar.
Name: echowlvl
Version: 0.1
Release: 1%{?_dist_release}
Summary: Sample program for RPM making hands-on (lms201107)
Summary(ja): RPM パッケージ作成ハンズオン (lms201107) 用サンプルプログラム
Group: Applications/Other
License: GPLv3+
URL: http://trac.vinelinux.org/wiki/OfflineMeeting/20110711
Source0: http://trac.vinelinux.org/repos/people/munepi/documents/11/%{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
Distribution: YOUR LINUX DISTRIBUTION
Vendor: YOUR VENDOR
Packager: YOUR NAME (or YOUR ID)
%description
echowlvl is a sample program for RPM making hands-on (lms201107).
%description -l ja
echowlvlは RPM パッケージ作成ハンズオン (lms201107) 用サンプルプログラムです.
\end{lstlisting}
\begin{itemize}
\item
{\ttfamily Name}:
パッケージ名です.
{\ttfamily \%\{name\}}というマクロで参照できます.
今回は,{\ttfamily echowlvl}として下さい.
\item
{\ttfamily Version}:
ソフトウェアのバージョンです.
{\ttfamily \%\{version\}}というマクロで参照できます.
今回は,{\ttfamily 0.1}としてください.
\item
{\ttfamily Release}:
リリース番号とVine Linuxのバージョンを組み合せて書きます.
リリース番号は,同じバージョンで何回目のリリースになるかを意味します.
{\ttfamily \%\{?\_dist\_release\}}は,
Vine Linuxのバージョンに置き換えられます.
例えば,Vine Linux~6の場合は,
{\ttfamily 1\%\{?\_dist\_release\}}は{\ttfamily 1vl6}となります.
{\ttfamily \%\{release\}}というマクロで参照できます.
\item
{\ttfamily Summary}, {\ttfamily Summary(ja)}:
パッケージの概要です.
パッケージの概要をそれぞれ英語と日本語で記入して下さい.
\item
{\ttfamily Group}:
ソフトウェアの種類です.
今回は{\ttfamily Applications/Other}にします.
\item
{\ttfamily License}:
ソフトウェアのライセンスです.
今回は{\ttfamily GPLv3+}にします.
\item
{\ttfamily \%description}, {\ttfamily \%description -l ja}:
{\ttfamily Summary}よりも詳しいパッケージの解説を書きます.
\end{itemize}
\paragraph{スクリプト}
ソフトウェアのソースアーカイブを展開し,必要であればパッチを当て,
コンパイル,インストールの一連の作業を記述します.
\begin{lstlisting}
%prep
%setup -q
%build
%configure
%__make %{?_smp_mflags}
%install
%__rm -rf $RPM_BUILD_ROOT
%__make install DESTDIR=$RPM_BUILD_ROOT
%clean
%__rm -rf $RPM_BUILD_ROOT
\end{lstlisting}
``いつもの呪文'' をざっくりspecファイルに記述すると,
このようになります.
echowlvlのrpm化はこれで十分なので,今回はこのままにしておきます.
\paragraph{ファイルリスト}
実際にインストールされるファイルリストを書きます.
\begin{lstlisting}
%files
%defattr(-,root,root,-)
\end{lstlisting}
さて,何を書けばよいのでしょう?\hskip.5zw
一旦,保留にしておきます.
\paragraph{更新履歴}
更新履歴は,パッケージのメンテナだけでなく,
パッケージに興味のある人が見るかもしれません.
他の人が見てよいように,
できるだけ分かりやすく記述するように心掛けましょう.
あなたの名前とメールアドレスを埋めて下さい.
\begin{lstlisting}
%changelog
* Sun Jul 17 2011 YOUR NAME 0.1-1
- first release
## end of file
\end{lstlisting}
\subsection{パッケージのビルド}
さきほどダウンロードしたechowlvl-0.1.tar.gzを
{\ttfamily \~{}/rpm/SOURCES/echowlvl}に移します.
\begin{lstlisting}
$ mkdir ~/rpm/SOURCES/echowlvl
$ mv echowlvl-0.1.tar.gz ~/rpm/SOURCES/echowlvl/
\end{lstlisting}
では,{\sffamily rpmbuild -ba}でパッケージをビルドしてみます.
\begin{lstlisting}
$ rpmbuild -ba ~/rpm/SPECS/echowlvl-vl.spec
\end{lstlisting}%$
そういえば,
{\ttfamily \%files}のファイルリストを埋めていませんでした.
早速,/usr/bin/echowlvlをファイルリストに追加しましょう.
\begin{lstlisting}
%files
%defattr(-,root,root,-)
%doc AUTHORS COPYING ChangeLog INSTALL NEWS README
%{_bindir}/echowlvl
\end{lstlisting}
{\ttfamily \%doc}に入れたドキュメントファイルは,
{\ttfamily /usr/share/doc/\%\{name\}-\%\{version\}}に格納されます.
再び,{\sffamily rpmbuild -ba}でechowlvlパッケージをビルドして下さい.
今度はechowlvlパッケージができあがっていませんか?
\subsection{パッケージのインストール}
echowlvlパッケージができたら,インストールをします.
echowlvlパッケージが期待した通りにインストールできて,
動作することを確認します.
\begin{lstlisting}
$ sudo apt-get install ~/rpm/RPMS/i686/echowlvl-0.1-1vl6.i686.rpm
\end{lstlisting}%$
{\sffamily echowlvl}コマンドを実行して動作確認をしましょう.
先ほどを同じ挙動をしているでしょうか?
\subsection{パッケージのアンインストール}
今度は,echowlvlパッケージをアンインストールしてみます.
\begin{lstlisting}
$ sudo apt-get remove echowlvl
\end{lstlisting}%$
{\sffamily echowlvl}コマンドを実行できてしまったりしないか,
確認してみましょう.
\begin{lstlisting}
$ echowlvl
bash: echowlvl: コマンドが見つかりません
$ which echowlvl
/usr/bin/which: no echowlvl in (/home/munepi/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin)
\end{lstlisting}
\section{さらにパッケージングしてみよう}
\subsection{サンプルが更新されたようです!}
{\sffamily wget}コマンドを用いて,
echowlvl-0.2.tar.gzをダウンロードして下さい.
\begin{lstlisting}
$ wget http://trac.vinelinux.org/repos/people/munepi/documents/11/echowlvl-0.2.tar.gz
\end{lstlisting}%$
新しくなったechowlvlをコンパイルして,
動作することを確認して下さい.
\subsubsection{ビルドに必要なライブラリを追加}
もしechowlvlをコンパイルできなかった方は,
エラーメッセージを見ながら,原因を追究してみましょう.
今回は,curses.hというヘッダファイルがコンパイルに必要だったようです.
/usr/include/curses.hは,
ncurces-develパッケージに格納されています.
{\sffamily apt-get}を使ってncurses-develパッケージをインストールします.
\begin{lstlisting}
$ sudo apt-get install ncurses-devel
\end{lstlisting}%$
\subsubsection{specファイルを更新}
echowlvlの新しいバージョンに合わせて,
echowlvl-vl.specを編集しましょう.
{\ttfamily Version}はバージョンを{\ttfamily 0.2}にして下さい.
{\ttfamily \%changelog}に
ソフトウェアが更新されたことを記します.
\begin{lstlisting}
## -*- coding: utf-8-unix -*-
## This is a template spec file for LILO 2011.07 Monthly Seminar.
Name: echowlvl
Version: 0.2
Release: 1%{?_dist_release}
...
%changelog
* Sun Jul 17 2011 YOUR NAME 0.2-1
- new upstream release
* Sun Jul 17 2011 YOUR NAME 0.1-1
- first release
## end of file
\end{lstlisting}
\subsubsection{パッケージを更新}
{\sffamily rpmbuild -ba}でパッケージのビルドを試みて下さい.
新しいバージョンに対応したechowlvlパッケージはできましたでしょうか?
echowlvlパッケージができた場合は,
パッケージのインストール,テスト,アンインストールもお忘れなく!
\section{ビルドテストしましょう}
パッケージができたら,パッケージのビルドテストをしましょう.
いつでもどんな環境でもパッケージングできた方が嬉しいですよね.
%「あの人の環境ではビルドできるけど,私の環境ではビルドできないよ?」,
「あの人の環境ではビルドできるけど,私の環境ではビルドできひんよ?」,
%「私の環境でもビルドできたけど,この機能が使えないよ?」
「私の環境でもビルドできたけど,この機能が使えへんよ?」
といったことが起こると不都合ですよね.
パッケージのビルドテストには,{\sffamily vbuilder}を使います.
{\sffamily vbuilder}は,
(chrootという)子環境に
Vine Linuxの最小環境から構築し,
パッケージの依存関係などのチェックをしてから
パッケージのビルドするツールです.
vbootstrap, vbuilderに関する詳細は,以下のURLに記載されています.
{\ttfamily http://trac.vinelinux.org/wiki/VineBootstrap}
\subsection{vbuilderの基本操作}
{\sffamily vbuilder}はvbootstrapパッケージに格納されています.
\begin{lstlisting}
$ sudo apt-get install vbootstrap
\end{lstlisting}%$
基本的な流れは以下の通りです.
\begin{enumerate}
\item
必要があれば,過去に構築した子環境を削除
\begin{lstlisting}
$ sudo vbuilder clean
\end{lstlisting}%$
\item
子環境に最小環境を構築
\begin{lstlisting}
$ sudo vbuilder build
\end{lstlisting}%$
\item
子環境上でsrc.rpmをビルド
\begin{lstlisting}
$ sudo vbuilder build-rpm hoge-1.0-1vl6.src.rpm
\end{lstlisting}%$
\end{enumerate}
vbuilderにこれらのアクションを一度に渡すこともできて,
以下のようにすれば,
順次 clean → build → build-rpm のように実行します.
\begin{lstlisting}
$ sudo vbuilder clean build build-rpm hoge-1.0-1vl6.src.rpm
\end{lstlisting}%$
この場合,buildを省略できます.
\begin{lstlisting}
$ sudo vbuilder clean build-rpm hoge-1.0-1vl6.src.rpm
\end{lstlisting}%$
なお,{\ttfamily \$ sudo vbuilder clean build}を実行すると,
デフォルトで/var/local/vbootstrap/6.0\_i386が
約600\,MB程度の容量を消費します.
{\sffamily vbuilder}を実行する際には,
ハードディスクの容量にご注意下さい.
\subsection{src.rpmをvbuilderに投げてみる}
echowlvl-0.2-1vl6.i686.rpmといっしょに,
もう1つechowlvl-0.2-1vl6.src.rpmというrpmができていました.
src.rpmは,
ソフトウェアのソースアーカイブやパッチファイルなど,
specファイルをまとめたソースパッケージです.
echowlvl-0.2-1vl6.src.rpmからechowlvl-0.2-1vl6.i686.rpmを
ビルドできます.
{\sffamily vbuilder}にechowlvl-0.2-1vl6.src.rpmを投げてみましょう.
一度{\sffamily vbuilder}を実行すると,
一連の作業が終わるまでしばらくかかります.
果たして{\sffamily vbuilder}は
echowlvl-0.2-1vl6.i686.rpmを返してくれるでしょうか?
\begin{lstlisting}
$ sudo vbuilder clean build-rpm ~/rpm/SRPMS/echowlvl-0.2-1vl6.src.rpm
\end{lstlisting}%$
\subsection{依存関係を解決する}
{\sffamily vbuilder}にechowlvl-0.2-1vl6.src.rpmを投げたら,
``curses.hがありません'' と言われてしまいました.
echowlvl-0.2-1vl6.src.rpmはソースパッケージとして不完全のようです.
/usr/include/curses.hはncurses-develパッケージに格納されています.
ncurses-develパッケージを事前にインストールしていると,
echowlvl-0.2-1vl6.src.rpmがビルドできそうです.
早速,試してみましょう.
さきほど{\sffamily vbuilder}で作った子環境上に
ncurses-develパッケージをインストールします.
\begin{lstlisting}
$ sudo vbuilder install-rpm ncurses-devel
\end{lstlisting}%$
再び,{\sffamily vbuilder}にechowlvl-0.2-1vl6.src.rpmを投げてみます.
echowlvl-0.2-1vl6.i686.rpmを返してくれるでしょうか?
\begin{lstlisting}
$ sudo vbuilder build-rpm ~/rpm/SRPMS/echowlvl-0.2-1vl6.src.rpm
\end{lstlisting}%$
\subsubsection{specファイルを更新}
echowlvl-vl.specを編集しましょう.
{\ttfamily Release}はリリース番号を{\ttfamily 2}にして下さい.
{\ttfamily BuildRequires: ncurses-devel}を追加します.
{\ttfamily \%changelog}に
{\ttfamily BuildRequires: ncurses-devel}を追加したことを記します.
\begin{lstlisting}
## -*- coding: utf-8-unix -*-
## This is a template spec file for LILO 2011.07 Monthly Seminar.
Name: echowlvl
Version: 0.2
Release: 2%{?_dist_release}
...
Source0: http://trac.vinelinux.org/repos/people/munepi/documents/11/%{name}-%{version}.tar.gz
BuildRequires: ncurses-devel
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
...
%changelog
* Sun Jul 17 2011 YOUR NAME 0.2-2
- added BuildRequires: ncurses-devel
* Sun Jul 17 2011 YOUR NAME 0.2-1
- new upstream release
* Sun Jul 17 2011 YOUR NAME 0.1-1
- first release
## end of file
\end{lstlisting}
\subsubsection{パッケージのビルドテスト}
再び,{\sffamily rpmbuild -ba}でechowlvlパッケージをビルドして下さい.
echowlvl-0.2-2vl6.i686.rpm, echowlvl-0.2-2vl6.src.rpmが生成されるはずです.
今度は,{\sffamily vbuilder}にechowlvl-0.2-2vl6.src.rpmを投げてみましょう.
一旦,{\sffamily vbuilder clean}で小環境を削除します.
{\sffamily vbuilder build-rpm}で小環境を再構築し,
echowlvl-0.2-2vl6.src.rpmをビルドします.
echowlvl-0.2-2vl6.i686.rpmを返してくれたら,
パッケージのビルドテストに成功です.
\begin{lstlisting}
$ sudo vbuilder clean build-rpm ~/rpm/SRPMS/echowlvl-0.2-2vl6.src.rpm
\end{lstlisting}%$
{\sffamily vbuilder}が返してくれたechowlvl-0.2-2vl6.i686.rpmの
パッケージをテストして下さい.
パッケージのインストール,動作確認,アンインストールに問題なければ,
入門編は終了です.お疲れ様でした.
%\appendix
%\section{{\sffamily rpmbuild}コマンドのヘルプ}
%
%\section{vbuilderコマンドのヘルプ}
\end{document}