LoginSignup
1
0

makefileのいろいろ

Last updated at Posted at 2019-05-08

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でエラーが起きていました。

postmake
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からプログラムが作れます。

Makefile
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()で確認してから評価するのが良いです。

1
0
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
1
0