LoginSignup
7
5

More than 5 years have passed since last update.

とりあえず用 Makefile

Last updated at Posted at 2014-12-25

とりあえず用 Makefile

make はビルドツールです。
私は CoffeeScript の JavaScript への変換などに make コマンドを使っています。

私が make にさせたい動作は、

拡張子が「.coffee」のファイルがあったら、coffee コマンドでそれを JavaScript に変換する

というものです。
要は、myscript.coffee などを書いたとき、とりあえず make しておけば myscript.js が得られるようにしたいのです。

make の動作を制御するには、その設定を Makefile に記述する必要があります。
本稿は、私が使っている Makefile の紹介です。

make の詳細については以下を参照ください。
- Manpage of 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
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}
7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5