他にも書かないかんかなーと思うとこはたくさんあるのですが、 気分的にこっち書いとこうということになりました。よろしく。
(2001/05/25追記: 途中でやめててもうしわけないっす。 書き足しました)
SDLはmulti-platformなライブラリです。 また、本家の冒頭で 「cross-platform」と書いている通り、 WindowsのライブラリをLinux上で作成する、といったことも可能です。
SDLの配布ファイル(ソースコードのarchive file)は、Windows用、Linux用、 といったように分かれておらず、すべて共通(例: SDL-1.2.0.tar.gz)です。 配布ファイルの中にはサポートしているすべての環境に対するコードが入っています。
それらのコードの多くの部分は、あなたが今使っている 環境(マシン、OS、インストールされているパッケージなど)と 違う環境向けに書かれたコードですので、コンパイルに失敗するかもしれませんし、 コンパイルが通ってもリンクでエラーが起きるかもしれません。 いずれにしても不要なコード、あるいは、別の環境では必要になるんだけど、 ここでは含まれてはいけないコードが 含まれています。
そのため、buildの前段階で、この環境(コンパイルする環境、 ターゲットとなる環境)で、どれが必要で、どれが不要かということを 調べる作業をする必要があります。
他の多くのソフトと同様に、 SDLは、この作業のためにautomake/autoconf/libtoolといったツールを 利用しています。それって何?という方は、 shimakiさんの ページや、 この本などを 読んでみてください。
SDLは、configureというスクリプトで、buildする環境に 関する情報、たとえば、どのようなOSなのか、 どんなパッケージがインストールされているか、などを調べます。 このconfigureスクリプトを手軽に生成するためのツールがautoconfです。
configureはその内容にしたがってMakefile.in からMakefileを生成します。 このMakefile.inを手軽に生成するためのツールがautomakeです。
libtoolはとりあえず略...
SDLソースのディレクトリ構造の図です。

手抜きでスマンクス(^^; これを見ますと、audio、cdrom、endian、events...
といった、SDL introで
見慣れた機能が並んでいて、その下に環境ごとにディレクトリが掘られている
様子が分かります。
今回はaudioを例にとって、
zinnia@iguchi:~/build/SDL/SDL-1.2.0/src/audio[10]% \ls -ARF Makefile.am SDL_sysaudio.h macrom/ Makefile.in SDL_wave.c nas/ SDL_audio.c SDL_wave.h nto/ SDL_audio_c.h alsa/ paudio/ SDL_audiocvt.c arts/ sun/ SDL_audiodev.c baudio/ ums/ SDL_audiodev_c.h dma/ windib/ SDL_audiomem.c dmedia/ windx5/ SDL_audiomem.h dsp/ SDL_mixer.c esd/ ./alsa: Makefile.am SDL_alsa_audio.c Makefile.in SDL_alsa_audio.h ./arts: Makefile.am SDL_artsaudio.c Makefile.in SDL_artsaudio.h ./baudio: Makefile.am Makefile.in SDL_beaudio.cc SDL_beaudio.h ./dma: Makefile.am Makefile.in SDL_dmaaudio.c SDL_dmaaudio.h ./dmedia: Makefile.am SDL_irixaudio.c Makefile.in SDL_irixaudio.h ./dsp: Makefile.am Makefile.in SDL_dspaudio.c SDL_dspaudio.h ./esd: Makefile.am Makefile.in SDL_esdaudio.c SDL_esdaudio.h ./macrom: Makefile.am Makefile.in SDL_romaudio.c SDL_romaudio.h ./nas: Makefile.am Makefile.in SDL_nasaudio.c SDL_nasaudio.h ./nto: Makefile.am SDL_nto_audio.c Makefile.in SDL_nto_audio.h ./paudio: Makefile.am Makefile.in SDL_paudio.c SDL_paudio.h ./sun: Makefile.am Makefile.in SDL_sunaudio.c SDL_sunaudio.h ./ums: Makefile.am Makefile.in SDL_umsaudio.c SDL_umsaudio.h ./windib: Makefile.am Makefile.in SDL_dibaudio.c SDL_dibaudio.h ./windx5: Makefile.am Makefile.in SDL_dx5audio.c SDL_dx5audio.h
src/audio以下のディレクトリは こんな感じになっています。 これ見て分かるのは
configureをしますと、各featureごとにその存在チェックを行います。 --disable-feature(または--enable-feature=no)することでこの チェックをスキップすることができます。
nas(Network Audio System)を例にとってconfigureの該当部分を眺めてみましょ う。
CheckNAS()
{
# Check whether --enable-nas or --disable-nas was given.
if test "${enable_nas+set}" = set; then
enableval="$enable_nas"
:
else
enable_nas=yes
fi
if test x$enable_audio = xyes -a x$enable_nas = xyes; then
echo $ac_n "checking for NAS audio support""... $ac_c" 1>&6
echo "configure:3788: checking for NAS audio support" >&5
have_nas=no
if test -r /usr/X11R6/include/audio/audiolib.h ; then
have_nas=yes
fi
echo "$ac_t""$have_nas" 1>&6
if test x$have_nas = xyes; then
CFLAGS="$CFLAGS -DNAS_SUPPORT"
SYSTEM_LIBS="$SYSTEM_LIBS -laudio -lXt"
AUDIO_SUBDIRS="$AUDIO_SUBDIRS nas"
AUDIO_DRIVERS="$AUDIO_DRIVERS nas/libaudio_nas.la"
fi
fi
}
おおざっぱに眺めてゆきますと
CFLAGSの方は、まあ、条件コンパイルのフラグっぽいということで よいのですが、AUDIO_{SUBDIRS,DRIVERS}は何者でしょうか? とりあえずこれを調べてみることにしましょう。
とりあえずgrepかけてみますか...
(zsh user only) zinnia@iguchi:~/build/SDL/SDL-1.2.0[44]% grep -l AUDIO_SUBDIRS **/* Makefile.in configure configure.in docs/Makefile.in docs/html/Makefile.in docs/man3/Makefile.in include/Makefile.in src/Makefile.in src/audio/Makefile.am src/audio/Makefile.in src/audio/alsa/Makefile.in src/audio/arts/Makefile.in src/audio/baudio/Makefile.in src/audio/dma/Makefile.in src/audio/dmedia/Makefile.in src/audio/dsp/Makefile.in src/audio/esd/Makefile.in src/audio/macrom/Makefile.in src/audio/nas/Makefile.in (中略) src/video/wincommon/Makefile.in src/video/windib/Makefile.in src/video/windx5/Makefile.in src/video/x11/Makefile.inうーん、かなりの量のファイルがヒットしました。が、ほぼすべてが Makefile関係のようですね。 Makefile.inはMakefile.amの生成物ですから...
zinnia@iguchi:~/build/SDL/SDL-1.2.0[46]% grep -l AUDIO_SUBDIRS **/* | grep -v Makefile.in$ configure configure.in src/audio/Makefile.amふむふむ。 src/audio/Makefile.amを見てみることにしましょう。
## Makefile.am for the SDL audio library
noinst_LTLIBRARIES = libaudio.la
# Define which subdirectories need to be built
SUBDIRS = @AUDIO_SUBDIRS@
DIST_SUBDIRS = alsa arts baudio dma dmedia dsp esd macrom nas nto \
paudio sun ums windib windx5
DRIVERS = @AUDIO_DRIVERS@
# Include the architecture-independent sources
COMMON_SRCS = \
SDL_audio.c \
SDL_audio_c.h \
SDL_audiocvt.c \
SDL_audiodev.c \
SDL_audiodev_c.h \
SDL_audiomem.c \
SDL_audiomem.h \
SDL_mixer.c \
SDL_sysaudio.h \
SDL_wave.c \
SDL_wave.h
libaudio_la_SOURCES = $(COMMON_SRCS)
libaudio_la_LIBADD = $(DRIVERS)
libaudio_la_DEPENDENCIES = $(DRIVERS)
automakeの細かいことはおいといて、意図を掴むように努力してみましょうか。
AUDIO_DRIVERS = dsp/libaudio_dsp.la dma/libaudio_dma.la arts/libaudio_arts.la esd/libaudio_esd.la nas/libaudio_nas.la AUDIO_SUBDIRS = dsp dma arts esd nasMakefileの動きとしては、SUBDIRSのそれぞれについてmakeをするというような 理解でよろしいかと思います。そんなこんなで、 AUDIO_{SUBDIRS,DRIVERS}に出てこないサブディレクトリは そもそもコンパイル/リンクの対象にならなさそうだということが 想像できましたでしょうか?
makeまでの手順はだいたい想像がつきました。 では実際にコードがどんなふうになっているのか、いよいよ見てみることに しましょう。configureのときに出てきた-DNAS_SUPPORTを手がかりにします。
zinnia@iguchi:~/build/SDL/SDL-1.2.0/src/audio[66]% grep NAS_SUPPORT **/* SDL_audio.c:#ifdef NAS_SUPPORT SDL_sysaudio.h:#ifdef NAS_SUPPORTおや、思ったより少ない。では該当部分を眺めてみます。
(SDL_audio.c)
#ifdef NAS_SUPPORT
&NAS_bootstrap,
#endif
(SDL_sysaudio.h)
#ifdef NAS_SUPPORT
extern AudioBootStrap NAS_bootstrap;
#endif
該当部分はこれだけでした。
どうもNAS_bootstrapというGlobal変数(AudioBootStrap構造体)が
キーのようです。
AudioBootStrap構造体の定義は、 SDL_sysaudio.hの、 さきほど見た場所のすぐ上にあります。
typedef struct AudioBootStrap {
const char *name;
const char *desc;
int (*available)(void);
SDL_AudioDevice *(*create)(int devindex);
} AudioBootStrap;
2つのconst charへのポインタ、2つの関数へのポインタを持つ構造体の
ようです。見た感じ、名前、説明、チェック用関数、???といった
気がします。
最後の関数createは、
SDL_AudioDeviceへのポインタを返す関数(引数はint1つ)へのポインタ
ということになりそうです。
SDL_AudioDeviceの定義は、AudioBootStrapのすぐ上にあります(うーん楽な展開)
ちょっとでかいので引用はひかえます。中身を見てみると、
OpenAudio、InitAudio、PlayAudioといった名前の(関数への)ポインタが
あったり、enabled、paused、openedといったint変数があったりで、
どうもdeviceの内部状態へのアクセス手段を提供するもののように
見えます。
ここまでの話をまとめます。
さてさて。では実際にNAS_bootstrapというものは どういう中身を持つのか調べてみましょう。
zinnia@iguchi:~/build/SDL/SDL-1.2.0/src/audio[67]% grep -l NAS_bootstrap **/* SDL_audio.c SDL_sysaudio.h nas/SDL_nasaudio.c上の2つは先程見たものですからいいですね。というわけで nas/SDL_nasaudio.cを見ることにします。
AudioBootStrap NAS_bootstrap = {
NAS_DRIVER_NAME, "Network Audio System",
Audio_Available, Audio_CreateDevice
};
先程のAudioBootStrapの定義とてらしあわせてみますと、
static int Audio_Available(void)
{
AuServer *aud = AuOpenServer("", 0, NULL, 0, NULL, NULL);
if (!aud) return 0;
AuCloseServer(aud);
return 1;
}
AuOpenServer/AuCloseServerというのはnasのAPIという理解でよいでしょう。
実際に起動できるかどうかのチェックをして、失敗したら0、
成功したら1を返す。というわけで、名前の通り利用可能かどうかの
チェックをする関数のようです。
続いてAudio_CreateDeviceです。 中身を見てみると、おおざっぱに言ってSDL_AudioDeviceのセッティングを行い、 それを返す関数と言ってよいようですね。
/* Set the function pointers */
this->OpenAudio = NAS_OpenAudio;
this->WaitAudio = NAS_WaitAudio;
this->PlayAudio = NAS_PlayAudio;
this->GetAudioBuf = NAS_GetAudioBuf;
this->CloseAudio = NAS_CloseAudio;
this->free = Audio_DeleteDevice;
return this;
最後の方だけ引用してみました。thisは(現在セットアップ中の)
SDL_AudioDevice構造体へのポインタです。
しかしthisを変数名として使うのはいかがなものか...
こんなふうにして、SDL_AudioDeviceに、nas(src/audio/nas)向けのルーチンを 登録して上流(src/audio)に返してやるというのが、 個々のdeviceの仕事のすべてです。
ここで上でリンクした関数がいずれもstaticで宣言されていることに とりあえず注目しておきましょう。 これらの関数は外から直接呼ばれるのではなく、 SDL_AudioDevice構造体経由で呼ばれます。 構造体にアドレスを登録できればそれでいいわけで、外部に公開する 必要はないわけです。staticにすることで、 SDL_nasaudio_Audio_Availableみたいに 名前が衝突しないようにする気遣いも不要になり、コードの使いまわしが 楽になりそうーという利点もあります。
いろいろと眺めてみましたが、ここまでの結果をまとめておきましょう。 なお、ここでは「推測」や「想像」などがまじっていることを おことわりしておきます(ここまで読んできた方には先刻承知でしょうが)。 疑わしいと思ったらコードを確認するようにしてみてください。
これが各deviceに視点を向けて、コードを追いかけたときの様子です。 SDL本体としては、個々のdeviceに対して直接働きかけるのではなく、 かならずSDL_AudioDeviceのポインタ経由で触りにゆくのだ、ということも おわかりいただけたと思います。そのため、新しいdeviceのサポートを したいときは、SDL_AudioDeviceで要求されているmethodを実装してやれば、 全体としての構造をいじる必要はないということになります(SDL_audio.cに 定義を追加する必要はありますが)
では、そうやって作られたAudioBootStrap、SDL_AudioDeviceは 実際にどのように使われてゆくのでしょうか? というのが 次回のネタになる予定です。
いきなり息切れ中。感想とかいただけるととても喜びます。 変なところや説明が不十分なとこなども是非ご指摘ください。 わかりづらいとか無駄なことはやめろとかでも涙を飲みつつ 粛々と読ませていただきます。ではまた。