FreeBSDもZRouterもmakefileでのビルドなので、思いついたことを書き留めておきます。もちろんBSD makeの話です。
:で変数を修飾パターンに従って変更することができます。
例えばVAR=abcで${VAR:Mab}はabになりVAR=xyzだとxyzのままになります。
修飾パターンはマッチや非マッチ、置換などがあります。
.if ${.TARGETS:Nall} == ""
STR="YES ALL"
.else
STR="NOT ALL"
.endif
all:
@echo "${STR}"
@echo "${.TARGETS:Nall}"
@echo "${.TARGETS:Mall}"
all2:
@echo "${STR}"
@echo "${.TARGETS:Nall}"
@echo "${.TARGETS:Mall}"
all3: all
.TARGETSはターゲットで、:Nは:Mの反対で、マッチしたらなくなります。
実行してみます。
% make
YES ALL
all
% make all
YES ALL
all
% make all2
NOT ALL
all2
% make all3
NOT ALL
all3
all3はallを実行しているのですが、コンテキストが違う状態になります。
最初に書かれるデフォルトがallでないとまた違った動きになるので注意が必要です。
書いてから気がついたが、これでも同じです。
.if ${.TARGETS} == "all"
STR="YES ALL"
.else
STR="NOT ALL"
.endif
こっちのほうが明示的だし、:Nとか:Mじゃないほうが良い気がします。:Nとか:Mもうまい使い方ってあるんでしょうか?
Open Watcom v2のmakefileでBSD makeでエラーが起きていました。
cretype.exe : ../c/cretype.c
$(CC) -I../../watcom/h -o $@ $<
$<はc.oのような暗黙(implicit)のルールでしか使えないようです。
並列実行
makeコマンドはjオプションで並列実行できます。
たとえばa.cとb.cからa.outを作るときにはa.cのコンパイルとb.cのコンパイルは並列してできます。またa.outはa.oとb.oができた後にリンクを実行しなければなりません。
以下のようなMakefileではいくらjオプションをつけても並列実行されません。
test1:
cc -c a.c
cc -c b.c
cc -o a.out a.o b.o
並列実行させるためには以下のように書きます。
test2: a.o b.o
cc -o a.out a.o b.o
c.o:
cc -c $<
これでa.oとb.oのコンパイルは並列実行され、その後にリンクが行われます。
% make -j2 test2
--- a.o ---
--- b.o ---
--- a.o ---
cc -O2 -pipe -c a.c -o a.o
--- b.o ---
cc -O2 -pipe -c b.c -o b.o
--- test2 ---
cc -o a.out a.o b.o
もちろん暗黙のルールでなくそれぞれターゲットを書いても良いです。
何らかの理由で、a.o,b.oをシーケンシャルに処理したい場合は以下のような行を追加します。
.ORDER: a.o b.o
実行するとこんなです。
% make -j2 test2
--- a.o ---
cc -O2 -pipe -c a.c -o a.o
--- b.o ---
cc -O2 -pipe -c b.c -o b.o
--- test2 ---
cc -o a.out a.o b.o
マクロ
FreeBSDではいろいろマクロがあり、下記だけでhello.cからプログラムが作れます。
PROG=hello
MK_MAN=no
.include <bsd.prog.mk>
マクロのファイルは/usr/share/mkにあります。
makeすると同じディレクトリでバイナリが作れますが、bsd.obj.mkには以下のように書いてあります。
#
# Warn of unorthodox object directory.
#
# The following directories are tried in order for ${.OBJDIR}:
#
# 1. ${MAKEOBJDIRPREFIX}/`pwd`
# 2. ${MAKEOBJDIR}
# 3. obj.${MACHINE}
# 4. obj
# 5. /usr/obj/`pwd`
# 6. ${.CURDIR}
#
# If ${.OBJDIR} is constructed using canonical cases 1 or 5, or
# case 2 (using MAKEOBJDIR), don't issue a warning. Otherwise,
# issue a warning differentiating between cases 6 and (3 or 4).
#
ソースのディレクトリにobjディレクトリがあれば、そこにオブジェクトが作られますが、以下を実行すると/tmpにpwdのディレクトリがなけれは同じディレクトリにオブジェが作られます。
% env MAKEOBJDIRPREFIX=/tmp make
ディレクトリを作るのは下記でできます。
% env MAKEOBJDIRPREFIX=/tmp make obj
こでれでmakeすれば/tmp/の下にオブジェクトが作られます。
オブジェクトの場所は以下の方法で確認できます。
% make whereobj
shスクリプト
以下のようにすると、da0がある場合のみ実行されます。
VER="10.0"
all:
@(if [ -e /dev/da0 ]; then \
${MAKE} nbflash ;\
else \
echo "No media" ;\
fi)
nbflash:
sudo dd if=$(VER)/armv7.img of=/dev/da0 bs=1m conv=sync
sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/da0 bs=1k seek=8 conv=sync
Malformed conditional
定義されてないものを評価すると発生するようです。先に定義をdefined()で確認してから評価するのが良いです。