xmkmf コマンドとImakefile 計算機やOSの違いによるソースコードやMakefileに微少な変更を加える煩雑さを 避けるために、Imakefile と xmkmf コマンドが使用される。 xmkmf コマンドはもともとは X ライブラリーをいろいろな機種にインストール するために用意されたものである。xmkmf コマンドは X のコンフィギュレー ションディレクトリー(/usr/lib/X11/config など )の設定を用いて imake コマンドを起動する。imake コマンドは ソースファイルのプリプロセス に使用されている cpp を使って Imakefile を処理し、Makefile を生成する。 xmkmfを使うには、Imakefile を作成し、 $ xmkmf とすれば良い($ はプロンプト)。これで、既存の Makefile は Makefile.bak と改名され、Imakefile より新しく Makefile が作られる。 Imakefile は cpp により処理されるので、cpp のコマンド、 #include "filename" #define FLAG #undef FLAG #ifdef FLAG #if defined(FLAG) || defined(NFLAG) #if defined(FLAG) && !defined(NFLAG) #elsif define(KFLAG) #else #endif 等が使える。||は OR, && はAND, ! は否定を表す。 これらを使って機種によって異るコンパイルパラメーターの設定が行える。 X11/config/Imake.tmpl にかかれている機種を表す変数名には次のようなものがある。 hitachiArchitecture HI-UX HPArchitecture HP-UX LinuxArchitecture Linux これらの変数は、xmkmf が起動されたときに設定されるので、これを使って機種固有の Makefile の変更の設定を行える。 一方、Fortran/C/C++ などに機種固有のコードを埋め込むには、同様に cpp の機能を使うとよい。 CやC++ のソースコードはコンパイル時に自動的に cppでプリプロセスされる。Fortran のコードはファイル名のサフィックスが .F だと cpp でプリプロセスされる(ただし、 日立の f77 コマンドにはこの機能はない)。X11/config の設定は無効であるが、 コンパイルの -D オプションを使うことにより、cpp の変数の定義を行える。そこで、 Imakefile のなかで機種固有の変数をコンパイルパラメーターに指定するようにしておくと ソースコードの中でも機種固有のコードを使用することができる。 lclib で使用している Imake 用のテンプレートファイルは jlcux1:/proj/phys/lclib/pro/config/lclib.tmpl ccjlc1:/proj.hp/phys/lclib/97a_f90/config/lclib.tmpl ccjlc1:/proj.hp/phys/lclib/97a_f90/config/hitachi.def などがある。これらを Imakefile のなかで#include しておくと、lclib での設定を簡単に使用できる。 Imakefile の例を下に示す。 ###################################################################### #ifdef hitachiArchitecture #define F90FORTRAN #undef DOSHRLIB #include "/proj.hi/phys/lclib/97a_f90/config/hitachi.def" CERNDIR = /cern/95a_f90/lib USRDIR = /usr/lib/X11R5 USRLIB = -lHITACHI -L$(USRDIR) -lX11 -L/lib/pa1.1 -lm SYSTEMLIB = -L/usr/lib/X11R5 -lXt -lXm -lX11 -lc -lPW -ldld ##################################### #else #include "/proj/phys/lclib/pro/config/lclib.tmpl" CERNDIR = /cern/pro/lib USRDIR = /usr/X11R6/lib USRLIB = -L$(USRDIR) -lX11 SYSTEMLIB = -L/usr/X11R6/lib -lXt -lXm -lX11 -lXext -lc -ldl -lm -lcrypt #endif ###################################################################### CERNLIB = -lgeant321 -ljetset74 \ -lgraflib -lgrafX11 -lkernlib \ -lpacklib -lpawlib \ -lgraflib -lgrafX11 -lkernlib -lpacklib -lmathlib JLCDIR = ../../wrk/lib JLCLIB = -ljlclib -lzbs INCPATH = -I../wrk/inc WORK_DIR = . WORK_MAIN = main.o WORK_OBJS = uginit.o ugeom.o gukine.o gutrev.o udraw.o \ gustep.o guout.o uglast.o guhadr.o guphad.o PROGRAM = jim # # all: と clean: の標準設定を上書きするために、:: を使う。 all:: $(PROGRAM) $(PROGRAM): $(WORK_MAIN) $(WORK_OBJS) $(FC) $(FOPT) $(INCPATH) $(WORK_MAIN) $(WORK_OBJS) \ -L$(JLCDIR) $(JLCLIB) \ -L$(CERNDIR) $(CERNLIB) \ $(USRLIB) \ -o $(PROGRAM) clean:: rm -f *.o rm -f $(PROGRAM) ###################################################################### (Imakefile の例の終了) lclib.templ のなかでは次のような -D 変数が各機種ごとに設定されている。 HPArchitecture -DHP hitachiArchitecture -DHIUXF77 LinuxArchitecture -DMACHTEN_PPC -DG77_521_OR_GREATER これ以外の設定については、lclib.templ を参照すること。 HIUX で使うときには、config/hitachi.def だけを #include すれば良い。 ただし、f77 を使うか f90 を使うかに応じて、F77FORTRAN か F90FORTRAN を #include の前に設定しておくことが必要である。 ###################################################################### cpp の高度な使い方ーマクロ #define TARGET と定義された場合には、cpp はソースプログラム中の TARGET という文字を空白と置き換える。 #define 文は一般的に次のように書くこともできる。 #define TARGET(arg1,arg2,...) replace-strings この場合には、TARGET文字列が現れたとき、replace-string 中の仮変数を 実変数の文字に置き換えた文字列に置き換えられる。この際、replace-spring に バックスラッシュ(\)を含めると複数行のものに置き換えることができる。 X ライブラリーの作成に使用される標準的なものは、 /usr/lib/X11/conf/Imake.rules に定義されている。これらを利用すれば、さらに簡単にImakefile を書くこともできる。例えば、 OBJS = obj1.o obj2.o LIBNAME = mylib INSTALLDIR = dirlib NormalLibraryTarget($(LIBNAME), $(OBJS)) InstallLibrary($(LIBNAME), $(INSTALLDIR)) とすると、ライブラリーを作る標準的なMakefileを作成することができる。 (24-October-1998 A.Miyamoto)