ソースから自前ビルドしたソフトウエアの効率的な管理方法
ぼくは長年こういう方法で管理してますよ、というお話です。Linuxです。
ディレクトリレイアウト概観
たとえば、asoとbmdという名前のソフトウエアをインストールしている状態はこんな感じ:
/usr/local/ ┬ app/ ┬ aso → aso-1.3
│ ├ aso-1.2/ ┬ bin/ ┬ armored
│ │ │ └ scrum
│ │ ├ sbin/ ─ syd
│ │ └ share/ ─ man/
│ ├ aso-1.3/ ┬ bin/ ┬ armored
│ │ │ └ scrum
│ │ ├ sbin/ ─ syd
│ │ └ share/ ─ man/
│ ├ bmd → bmd-2.0
│ └ bmd-2.0/ ┬ bin/ ─ tri
│ ├ include/ ─ angle.h
│ └ lib/libsnk.so.2.0.0
├ bin/ ┬ armored → ../app/aso/bin/armored
│ ├ scrum → ../app/aso/bin/scrum
│ └ tri → ../app/bmd/bin/tri
├ include/ ─ bmd → ../app/bmd/include
└ sbin/ ─ syd → ../app/aso/sbin/syd
- /usr/local/app/NAME-VERSION の下に一式インストールする
- /usr/local/app/NAME は /usr/local/app/NAME-VERSION への symlink
- /usr/local/app/NAME/bin/* については、/usr/local/bin/ の下に symlink を作る
- /usr/local/app/NAME/sbin/* についても同様、/usr/local/sbin/ の下に symlink を作る
- /usr/local/app/NAME/include については、
- /usr/local/app/NAME/include/*.h のタイプの場合、/usr/local/include/NAME に /usr/local/app/NAME/include への symlink を作る
- /usr/local/app/NAME/include/NAME/*.h のタイプの場合、/usr/local/include/NAME に /usr/local/app/NAME/include/NAME への symlink を作る
- /usr/local/app/NAME/lib については、echo "/usr/local/app/NAME/lib" > /etc/ld.so.conf.d/NAME.conf する (/usr/local/lib/にはsymlinkを張らない)
- /usr/local/app/NAME/share/man については、vi /etc/manpath.configしてMANDATORY_MANPATH /usr/local/app/NAME/share/man を追加する (/usr/local/share/man/にはsymlinkを張らない)
新規にインストールする場合の具体手順
次に具体的な手順。
"neo"という名のソフトウエアを新規にインストールする場合の手順。
tar zxf neo-1.0.tar.gz cd neo-1.0 ./configure --prefix=/usr/local/app/neo-1.0 --sysconfdir=/usr/local/etc/neo make make install ln -snf neo-1.0 /usr/local/app/neo cd /usr/local/bin/ && ln -sf ../app/neo/bin/* . # bin/* があれば cd /usr/local/sbin/ && ln -sf ../app/neo/sbin/* . # sbin/* があれば ln -snf ../app/neo/include /usr/local/include/neo # include があれば echo "/usr/local/app/neo/lib" > /etc/ld.so.conf.d/neo.conf # lib があれば ldconfig vi /etc/manpath.config # share/man があれば "MANDATORY_MANPATH /usr/local/app/NAME/share/man" を追加
後半の symlink 張りとかがめんどくさいですが、一度きりの作業(後述)なので気にしない。
異なるバージョンのをインストールする場合の具体手順
つづいてニューバージョンの neo-1.1 をインストールする場合。このへんからがミソです。
tar zxf neo-1.1.tar.gz cd neo-1.1 ./configure --prefix=/usr/local/app/neo-1.1 --sysconfdir=/usr/local/etc/neo make make install ln -snf neo-1.1 /usr/local/app/neo
基本的に、/usr/local/app/neo の symlink を張り替えるだけで OK。なぜなら、新規のときの bin, sbin, include, lib, man の symlink やパス指定は、全て /usr/local/app/neo-VERISON ではなく /usr/local/app/neo というパスを使っているため。
もし、neo-1.1 でなにか不具合があった場合には、前の neo-1.0 を指す symlink に張り直すだけで切り戻しが完了するのでラクチン。
このような2段階のsymlinkは、Debian系の/etc/alternatives/などでも見られる手法ですね。
$ readlink /usr/bin/vim /etc/alternatives/vim $ readlink /etc/alternatives/vim # ここのsymlinkがつけかわる /usr/bin/vim.gnome $ readlink /usr/bin/vim.gnome # (実体)
あと、他のマシンにも neo-1.1 をインストールする場合、構成が一緒なら、rsync -avR /usr/local/app/neo /usr/local/app/neo-1.1 OTHERHOST:/ で完了するのでラクチン。
つまり、初回インストール時は symlink 張りなどちょいとめんどい(でも一度きり)ですが、バージョンアップ時(こっちは何度かあるはず)には手順が非常に少なくて済む管理手法というわけです。
おまけ
./configure のヘルパースクリプト
configureのオプション指定も、こんなヘルパースクリプトを用意して簡単にしています。
#!/bin/sh # /usr/local/src/conf/generic . /usr/local/src/conf/common decide_version "$@" [ -z "$SYS_HOME" ] && SYS_HOME=/usr/local CONFIGURE_OPT="--sysconfdir=${SYS_HOME}/etc/${APP}" [ "$1" = "-0" ] && CONFIGURE_OPT= myconfigure \ --prefix=/usr/local/app/${APP}-${VER} \ $CONFIGURE_OPT \ ;
# -*- mode: sh; -*- # /usr/local/src/conf/common #_CFLAGS='-march=pentium3 -O3 -pipe -fomit-frame-pointer' _CFLAGS='-O2 -pipe -fomit-frame-pointer' myconfigure() { { echo env CFLAGS="${_CFLAGS}" ./configure "$@"; echo env CFLAGS="${_CFLAGS}" ./configure "$@"; } 2>&1|tee _configure.log } debugconfigure() { { echo env CFLAGS="-O0 -g" ./configure "$@"; echo env CFLAGS="-O0 -g" ./configure "$@"; } 2>&1|tee _configure.log } decide_version() { VER=${PWD##*-} APP=${PWD##*/}; APP=${APP%%-*} case $VER in [0-9]*) ;; *) VER=;; esac case $1 in [0-9]*) VER=$1 shift ;; esac if [ -z "$VER" ]; then echo -n "input version string> " read VER fi echo "APP=$APP" echo "VER=$VER" read -t 8 -p 'hit any key' dummy }
$ cd neo-1.2 $ /usr/local/src/conf/generic --prefix=/usr/local/app/nao-1.2 # よきにはからってくれる --sysconfdir=/usr/local/etc/neo hit any key ...(snip)... $ make
固有のオプションをいろいろ指定したいときは、conf/generic を conf/nginx とかにコピーしてもろもろ指定してます。
#!/bin/sh
# /usr/local/src/conf/nginx
. /usr/local/src/conf/common
decide_version "$@"
[ -z "$SYS_HOME" ] && SYS_HOME=/usr/local
myconfigure \
--prefix=/usr/local/app/nginx-${VER} \
--conf-path=$SYS_HOME/etc/nginx/nginx.conf \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/run/nginx/nginx.lock \
--error-log-path=/var/log/nginx/default.err \
--http-log-path=/var/log/nginx/default.acc \
--http-client-body-temp-path=/var/tmp/nginx/req \
--http-proxy-temp-path=/var/tmp/nginx/proxy \
--http-fastcgi-temp-path=/var/tmp/nginx/fastcgi \
--without-mail_pop3_module \
--without-mail_imap_module \
--without-mail_smtp_module \
--with-md5-asm \
--with-sha1-asm \
--with-http_stub_status_module \
--with-http_realip_module \
;
なんでソースを自前ビルドするの? ディストリのバイナリパッケージ使わないの?
バイナリパッケージはバリバリ使っていて、むしろ、ソースから自前ビルドはごく少数です。
自分が自前ビルドする判断基準はこうです:
- 先っちょを追っかけたい
- ディストリ付属のは往々にしてちょっと古かったりするので
- configureのオプションを把握しておきたい、好きなように指定したい
- ApacheとかNginxとかですね。不要なものは積極的に--without-*の刑。
具体的にはあまりなくて、HTTPサーバ (Apache, Nginx, Lighttpd)、PHP、memcached、Tokyo Cabinetとライブラリ系のものがいくつかぐらいです。