ソースから自前ビルドしたソフトウエアの効率的な管理方法
ぼくは長年こういう方法で管理してますよ、というお話です。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とライブラリ系のものがいくつかぐらいです。