August 28, 2006

makeでソースとバイナリを違うディレクトリに

先日、室内飛行機の自律飛行プロジェクトの成果物としてH8/3694のフレームワークを公開しましたが、その際、自動コンパイル(ビルド)をどのように構成するかで少し悩みました。

オープンソース系の大きなプロジェクト(apacheなど)をみると、ソースとそのコンパイル結果であるバイナリは同じ場所に展開されるのが常套手段のようです。これはコンパイラが分割コンパイルをサポートしており、ビルドを行うのにメジャーなプログラムであるmakeがこのような方法を簡単に実現できるためだと思います。
例えば、あるフォルダ内にあるc言語のソースを全てまとめてhogeというプログラムを生成するmakeスクリプト(Makefile)は、以下のように簡単に書けます。

TARGET = hoge
SRCS = $(shell ls *.c)
OBJS = $(SRCS:.c=.o)

all : $(TARGET)

%.o : %.c
    $(CC) -c $(CFLAGS) -o $@ $<

$(TARGET) : $(OBJS)
    $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^

clean :
    rm -f $(OBJS) $(TARGET)

.PHONY: all clean

このスクリプトを使ってmakeを実行すると、(ソース).cは同じディレクトリに分割コンパイルされて(ソース).oというバイナリとして生成されます。そして(ソース).oが合わさって最終的にhogeという目的のブツが手に入ります。

ところがソースを書くのに別にeclipseなどの統合開発環境(IDE)を使用している場合、ソースとバイナリが同じディレクトリにあると、使用上鬱陶しいことがあります(例えばファイルを選択する際など)。eclipseならフィルターで消すことができますが、根本的な解決にはならないので、Visual Studioのようにバイナリを別ディレクトリに生成した方がよいのではないかと考えました。

続きをどうぞ。

そのような場合は、次のようなMakefileを書けばうまくいきます。

TARGET = hoge
SRCS = $(shell ls *.c)
OBJS = $(SRCS:.c=.o)

BUILD_DIR = build_by_$(CC)

all : $(BUILD_DIR) $(patsubst %,$(BUILD_DIR)/%,$(TARGET))

$(BUILD_DIR) :
    mkdir $(BUILD_DIR)

$(BUILD_DIR)/%.o : %.c
    $(CC) -c $(CFLAGS) -o $@ $<

$(BUILD_DIR)/$(TARGET) : $(patsubst %,$(BUILD_DIR)/%,$(OBJS))
    $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^

clean :
    rm -r $(BUILD_DIR)

.PHONY: all clean

ここでpatsubstという組込み関数が活躍しています。これは文字列を編集する関数の一つで、makeの機能です。詳細はgmakeのマニュアル Functions for Transforming Textをどうぞ。他にも色々な組込み関数があるようです。

こうすると生成されるものは全てbuild_by_$(CC)の中にでてくるので、管理がしやすくなるのではないでしょうか。リビルドの前処理はそのディレクトリを消せばいいだけですし、CVSやSVNといったプロジェクト管理ツールとの併用もしやすくなると思います。

なおH8/3694のフレームワークではさらに凝って、別ディレクトリにバイナリを生成することを多段makeで実現しています。ダウンロードはこちらから。

23:22 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク | この記事をdel.icio.usでブックマーク | トラックバック
このエントリーのトラックバックURL: http://fenrir.naruoka.org/mt/mt-tb.cgi/512
コメント
コメントする









名前、アドレスを登録しますか?
(次回以降コメント入力が楽になります)
  • 匿名でのコメントは受け付けておりません。
  • 名前(ハンドル名可)とメールアドレスは必ず入力してください。
  • メールアドレスを表示されたくないときはURLも必ず記入してください。
  • コメント欄でHTMLタグは使用できません。
  • コメント本文に日本語(全角文字)がある程度多く含まれている必要があります。
  • コメント欄内のURLと思われる文字列は自動的にリンクに変換されます。