「Makefile」の版間の差分
(→変数を使う方法) |
|||
(4人の利用者による、間の30版が非表示) | |||
行1: | 行1: | ||
'''Makefile'''とはmakeコマンドを実行したときに読み込まれるテキストファイル。 | '''Makefile'''とはmakeコマンドを実行したときに読み込まれるテキストファイル。 | ||
makeとは、C言語などのソースファイルが複数存在していても、自動で順番を把握し[[コンパイル]]する[[コマンド]]である。 | makeとは、C言語などのソースファイルが複数存在していても、自動で順番を把握し[[コンパイル]]する[[コマンド]]である。 | ||
+ | Eosでは、makeをつかってコマンドをまとめ、大きな仕事(電子線トモグラフィーや単粒子解析など)をさせます。分散環境とストリーム実行、入出力記述の自由度の拡大を目的として、次世代makeとして、[[PIONE]]を現在開発中です。 | ||
== '''EosにおけるMakefile''' == | == '''EosにおけるMakefile''' == | ||
+ | |||
+ | [[ファイル:makefile.PNG|thumb|right|350px|Makefileの一部]] | ||
+ | [[3次元再構成]]を[[Eos]]で行う場合、ファイル数が莫大になると、1つずつ[[コマンド]]を打ち込んでいては多大な労力を必要としてしまう。 | ||
+ | この労力を削減するために、[[Eos]]はmakeコマンドを使って実行することが必要であることが多い。 | ||
+ | また、makefileを理解するためには[[シェルスクリプト]]の知識も必要となる。<br> | ||
+ | <br> | ||
+ | <br> | ||
+ | |||
+ | .ref3d.red2d: <span style="color:red">(1)</span> | ||
+ | mrc3Dto2D -i $*.ref3d -o $*.ref2d -EulerMode YOYS InterpolationMode 0 -Rot1 0 359 $(STEP) -Rot2 0 359 $(STEP) -Rot3 0 0 $(STEP) -m 1 | ||
+ | |||
+ | 例えば、上記のようなMakefileがあったとして、 | ||
+ | |||
+ | $ make EM.ref2d | ||
+ | |||
+ | makeコマンドを上のように実行すると、自動で拡張子.ref2dを生成する行を探し実行してくれる。 | ||
+ | |||
+ | 今回は(1)の部分が、拡張子.ref3dファイルから.ref2dファイルを生成するという意味を表しており、以下の部分を実行する。 | ||
+ | |||
+ | mrc3Dto2D -i $*.ref3d -o $*.ref2d -EulerMode YOYS InterpolationMode 0 -Rot1 0 359 $(STEP) -Rot2 0 359 $(STEP) -Rot3 0 0 $(STEP) -m 1 | ||
+ | |||
+ | この行が、先程の(1)に属していることを表すために、先頭にTabによる空行が挿入されている。 | ||
+ | つまり、Tabによる空欄がなくなるまで、(1)に属する領域ということになる。 | ||
+ | |||
+ | 更に、以下のようにmakeをmakeするMakefileを作れば、複数の工程を1度のmakeで実行することができる。 | ||
+ | このように、[[3次元再構成]]など複数の工程が必要な作業においてMakefileは必需品となる。 | ||
+ | |||
+ | All:: | ||
+ | make $(TARGET).ref3d; | ||
+ | make $(TARGET).ref2d; | ||
+ | make AVGs; | ||
+ | make -j $(JOP_NUM) corinfo; | ||
+ | make CORINFOs; | ||
+ | make $(TARGET).ds6; | ||
+ | |||
+ | == Makefile作成での注意点 == | ||
+ | === シェルスクリプトとの構文の違い === | ||
+ | makefileの構文は基本的に[[シェルスクリプト]]と同じであるが、中には違う規則もある。これはmakefileが1行1行でシェルスクリプトを実行するためである。ここではそれらの違いによる注意点を示す。<br> | ||
+ | <br> | ||
+ | |||
+ | ==== 変数 ==== | ||
+ | 変数の値は1行内でしか保持されない。行をまたぐときは;と\を使用する。さらに[[シェルスクリプト]]にて変数を使用するときには$iのように記述するが、Makefileにおいては$$iのように$を2つ重ねて記述する。<br> | ||
+ | |||
+ | <pre> | ||
+ | i=1 ; \ | ||
+ | echo "$$i" | ||
+ | </pre> | ||
+ | <br> | ||
+ | |||
+ | ==== 制御文、ループ文 ==== | ||
+ | 制御文、ループ文を記述するときは1行で文を閉じなければならない。<br> | ||
+ | |||
+ | <pre> | ||
+ | if [ (条件) ]; then (処理); fi | ||
+ | </pre> | ||
+ | |||
+ | 条件、処理が長いときは\を使うと行をまたぐことができ、読みやすいようになる。<br> | ||
+ | <pre> | ||
+ | if [ (条件1) ]; then \ | ||
+ | (処理A); \ | ||
+ | if [ (条件2) ]; then \ | ||
+ | (処理B); \ | ||
+ | fi; \ | ||
+ | (処理C); \ | ||
+ | fi | ||
+ | </pre> | ||
+ | <br> | ||
+ | |||
+ | <pre> | ||
+ | for (( i=0; i<5; i++ )); \ | ||
+ | do \ | ||
+ | echo "$$i"; \ | ||
+ | done | ||
+ | </pre> | ||
+ | <br> | ||
+ | |||
+ | このとき途中でコメントアウトの#を使用すると、以降の処理までコメントアウトされてしまい、エラーや予期しない動作となってしまう恐れもあるので注意が必要である。 | ||
+ | <pre> | ||
+ | for (( i=0; i<5; i++ )); \ | ||
+ | do \ | ||
+ | echo "$$i"; \ | ||
+ | # echo "Test"; \ | ||
+ | done | ||
+ | </pre> | ||
+ | 上記の場合、echo "Test"; だけでなくdoneもコメントアウトしたことになるので、構文エラーとなる。<br> | ||
+ | <br> | ||
+ | |||
+ | === 特定のサフィックスをもつ変数の作り方 === | ||
+ | ここは,lsを使って,特定のサフィックスをもつファイルのリストをもつ変数の作り方を示します。 | ||
+ | |||
+ | TIF.lst:: | ||
+ | echo "TIFFILES=\\\\" > TIF.lst | ||
+ | for i in `ls -1 *.tif`; do \ | ||
+ | echo $$i | sed -e s/tif/tif\\\\/ >> TIF.lst; \ | ||
+ | done | ||
+ | echo "" >> TIF.lst | ||
+ | |||
+ | バックスラッシュが変換されてしまうために,最終的に一つでよいのですが,4つ必要になっています。 | ||
+ | sedを使って,最終のtifの後ろに,バックスラッシュをつけて,改行できるようにしています。こうすることで,あとで,このファイルから必要のないものを消していくこともできます。 | ||
+ | |||
+ | == 多量の同一サフィックス・ファイルの扱い方 == | ||
+ | === フォーニーターゲットの使い方 === | ||
+ | まちがって消してしまわないために一番よく使うのは,cleanでしょうか。 | ||
+ | |||
+ | clean: | ||
+ | rm *.mrc | ||
+ | |||
+ | として,mrcをもつサフィックスを消します。 | ||
+ | |||
+ | === 変数を使う方法 === | ||
+ | |||
+ | $ make init | ||
+ | $ make all | ||
+ | |||
+ | の順序で実行するしかけです。TIF.lstなかで,TIFFILESという変数を用意したのち, そのサフィックスを置き換えていくことで利用できる様にしています。 | ||
+ | このばあいは,*.tifファイルが最初にある場合につかいます。 | ||
+ | |||
+ | .SUFFIXES: .tif .mrc .sec .fft | ||
+ | |||
+ | -include TIF.lst | ||
+ | -include make.config | ||
+ | |||
+ | all: TIF.lst | ||
+ | make -j $(JOBS) mrc | ||
+ | |||
+ | init: | ||
+ | make TIF.lst | ||
+ | |||
+ | mrc: $(TIFFILES:.tif=.mrc) | ||
+ | |||
+ | TIF.lst:: $(TIFFILES) | ||
+ | echo "TIFFILES=\\\\" > TIF.lst | ||
+ | for i in `ls -1 *.tif`; do \ | ||
+ | echo $$i | sed -e s/tif/tif\\\\/ >> TIF.lst; \ | ||
+ | done | ||
+ | echo "" >> TIF.lst | ||
+ | |||
+ | .tif.mrc: | ||
+ | tiff2mrc -i $*.tif -o $*.mrc -m 1 | ||
+ | |||
+ | >> make.config | ||
+ | JOBS=4 |
2021年12月12日 (日) 02:08時点における最新版
Makefileとはmakeコマンドを実行したときに読み込まれるテキストファイル。 makeとは、C言語などのソースファイルが複数存在していても、自動で順番を把握しコンパイルするコマンドである。 Eosでは、makeをつかってコマンドをまとめ、大きな仕事(電子線トモグラフィーや単粒子解析など)をさせます。分散環境とストリーム実行、入出力記述の自由度の拡大を目的として、次世代makeとして、PIONEを現在開発中です。
目次
EosにおけるMakefile
3次元再構成をEosで行う場合、ファイル数が莫大になると、1つずつコマンドを打ち込んでいては多大な労力を必要としてしまう。
この労力を削減するために、Eosはmakeコマンドを使って実行することが必要であることが多い。
また、makefileを理解するためにはシェルスクリプトの知識も必要となる。
.ref3d.red2d: (1)
mrc3Dto2D -i $*.ref3d -o $*.ref2d -EulerMode YOYS InterpolationMode 0 -Rot1 0 359 $(STEP) -Rot2 0 359 $(STEP) -Rot3 0 0 $(STEP) -m 1
例えば、上記のようなMakefileがあったとして、
$ make EM.ref2d
makeコマンドを上のように実行すると、自動で拡張子.ref2dを生成する行を探し実行してくれる。
今回は(1)の部分が、拡張子.ref3dファイルから.ref2dファイルを生成するという意味を表しており、以下の部分を実行する。
mrc3Dto2D -i $*.ref3d -o $*.ref2d -EulerMode YOYS InterpolationMode 0 -Rot1 0 359 $(STEP) -Rot2 0 359 $(STEP) -Rot3 0 0 $(STEP) -m 1
この行が、先程の(1)に属していることを表すために、先頭にTabによる空行が挿入されている。 つまり、Tabによる空欄がなくなるまで、(1)に属する領域ということになる。
更に、以下のようにmakeをmakeするMakefileを作れば、複数の工程を1度のmakeで実行することができる。 このように、3次元再構成など複数の工程が必要な作業においてMakefileは必需品となる。
All:: make $(TARGET).ref3d; make $(TARGET).ref2d; make AVGs; make -j $(JOP_NUM) corinfo; make CORINFOs; make $(TARGET).ds6;
Makefile作成での注意点
シェルスクリプトとの構文の違い
makefileの構文は基本的にシェルスクリプトと同じであるが、中には違う規則もある。これはmakefileが1行1行でシェルスクリプトを実行するためである。ここではそれらの違いによる注意点を示す。
変数
変数の値は1行内でしか保持されない。行をまたぐときは;と\を使用する。さらにシェルスクリプトにて変数を使用するときには$iのように記述するが、Makefileにおいては$$iのように$を2つ重ねて記述する。
i=1 ; \ echo "$$i"
制御文、ループ文
制御文、ループ文を記述するときは1行で文を閉じなければならない。
if [ (条件) ]; then (処理); fi
条件、処理が長いときは\を使うと行をまたぐことができ、読みやすいようになる。
if [ (条件1) ]; then \ (処理A); \ if [ (条件2) ]; then \ (処理B); \ fi; \ (処理C); \ fi
for (( i=0; i<5; i++ )); \ do \ echo "$$i"; \ done
このとき途中でコメントアウトの#を使用すると、以降の処理までコメントアウトされてしまい、エラーや予期しない動作となってしまう恐れもあるので注意が必要である。
for (( i=0; i<5; i++ )); \ do \ echo "$$i"; \ # echo "Test"; \ done
上記の場合、echo "Test"; だけでなくdoneもコメントアウトしたことになるので、構文エラーとなる。
特定のサフィックスをもつ変数の作り方
ここは,lsを使って,特定のサフィックスをもつファイルのリストをもつ変数の作り方を示します。
TIF.lst:: echo "TIFFILES=\\\\" > TIF.lst for i in `ls -1 *.tif`; do \ echo $$i | sed -e s/tif/tif\\\\/ >> TIF.lst; \ done echo "" >> TIF.lst
バックスラッシュが変換されてしまうために,最終的に一つでよいのですが,4つ必要になっています。 sedを使って,最終のtifの後ろに,バックスラッシュをつけて,改行できるようにしています。こうすることで,あとで,このファイルから必要のないものを消していくこともできます。
多量の同一サフィックス・ファイルの扱い方
フォーニーターゲットの使い方
まちがって消してしまわないために一番よく使うのは,cleanでしょうか。
clean: rm *.mrc
として,mrcをもつサフィックスを消します。
変数を使う方法
$ make init $ make all
の順序で実行するしかけです。TIF.lstなかで,TIFFILESという変数を用意したのち, そのサフィックスを置き換えていくことで利用できる様にしています。 このばあいは,*.tifファイルが最初にある場合につかいます。
.SUFFIXES: .tif .mrc .sec .fft -include TIF.lst -include make.config all: TIF.lst make -j $(JOBS) mrc init: make TIF.lst mrc: $(TIFFILES:.tif=.mrc) TIF.lst:: $(TIFFILES) echo "TIFFILES=\\\\" > TIF.lst for i in `ls -1 *.tif`; do \ echo $$i | sed -e s/tif/tif\\\\/ >> TIF.lst; \ done echo "" >> TIF.lst .tif.mrc: tiff2mrc -i $*.tif -o $*.mrc -m 1
>> make.config
JOBS=4