とりあえず用 Makefile
make はビルドツールです。
私は CoffeeScript の JavaScript への変換などに make コマンドを使っています。
私が make にさせたい動作は、
拡張子が「.coffee」のファイルがあったら、coffee コマンドでそれを JavaScript に変換する
というものです。
要は、myscript.coffee などを書いたとき、とりあえず make しておけば myscript.js が得られるようにしたいのです。
make の動作を制御するには、その設定を Makefile に記述する必要があります。
本稿は、私が使っている Makefile の紹介です。
make の詳細については以下を参照ください。
動作環境について
Makefile は GNU make 用に記述されています。
また、make が呼び出すコマンド(例えば、coffee コマンド)は、OS にインストールされている必要があります。
私は、Ubuntu Linux で使用しているので、細部で Ubuntu に依存しているところがあるかも知れませんが、大抵の UNIX、Linux、POSIX系OS で動作すると思います。
この Makefile について
Makefile は本稿末尾に掲載しています。
make は(デフォルト動作では)カレントディレクトリの Makefile ファイルを読み込みます。
なので、基本的には Makefile はカレントディレクトリに置いて使います。
make 実行時は引数にターゲットを指定します。
この Makefile がサポートするターゲットは以下です。
ターゲット | 説明 |
---|---|
build | 成果物を生成する。例えば「myscript.coffee」があった時「myscript.js」を生成する |
clean | 成果物を消去する。例えば「myscript.coffee」があった時「myscript.js」を消去する |
ターゲットを省略した場合は「build」を指定したとみなされます。
実行例は以下です。
$ make # buildターゲット実行 (成果物を生成)
$ make clean # cleanターゲット実行 (成果物を消去)
Makefile を実行する
毎回 Makefile を作業ディレクトリにコピーするのは面倒です。
この Makefile は先頭行に shebang を記載しています。
shebang とは以下のもので、シェルスクリプトなどによく見られます。(make のパス(/usr/bin/make)は、お使いの環境と異なる場合があります)
#!/usr/bin/make -f
これがあれば、Makefile 実行権を付与すると実行することができます。
$ chmod +x Makefile
$ ./Makefile # 実行できる。(make -f Makefile と同じこと)
私は以下のように環境を作っています。
$ cd ~/etc/tmpl/mk/
$ ls Makefile
Makefile # Makefile は ~/etc/tmpl/mk に置く
$ chmod +x Makefile # 実行権を付与
$ cd ~/bin/
$ ln -s ~/etc/tmpl/mk/Makefile mk # mk という名前でシンボリックリンクを作る
あるいは単純に以下のようにしてもいいです。
$ cd ~/bin/
$ ls Makefile
Makefile # Makefile は ~/bin/ に置く
$ chmod +x Makefile # 実行権を付与
$ mv Makefile mk # mk という名前にリネーム
私の環境では、~/bin に PATH を通しています。なので、上のようにすることで、「mk」とタイプすると、(Makefile を毎回コピーしなくても)この Makefile を実行することができます。
$ mk # buildターゲット実行 (成果物を生成)
$ mk clean # cleanターゲット実行 (成果物を消去)
オプション「-n」
これは参考情報です。
make にはいろいろオプションがあります。
私が一番よく使うオプションは「-n」です。
これは、実際にはターゲットを実行しませんが、どのように make が動作しようとするか見るだけのオプションです。
$ mk -n # buildターゲット実行の様子を見る (実際には成果物を生成しない)
$ mk -n clean # cleanターゲット実行の様子を見る (実際には成果物を消去しない)
Makefile
「xxx.coffee」を「xxx.js」に変換する以外にも以下の動作をサポートします。
ソースファイル | 作られるファイル | 実行するコマンド | 説明 |
---|---|---|---|
xxx.coffee | xxx.js | coffee | CoffeeScriptソースからJavaScriptファイルを作る |
xxx.haml | xxx.html | haml | Haml形式ファイルからHTML5文書を作る |
xxx.xhaml | xxx.xhtml | haml | Haml形式ファイルからXHTML文書を作る |
xxx.ghaml | xxx.goml | haml | Haml形式ファイルからGOML(HTML5)文書を作る |
xxx.md | xxx.html | markdown | Markdown形式ファイルからHTML5文書を作る |
xxx.less | xxx.css | lessc | LESSソースからCSSファイルを作る |
xxx.sass | xxx.css | sass | SCSSソースからCSSファイルを作る |
xxx.erl | xxx.beam | erlc | ErlangソースをBEAMファイルにコンパイルする |
xxx.hs | xxx (実行形式) | ghc | Haskellソースをコンパイルする |
xxx.ml | xxx (実行形式) | ocamlc | OCamlソースをコンパイルする |
xxx.c | xxx (実行形式) | ${CC} | Cソースをコンパイルする |
xxx.cpp | xxx (実行形式) | ${CXX} | C++ソースをコンパイルする |
xxx.d | xxx (実行形式) | gdc | Dソースをコンパイルする |
xxx.m | xxx (実行形式) | gcc | Objective-Cソースをコンパイルする |
xxx.java | xxx.class | javac | Javaソースをclassファイルにコンパイルする |
xxx.scala | xxx.class | scalac | Scalaソースをclassファイルにコンパイルする |
xxx.v | xxx (実行形式) | iverilog | Verilogソースをコンパイルする |
xxx.cs | xxx.exe | dmcs | C#.monoソースをexeファイルにコンパイルする |
xxx.fs | xxx.exe | fsharpc | F#.monoソースをexeファイルにコンパイルする |
xxx.dot | xxx.png | dot | DOT形式(Graphviz)ファイルからPNG画像ファイルを作る |
xxx.ry | xxx.rb | racc | Racc文法ファイルからRubyスクリプトを作る |
(注意)
Makefile のコマンド行の先頭はタブである必要があります。
コピー&ペーストをするとタブの部分がスペースに置き換わってしまうかも知れません。
その場合は以下のようにしてタブを復元してください。
$ sed 's/^ /\t/' Makefile >tmp # 変換するスペースは4つです (「s/^ /\t/」の部分)
$ mv tmp Makefile
# !/usr/bin/make -f
# ----------------------------------------------------------------------
#
# javaScript
#
COFFEE := coffee
COFFEEFLAGS := -b
TARGETS += ${patsubst %.coffee, %.js, ${wildcard *.coffee}}
.SUFFIXES : .js .coffee
%.js : %.coffee
${COFFEE} ${COFFEEFLAGS} -c $<
# ----------------------------------------------------------------------
#
# HTML/XHTML/GOML
#
HAML := haml
HAMLFLAGS := -q
XHAMLFLAGS := ${HAMLFLAGS}
GHAMLFLAGS := ${HAMLFLAGS}
MARKDOWN := markdown
MDFLAGS :=
TARGETS += ${patsubst %.haml, %.html, ${wildcard *.haml}} \
${patsubst %.md, %.html, ${wildcard *.md}} \
${patsubst %.xhaml, %.xhtml, ${wildcard *.xhaml}} \
${patsubst %.ghaml, %.goml, ${wildcard *.ghaml}}
.SUFFIXES : .html .haml \
.md \
.xhtml .xhaml \
.goml .ghaml
%.html : %.haml
${HAML} ${HAMLFLAGS} $< $@
%.xhtml : %.xhaml
${HAML} -f xhtml ${XHAMLFLAGS} $< $@
%.goml : %.ghaml
${HAML} ${GHAMLFLAGS} $< $@
%.html : %.md
echo '<!DOCTYPE html>' >$@
echo '<meta charset="UTF-8">' >>$@
echo '<title></title>' >>$@
echo '' >>$@
${MARKDOWN} ${MDFLAGS} $< >>$@
#
# CSS
#
LESSC := lessc
LESSFLAGS :=
SASS := sass
SCSSFLAGS :=
SASSFLAGS := ${SCSSFLAGS}
TARGETS += ${patsubst %.less, %.css, ${wildcard *.less}} \
${patsubst %.scss, %.css, ${wildcard *.scss}}
.SUFFIXES : .css .less \
.scss
%.css : %.less
${LESSC} ${LESSFLAGS} $< $@
%.css : %.scss
${SASS} ${SASSFLAGS} $<:$@
# ----------------------------------------------------------------------
#
# Erlang
#
ERLC := erlc
ERLFLAGS :=
TARGETS += ${patsubst %.erl, %.beam, ${wildcard *.erl}}
.SUFFIXES : .beam .erl
%.beam : %.erl
${ERLC} ${ERLFLAGS} $<
# ----------------------------------------------------------------------
#
# Haskell
#
GHC := ghc
GHCFLAGS :=
TARGETS += ${patsubst %.hs, %, ${wildcard *.hs}}
.SUFFIXES : .hs
% : %.hs
${GHC} ${GHCFLAGS} -o $@ $<
#
# OCaml
#
OCAMLC := ocamlc
OCAMLFLAGS :=
TARGETS += ${patsubst %.ml, %, ${wildcard *.ml}}
.SUFFIXES : .ml
% : %.ml
${OCAMLC} ${OCAMLFLAGS} -o $@ $<
# ----------------------------------------------------------------------
#
# C/C++
#
TARGETS += ${patsubst %.c, %, ${wildcard *.c}} \
${patsubst %.cpp, %, ${wildcard *.cpp}}
.SUFFIXES : .c \
.cpp
# ----------------------------------------------------------------------
#
# D
#
GDC := gdc
GDCFLAGS :=
TARGETS += ${patsubst %.d, %, ${wildcard *.d}}
.SUFFIXES : .d
% : %.d
${GDC} ${GDCFLAGS} -o $@ $<
# ----------------------------------------------------------------------
#
# Objective-C
#
OBJCC := gcc
OBJCFLAGS :=
TARGETS += ${patsubst %.m, %, ${wildcard *.m}}
.SUFFIXES : .m
% : %.m
${OBJCC} ${OBJCFLAGS} -o $@ $<
# ----------------------------------------------------------------------
#
# Java/Scala
#
JAVAC := javac
JAVAFLAGS :=
SCALAC := scalac
SCALAFLAGS :=
TARGETS += ${patsubst %.java, %.class, ${wildcard *.java}} \
${patsubst %.scala, %.class, ${wildcard *.scala}}
.SUFFIXES : .class .java \
.scala
%.class : %.java
${JAVAC} ${JAVAFLAGS} $<
%.class : %.scala
${SCALAC} ${SCALAFLAGS} $<
# ----------------------------------------------------------------------
#
# Verilog
#
IVERILOG := iverilog
IVERILOGFLAGS :=
TARGETS += ${patsubst %.v, %, ${wildcard *.v}}
.SUFFIXES : .v
% : %.v
${IVERILOG} ${IVERILOGFLAGS} -o $@ $<
# ----------------------------------------------------------------------
#
# C#/F# (.mono)
#
DMCS := dmcs
DMCSFLAGS :=
FSHARPC := fsharpc
FSHARPFLAGS :=
TARGETS += ${patsubst %.cs, %.exe, ${wildcard *.cs}} \
${patsubst %.fs, %.exe, ${wildcard *.fs}}
.SUFFIXES : .exe .cs \
.fs
%.exe : %.cs
${DMCS} ${DMCSFLAGS} $<
%.exe : %.fs
${FSHARPC} ${FSHARPFLAGS} $<
# ----------------------------------------------------------------------
#
# Graphviz
#
DOT := dot
DOTFLAGS :=
TARGETS += ${patsubst %.dot, %.png, ${wildcard *.dot}}
.SUFFIXES : .png .dot
%.png : %.dot
${DOT} ${DOTFLAGS} -Tpng -o $@ $<
# ----------------------------------------------------------------------
#
# Racc
#
RACC := racc
RACCFLAGS := -g
TARGETS += ${patsubst %.ry, %.rb, ${wildcard *.ry}}
.SUFFIXES : .ry .rb
%.rb : %.ry
${RACC} ${RACCFLAGS} -o $@ $<
# ======================================================================
#
# dependencies
#
.PHONY: build clean
build : ${TARGETS}
clean :
${RM} ${TARGETS}