masato: 2006年2月アーカイブ

/usr/opt/pkgs/foo-1.0.0/lib/libfoo.so.1
/usr/opt/pkgs/foo-1.0.1/lib/libfoo.so.1
/usr/opt/foo => /usr/opt/pkgs/foo-1.0.1

だったものを

/usr/opt/pkgs/foo-1.0.0/lib/libfoo.so.1
/usr/opt/pkgs/foo-1.0.1/lib/libfoo.so.1
/usr/opt/foo => /usr/opt/pkgs/foo-1.0.0

に変えたとかいう場合はどうでしょうか?

どのライブラリをロードするのかはライブラリのサーチパスに依存します。システムのサーチパスは ld.so.conf で設定しますが、これは環境変数の LIBRARY_PATH でも変更可能です。絶対パスでリンクされるのは /lib/ld.so のみ(linux の場合は /lib/ld-linux.so)です。/lib/ld.so が実行時にライブラリのサーチパスを検索してロードするライブラリを決定します。

例えばサーチパスが

/opt/foo/lib
/opt/pkg/foo-1.0.0/lib
/opt/pkg/foo-1.0.1/lib

の場合は、/opt/foo/lib/libfoo.so.1 がリンクされます。

メジャーバージョンが同じパッケージが複数存在する場合の切り替えは、残念ながらちょっと分かりません。
libfoo.so.x ではなく libfoo.so.x.y.z にリンクできれば可能なんでしょうけど。

ELFの思想的にはメジャーバージョンが同じ場合は後方互換性が保たれるので、問題がおきることはありません。
もし新しいバージョンで問題が起きた場合は、新しいバージョンのライブラリを削除してやれば自動的に古いバージョンのライブラリがロードされるので、問題なく実行されます。既に新しいバージョンのライブラリにリンクしているプログラムがあって、そのプログラムが新しいバージョンの後方互換のない機能を使っていれば失敗します。その場合は新しくコンパイルしなおすか、問題のあるバージョンのライブラリを使うことになるのですが、そのようなケースはまれですね。

メジャーバージョンが異なる場合は、問題なく共存できます。
例えば

/opt/pkgs/foo-1.0.0/lib/libfoo.so.1
/opt/pkgs/foo-2.0.0/lib/libfoo.so.2
/opt/foo => /opt/pkgs/foo-2.0.0

であっても /opt/pkgs/foo-1.0.0/lib をちゃんとライブラリのサーチパスに登録しておけば、libfoo.so.1 にリンクしているプログラムは問題なく実行できるわけです。

折り見てこのネタいただこうと思います(苦笑

僕もELFさんのPHPインストールスクリプト参考にして、自分用の作りましたw

個人的にいはalternativesとかでこの辺もできたら面白いんだけど.

リンクするライブラリはコンパイル時に決定するものなので、切り替えるとしたらヘッダファイルでしょうね。

またまたELFさんとこからTBをもらいました。
ありがとうございます。

続: includeとlibはワイルドカード指定はよくないのでは?

シンボリックリンクにしなかったのはhttpd.confを修正したくなかったから(趣味の問題ですね

僕も極力オリジナルのファイルは修正しないようにしてます。なので別ファイルに

<Directory "/var/www/cgi-bin">
Options FollowSymLinks
</Directory>

と書いてます。

パーティションが同じなら cp ではなくてハードリンクでもいいと思います。ハードリンクならバイナリが書き換えられても大丈夫だし、設定ファイルも変更する必要がない。

ABIがデグレードした場合,foo-1.1.1のABIに依存するバイナリはことごとく実行できなくなります. また,アップグレードの場合でも動作しなくなる場合があります.

この辺は /etc/ld.so.conf.d でライブラリパスを追加してやると問題ないです。ライブラリにはバージョン番号がついている(はず)なので、たとえシンボリックリンクでデフォルトの参照先を変更しても実行時にはちゃんとコンパイル時にリンクしたバージョンのライブラリを参照してくれます。逆に言うと実行時にコンパイル時にリンクしたバージョンのライブラリを参照しようとするので、ちゃんと過去のバージョンのライブラリを残しておかないと、実行できなくなります。

Red Hat 系でベタなところだとcompatシリーズのパッケージ. これでgcc 4系(ABI的には3.4系も)3.2系,2.96系が共存します.opensslもありますね(openssl-*,openssl097fとか). 私も同様なやり方でいくつかの独自パッケージを共存させています(ABIが変化したときに依存関係を崩さずにアップデートとかでは常套手段)

できないって言い切っちゃうのは、よくない表現でしたね。すみません。

もちろん過去との互換性を保つために古いライブラリ類のパッケージが存在するのは知ってます。かつては僕もディストリ作ってましたから。この手のパッケージは過去の互換性のために存在するので、ライブラリや実行ファイルのみの存在なんですよね。ヘッダファイルの共存まではできない。なので、任意のバージョンのライブラリにリンクすることができないという問題があります。

P1050145
P1050145 posted from フォト蔵

25, 26日と未踏ユース報告会&懇親会に参加してきました。

いろいろ面白いプロジェクトがありましたが、僕が一番面白かったのは音楽を視覚的に認識する方法 及び ウダーの習得を支援するソフトウェアの開発です。

採択者の宇田さんは、すでにウダーというオリジナルの楽器を開発していて、このウダーの習得を支援するためにウダー譜という独自の記法をあみだしました。
楽器だけにとどまらず、譜面までオリジナルのものを開発するなんて、なんてクリエイティブな人だろう。
今回の未踏では、そのウダー譜を使って音楽を視覚的に表示するソフトウェアを開発されてました。

あとびっくりしたのがメソッド名が全部日本語になってることw

ウダーは量産化をするというので、量産化された折にはぜひ購入したい!!

懇親会ではいろんな人とお話することができた。
未踏をやってる人ってみんな積極的で個性的ですごく面白い!!
僕も負けないように頑張らないと。

P1050144
P1050144 posted from フォト蔵

今日(もう昨日か)は千葉PMによる未踏の成果報告会に行ってきました。
今回はJavassistの千葉PM、rubyのまつもとさん、seaserのひがさんと豪華な3氏による講演があるおかげか、聴講者がいっぱいいました。
採択プロジェクトは ruby 2件、java 2件とどちらもやってない僕には少し肩身がせまかったです。(苦笑)

笹田君は相変わらずすごかったなぁ。ネタ的にもw

Mayaa はよく分かりませんでした。Javaの世界はまったく分からない。

BioRuby はなんかすごそうってイメージ。生物関係なのでどれくらいすごいのかはよく分かりませんでしたが。

すごく面白いと思ったのが、Tuigwaa です。
簡単に言うと、wiki をさらに発展させて web アプリケーションまで作れるようにしたやつです。

テーブルの定義とか、フォームの入力とか簡単に生成できて、値のチェックとかもちゃんと自動でやってくれる。
HTML は wiki で編集できて、WYSIWYG なエディタで入力。
wiki で入力したデータは PDF に変換することもできるので、そのまま印刷できます。

今回の未踏の報告会の参加申し込みのページは Tuigwaa で作ったそうです。
Tuigwaa の BTS も Tuigwaa で作っているそうです。

これは面白い!!ぜひ世界的ソフトウェアに成長して欲しい。

よくきたblogからTBいただきました。
ありがとうございます。

includeとlibはワイルドカード指定はよくないのでは?

で,本題なんですがincludeやlibあたりをワイルドカードで一気に追加すると
ほとんどの場合特定のバージョンが使用されるってことは無いですか?
個人的にはPATHも含め,ビルド時に明示的にやるべきだと思います.

まず始めに前提条件として、tarballからインストールしたソフトウェアを簡単に管理するは汎用的な方法で特にPHPに特化した内容ではないです。

複数バージョンをインストールする場合は /opt/pkgs/hoge-x.x.x にインストールします。
この場合は /opt/pkgs/hoge-x.x.x のディレクトリにはパスには含まれません。
実際にパスが通るのはシンボリックリンクをはってる /opt/hoge 以下になります。

複数のバージョンをインストールしていても、使われるのは1つだけなので複数ディレクトリにパスを通しても意味はありません。
使用するバージョンを変更する場合は /opt/hoge のシンボリックリンクを変更します。

自分自身が精通しているパッケージなら応用はいくらでも利きますが、そうでない場合、例えばテストで複数バージョンのライブラリをテストしないといけないとかだと、結構大変です。
この方法だとシンボリックリンク先を変更するだけですむので楽ですし、どんなパッケージにも適用可能です。

ファイルの実体には固有の名前をつけておいて、汎用的な名前のファイルをシンボリックリンクにしておいて、シンボリックリンクの参照先を変更することでデフォルトの挙動をかえるのはUNIXでは昔から行われています。

例えばよくあるのがライブラリのバージョンの切り替えで、よくあるライブラリのファイル名は libhoge.so-x.x.x ですが、通常 libhoge.so.x.x.x に対するシンボリックリンク libhoge.so があります。
プログラムをコンパイルしてライブラリをリンクするときはライブラリのバージョンを含めずに libhoge.so を使用します。
こうしておくとリンカがライブラリをリンクするときはバージョンのことは考えずにすみ、ライブラリのバージョンを変更する場合は libhoge.so の参照先を変更するだけですみます。

この辺の知識はThe Linux ELF HOWTOを読んで勉強しました。
10年以上程前に書かれた文書ですがまったく色あせてない。この辺の技術は急激に変化しない基盤技術なので当然ですが。

デフォルトでアクセスするファイルはシンボリックリンクにしておいて、必要なときに参照先を変更するのがUNIX的なようです。

フォト蔵API

フォト蔵APIを公開しました。
まだ開発段階ですが、「貼る蔵」で使用されている一通りの機能はそろっています。

ご意見、ご要望お待ちしています!!

PHP のプログラムにはバージョンによって動いたり動かなかったりするものがあります。
特にバージョン4, 5の違いは大きいので、これを簡単に切り替える方法を試行錯誤しながらやってみたら結構うまくいきました。

まず前提として mod_php は使いません。さすがに Apache のモジュールで複数バージョンを共存させるのは無理なので、PHP は CGI で動作させます。これなら呼び出し先の PHP プログラムを変更するだけですむので、簡単にバージョンの切り替えができます。

複数バージョンのインストールについては前回のエントリtarballからインストールしたソフトウェアを簡単に管理するを参照してください。
インストールする時に注意するのは --with-apxs2 とかのオプションをつけて apache のモジュールをコンパイルしないことです。そうすると、勝手に CGI 用にコンパイルしてくれます。
あるいは --enable-cgi をつけるといいかも。(未確認)

インストールが終わったら PHP が CGI プログラムとして呼び出されるように Apache の設定を変更します。
Fedora の場合は

ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"

と定義されていますので、/var/www/cgi-bin にファイルを追加してやるだけですみます。

sudo ln -s /opt/php/bin/php /var/www/cgi-bin/php
sudo ln -s /opt/pkgs/php-4.4.2/bin/php /var/www/cgi-bin/php-4.4.2
sudo ln -s /opt/pkgs/php-5.1.2/bin/php /var/www/cgi-bin/php-5.1.2

デフォルトの設定だと /var/www/cgi-bin でシンボリックリンクが許可されてなかったので、次の設定を apache に追加しました。

<Directory /var/www/cgi-bin>
Options FollowSymLinks
</Directory>

これで PHP を CGI プログラムとして呼び出す準備が整いました。

次に .php のファイルのアクセスに対して自動的に PHP が呼ばれるように設定します。
以下の内容で /etc/httpd/conf.d/php.conf を追加します。

Action php-script /cgi-bin/php
Action php-script-4.4.2 /cgi-bin/php-4.4.2
Action php-script-5.1.2 /cgi-bin/php-5.1.2
AddHandler php-script .php
DirectoryIndex index.php

これで .php へのアクセスに対してはデフォルトの PHP(/cgi-bin/php) が呼ばれるようになります。
php-script-4.4.2, php-script-5.1.2 は切り替え用なので、デフォルトでは使用されていません。

ようやく全ての準備が整いました。何もしなければ、デフォルトの PHP が使用されます。
違うバージョンの PHP を使用したい場合は、.htaccess に

AddHandler php-script-4.4.2 .php

と書くことで簡単に切り替えを行うことができます。
適当なところで phpinfo() の出力を見てみましょう。
ちゃんと切り替わっているはずです。

普通 tarball からインストールする時は

./configure
make
sudo make install

のようにインストールします。この場合は全てのファイルが /usr/local に入るわけですが、
これだと複数のソフトウェアをインストールした場合に、どのファイルがどのソフトウェアに所属するのか分からなくなって、アンインストールができなくなります。

なので僕はいつも tarball からソフトウェアをインストールする場合は、
例えば hoge というソフトウェアをインストールする場合、必ず /opt/hoge にインストールしています。

./configure --prefix=/opt/hoge
make
sudo make install

こうすると複数のソフトウェアをインストールしても、ソフトウェアごとにディレクトリが分かれるので、

sudo rm -rf /opt/hoge

とすれば一発でアンインストールできます。

環境変数 PATH の設定は、以前書いたエントリー環境変数 PATH を自動で設定する方法で自動で設定されるので、楽チンです。

さらに他の環境変数も次のように定義しています。

# MANPATH の設定
MANPATH=
add_env MANPATH "${HOME}/man" "${HOME}/opt/*/man/ja" "${HOME}/opt/*/man"
add_env MANPATH "/usr/local/man/ja" "/usr/local/man"
add_env MANPATH "/usr/local/*/man/ja" "/usr/local/*/man"
add_env MANPATH "/opt/local/man/ja" "/opt/local/man"
add_env MANPATH "/opt/local/*/man/ja" "/opt/local/*/man"
add_env MANPATH "/opt/*/man/ja" "/opt/*/man"
add_env MANPATH "/usr/share/jman"
add_env MANPATH "/usr/*/man/ja"
add_env MANPATH "/usr/*/man"
add_env MANPATH "/usr/man/ja" "/usr/man"
clean_env MANPATH
export MANPATH
# LD_LIBRARY_PATH の設定
LD_LIBRARY_PATH=
add_env LD_LIBRARY_PATH "${HOME}/lib" "${HOME}/opt/*/lib"
add_env LD_LIBRARY_PATH "/usr/local/lib" "/usr/local/*/lib"
add_env LD_LIBRARY_PATH "/opt/local/lib" "/opt/local/*/lib"
add_env LD_LIBRARY_PATH "/opt/*/lib"
add_env LD_LIBRARY_PATH "/lib"
add_env LD_LIBRARY_PATH "/usr/lib"
add_env LD_LIBRARY_PATH "/usr/*/lib"
clean_env  LD_LIBRARY_PATH
export LD_LIBRARY_PATH
# LIBRARY_PATH の設定
LIBRARY_PATH=
add_env LIBRARY_PATH "${HOME}/lib" "${HOME}/opt/*/lib"
add_env LIBRARY_PATH "/usr/local/lib" "/usr/local/*/lib"
add_env LIBRARY_PATH "/opt/local/lib" "/opt/local/*/lib"
add_env LIBRARY_PATH "/opt/*/lib"
add_env LIBRARY_PATH "/lib"
add_env LIBRARY_PATH "/usr/lib"
add_env LIBRARY_PATH "/usr/*/lib"
clean_env  LIBRARY_PATH
export LIBRARY_PATH
# C_INCLUDE_PATH の設定
C_INCLUDE_PATH=
add_env C_INCLUDE_PATH "${HOME}/include" "${HOME}/opt/*/include"
add_env C_INCLUDE_PATH "/usr/local/include" "/usr/local/*/include"
add_env C_INCLUDE_PATH "/opt/local/include" "/opt/local/*/include"
add_env C_INCLUDE_PATH "/opt/*/include"
add_env C_INCLUDE_PATH "/usr/include"
add_env C_INCLUDE_PATH "/usr/*/include"
clean_env  C_INCLUDE_PATH
export C_INCLUDE_PATH

こうしておくと、/opt にインストールしたソフトウェアの man もちゃんと読めますし、
コンパイルする時にヘッダファイルもちゃんとインクルードしてくれるし、
ライブラリもちゃんとロードしてくれます。

既にシステムにパッケージがインストールされているんだけど最新バージョンを試してみたいときなんかは、
とりあえず /opt にインストールしてテストすることができます。
/opt のパスは /usr よりも先に設定されるので /opt にインストールしたものが優先されます。
/etc/ld.so.conf を書き換えない限りは /opt にインストールした環境はシステムに影響を与えないので、
他のプログラムの動作に影響を与えることはありません。

上記の方法を使うと複数バージョンをインストールすることも簡単です。

複数バージョンをインストールする場合は /opt/pkgs/hoge-x.x.x にインストールします。

./configure --prefix=/opt/pkgs/hoge-1.0.0
make
sudo make install

このままではパスが通りませんので、シンボリックリンクをはってあげます。

sudo ln -s /opt/pkgs/hoge-1.0.0 /opt/hoge

違うバージョンを使いたい場合はシンボリックリンクをはりなおす。

sudo ln -s /opt/pkgs/hoge-2.0.0 /opt/hoge

複数バージョンのインストールなんかは RPM のようなパッケージ管理システムを使ってもできないので、かなり便利です。

あぶね~!!

迷惑コメントを削除しようとして普通のコメント全部削除してしまいました。
一瞬あせったけど、コメントのテーブルからデータをインサートしなおして復活!!
全て再構築して元に戻ったみたい。

IE Developer Toolbar Beta 2
が出たというので、早速インストール。

普段は Firefox で webdevelopper なのですが、やはり IE で動作確認しないといけないので、こういうツールがあると便利です。
さすがに webdevelopper ほど機能が豊富ではないですが、一通り機能がそろってるので入れておくとかなり便利。

ついでに ieHTTPHeaders も入れてみました。
これで IE での動作確認が快適になった!!

VMware Server がフリーで公開されました。

以前までフリーだった VMware Player では仮想マシンを作成することはできなかったのですが、
VMware Server は仮想マシンを作って、OS のインストールから行うことができます。
すばらしい!!

早速インストールして使ってます。

VMware Player では1つの仮想マシンしか動作することができなかったんですが、
VMware Server では複数のマシンを動作させることができるので、かなり便利です。

みなさんは UNIX系 OS で環境変数 PATH の設定をどうしてますか?
UNIX系 OS では微妙にディレクトリ構成が違ってたり、
同じ OS でも後から追加したパッケージの関係で PATH が違ってたりして面倒です。

僕の場合、環境変数 PATH は自動で設定するようにしているので、
ほとんど数年間シェルの設定は変わっていません。

すごく便利なので、僕が使ってる方法を紹介します。

まずは次のようなシェル関数を定義する。
function add_env(){
env_name=$1
shift

for i in $@; do
if ! dirs=`eval echo $i` > /dev/null 2>&1; then
continue
fi

for i in `eval echo $dirs`; do
if eval echo \$$env_name | egrep '(\:|^)'$i'(\:|$)' >/dev/null 2>&1; then
continue
fi

if [ -d $i ]; then
eval $env_name=\$$env_name:$i
fi
done
done
}

この関数は受け取った第2引数以降(複数可、メタキャラクタ指定可)を評価して、
ディレクトリだったら第1引数で指定した変数に追加するという処理を行います。

あとはこんな感じで環境変数に追加したい候補を列挙するだけ。
PATH=
add_env PATH "${HOME}/bin" "${HOME}/sbin"
add_env PATH "${HOME}/opt/*/bin" "${HOME}/opt/*/sbin"
add_env PATH "/usr/local/bin" "/usr/local/sbin"
add_env PATH "/usr/local/*/bin" "/usr/local/*/sbin"
add_env PATH "/opt/local/bin" "/opt/local/sbin"
add_env PATH "/opt/local/*/bin" "/opt/local/*/sbin"
add_env PATH "/opt/*/bin" "/opt/*/sbin"
add_env PATH "/usr/ucb"
add_env PATH "/bin" "/sbin"
add_env PATH "/usr/bin" "/usr/sbin" "/usr/*/bin" "/usr/*/sbin"

自動的に存在するディレクトリだけ $PATH に追加してくれるので、
いろんな環境で存在しそうなディレクトリを列挙しておけば、
自動的に必要なパスだけ残るようになっているわけです。

僕はこれですごくハッピーなのですが、
もし他に良い方法とかあったら、ぜひ教えてください!!

このアーカイブについて

このページには、masato2006年2月に書いたブログ記事が含まれています。

前のアーカイブはmasato: 2006年1月です。

次のアーカイブはmasato: 2006年3月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。