「パッケージングポリシーとか面倒臭いんじゃ社内用にちょっとしたファイルを所定のパスに配置するのに使いたいだけなんじゃ」という人のために。
「hello, world」を出力するhelloプログラムを/usr/local/bin/に配置する簡単な例を作ってみます。
$ uname -srm
Linux 6.5.0-25-generic x86_64
$ lsb_release -sd
Ubuntu 22.04.4 LTS
本文
パッケージング対象
これらをパッケージにしていきます(hello.cは割愛)。
Makefileの$(DESTDIR)
変数は以下を参考にしています。
$ tree
.
├── Makefile
└── hello.c
BINARY := hello
.PHONY: all install clean rpm
all: $(BINARY)
install: $(BINARY)
install -d $(DESTDIR)/usr/local/bin/
install -m 0755 hello $(DESTDIR)/usr/local/bin/hello
clean:
$(RM) $(BINARY)
この時点ではmake
・make install
すると/usr/local/bin/にhelloの実行ファイルがインストールされるだけです。
$ make
cc hello.c -o hello
$ sudo make install
install -d /usr/local/bin/
install -m 0755 hello /usr/local/bin/hello
$ hello
hello, world
rpmターゲット
Ubuntuでrpmを作成するにはrpmパッケージが必要なのでまずはインストールします。
$ sudo apt update && sudo apt install rpm
rpmを作成出来る様に変更を加えます。
.
├── Makefile
├── hello.c
└── hello.spec
BINARY := hello
.PHONY: all install clean rpm
all: $(BINARY)
install: $(BINARY)
install -d $(DESTDIR)/usr/local/bin/
install -m 0755 hello $(DESTDIR)/usr/local/bin/hello
clean:
$(RM) $(BINARY)
rpm: $(BINARY)
make install DESTDIR=${PWD}/root
rpmbuild --bb --buildroot ${PWD}/root \
--define "%_topdir ${PWD}" \
--define "%_builddir ${PWD}" \
--define "%_buildrootdir ${PWD}/root" \
--define "%_rpmdir ${PWD}/rpm" \
--define "%_srcrpmdir ${PWD}/rpm" \
hello.spec
rm -rf root
Summary: hello world program
Name: hello
Version: 1.0
Release: 0
License: MIT
Packager: liqsuq <liqsuq@example.com>
%description
hello world program
%files
/usr/local/bin/hello
specファイルの各項目については以下を参照してください。
rpmではデフォルトでは~/rpmbuild/内にいくつかのディレクトリが作成されそこでビルドされるのですが、今回の様にMakefileでソースツリー内で作業するのには向いていません。なので内部変数をいじり、ソースツリー内に作業を行う様にしています。
またポイントとして、rpmターゲット内でinstallターゲットを呼び、ソースツリー内のrootディレクトリにインストールを行いこのディレクトリを元にrpm作成を行っています。rpmビルドではspecファイルにbuildセクションがあり、それを使うことも出来るのですが後述のdebターゲットと処理を共通化するために敢えてこうしています。
この状態でmake rpm
を行うと計算機のアーキテクチャに合わせたrpmファイルが作成されます。
$ make rpm
:
$ tree
.
├── Makefile
├── hello
├── hello.c
├── hello.spec
└── rpm
└── x86_64
└── hello-1.0-0.x86_64.rpm
specファイルにBuildArch: noarchを追加すると〜.noarch.rpmと付くアーキテクチャに依存しないパッケージが作成されます。シェルスクリプトや設定ファイル等に便利でしょう。
debターゲット
debを作成出来る様に変更を加えます。
以下のtree出力中のdeb
はディレクトリです。dpkg-debの引数解釈の都合、ディレクトリが無いとパッケージファイル名と認識されてしますので予め作成しておきます。
$ tree
.
├── DEBIAN
│ └── control
├── Makefile
├── deb
├── hello.c
└── hello.spec
BINARY := hello
.PHONY: all install clean rpm deb
all: $(BINARY)
install: $(BINARY)
install -d $(DESTDIR)/usr/local/bin/
install -m 0755 hello $(DESTDIR)/usr/local/bin/hello
clean:
$(RM) $(BINARY)
rpm: $(BINARY)
make install DESTDIR=${PWD}/root
rpmbuild --bb --buildroot ${PWD}/root \
--define "%_topdir ${PWD}" \
--define "%_builddir ${PWD}" \
--define "%_buildrootdir ${PWD}/root" \
--define "%_rpmdir ${PWD}/rpm" \
--define "%_srcrpmdir ${PWD}/rpm" \
hello.spec
rm -rf root
deb: $(BINARY)
make install DESTDIR=${PWD}/root
cp -r DEBIAN root/
fakeroot dpkg-deb --build root deb
rm -rf root
Package: hello
Maintainer: liqsuq <liqsuq@example.com>
Architecture: amd64
Version: 1.0-0
Description: hello world program
こちらではrootディレクトリにインストールした後にDEBIANディレクトリをコピーしてdebの作成を行っています。DEBIANディレクトリをコピーする理由や各項目の説明は以下を参照してください。
この状態でmake deb
を行うとDEBIAN/controlのArchtecture:
に対応するdebファイルが作成されます。
$ make deb
:
$ tree
.
├── DEBIAN
│ └── control
├── Makefile
├── deb
│ └── hello_1.0-0_amd64.deb
├── hello
├── hello.c
└── hello.spec
debではDEBIAN/controlにArchtecture: all
と記述するとアーキテクチャに依存しないパッケージが作成されます。
ソースツリー
最終的なソースツリー及びMakefileは以下の様になります。
$ tree
.
├── DEBIAN
│ └── control
├── Makefile
├── deb
├── hello.c
└── hello.spec
BINARY := hello
.PHONY: all install clean rpm deb
all: $(BINARY)
install: $(BINARY)
install -d $(DESTDIR)/usr/local/bin/
install -m 0755 hello $(DESTDIR)/usr/local/bin/hello
clean:
$(RM) $(BINARY)
rpm: $(BINARY)
make install DESTDIR=${PWD}/root
rpmbuild --bb --buildroot ${PWD}/root \
--define "%_topdir ${PWD}" \
--define "%_builddir ${PWD}" \
--define "%_buildrootdir ${PWD}/root" \
--define "%_rpmdir ${PWD}/rpm" \
--define "%_srcrpmdir ${PWD}/rpm" \
hello.spec
rm -rf root
deb: $(BINARY)
make install DESTDIR=${PWD}/root
cp -r DEBIAN root/
fakeroot dpkg-deb --build root deb
rm -rf root
結び
後は必要に応じて依存関係やプリ/ポストスクリプトを記述してみてください。
debでアーキテクチャを決め打ちせずビルド中に自動判定するとかソースパッケージを作りたいとかがしたい場合には各パッケージングガイドを読んでみてください。自分は諦めました。特にdeb。
// ビルド中にDebianポリシーに違反していないか等のチェックが走るため軽率に使えない