makeの覚書

 
tiutiu.net/ プログラム/supply/make/
2007/7/11
もっともシンプルなmakefile
a.out:
    gcc hello.c

空行には, tab, 空白などの空白文字はない。入れるとエラー。 一段下がっている行の先頭にはtabがある。

サフィックス

定型の操作を簡潔に表現する方法。phpファイルからhtmlファイルを作成 するとする。makefileにはphpとhtmlが拡張子であることと, 操作方法を 教える。

# htmlとphpは拡張子である。
.SUFFIXES: .html .php

# .phpから.htmlを作成する。
.php.html:
	php $< > $@

all: index.html foo.html
$<, $@は自動変数(Automatic Variables)。$<が入力で, $@が作成対象。
foreach

いくつかのファイルを一つづつ操作したいとき。たとえば, いくつかの別のディレクトリのmakefileを実行したいとき。

SUBDIR=foo bar

all:
    list="$(SUBDIR)"; \
    for i in $$list; do \
        echo $$i; \
        cd $$i; make; cd ..; \
    done

各コマンド行の最後の"\"を抜かすと動かないので注意。最後の 行のみ不要。また, 各コマンドの最後の";"を抜かすと動かないので 注意。最後のコマンドのみ不要。なお, 当方の環境はbashで確認 しています。csh, tschで動かした場合は確認していません。

条件分岐
STR=

all: printstr createdir

# STRになにか設定されていたら表示する。
printstr:
	@if test "$(STR)" != ""; then \
        echo "$(STR)"; \
    fi

# ディレクトリfooがなければfooを作成
createdir:
    @if [ ! -d foo ]; then \
        mkdir foo; \
        echo 'create dir foo'; \
    fi

# 本来はfooを作成のターゲットにすべき
ワイルドカード

ディレクトリ中のファイル命の取得などが可能。

objects=$(patsubst %.php, %.html, $(wildcard *.php))
no_public=foo.html index.html

all:
    echo $(objects)
    echo $(wildcard *.php)
    echo $(wildcard *.html)
    echo $(filter-out $(no_public), $(objects))

patsubstrは文字を変換するための文字関数(text function)。 ... %.php, %.html ... で拡張子をphpからhtmlに変換している。

wildcardで指定された文字にマッチするファイルの取得。 $(wildcard *.php)でディレクトリ中の拡張子phpのファイルを 全て空白区切りで列挙。

filter-outは第一引数の文字(空白区切りで複数可能)を第二引数から 取り除く文字関数。objectsにfoo.html, index.htmlがあっても no_publicで指定されているので表示されない。

表示の抑制

原則としてmakeにて実行される命令はコンソールに表示されるが, それを抑制したい場合は, 命令の先頭に@をつける。

all:
    @echo 'hello world'
エラーの無視

原則としてmakeはエラーが起きたところで処理を中断する。 たとえば存在しているディレクトリを作成しようと するとエラーになる。 それを無視するには命令の先頭に"-"をつける。

all:
    -mkdir foo
    @echo 'create directory foo'

ここでは存在しているディレクトリを作成しようとしてエラーに しているが, これは例のためであって, 本来は 作成するディレクトリをターゲットにするか, 先にディレクトリの存在をチェックすべきである。

makefileの分割

makefile

include def.mk
all:
	echo $(DEF1)

def.mk

DEF1 = hello make

実行結果

$ make
echo hello make
hello make
Error 57

現在は発生しないようだが, 以前makefile中でリダイレクトを使用すると Error 57というエラーが出ることがあった。その場合, makefileの先頭に

SHELL=/bin/bash

と書くと直った。makefile全体の例。

SHELL=/bin/bash
all:
	echo 'hello' > build.log

Google