アプリ版:「スタンプのみでお礼する」機能のリリースについて

移植性の高いmakefileの作成

C言語で書かれたソースファイルをmakeツールでビルドしています。
もともとコンパイラとして「Borland C++ Compiler 5.5.1」を使用し、Borland C++ 同ツール付属のmakeツール「MAKE Version 5.2」を使用していました。
makeの基本文法は理解しており、Borlandのコンパイラを使用している間は特に問題ありませんでした。
しかし最近、新たにGCC系列のMinGWという開発環境一式と、補助ツールMSYSを導入し、既存のmakefileをGCCおよびGNUmakeに対応させることにしました。
具体的には、
GMAKEを起動した場合はgccでコンパイルする。
Borland make を起動した場合にはbcc32でコンパイルする。
という切り替えを同一のmakefileで行おうと考えました。
しかし、ここで問題が発生しました。
makeの依存関係部分はborland付属make(以下Bmakeとします)とGNUmakeであまり違いはないのですが、単一のmakefileで対応しようとすると、どうしてもコンパイラオプションやコンパイルコマンドを切り替える部分が必要です。しかし、ifdefやincludeディレクティブに関してはお互いにまったく互換性がなく、片方のmakeで有効なフラグをつかってifdefで分岐しようとしても、もう片方では完全に文法エラーです。
例えば、ifdefやincludeディレクティブは、Bmakeでは先頭に!が必要ですが、GNUmakeには必要ありません。
以下の書籍でポータブルなmakefileの記述に関していろいろ調べたのですが、Bmakeの特殊な文法についての言及がなく、対応策が見つかりません。

様々な環境でビルドされるFireFox3.0のソースコードも参考にしようとmakefileと思われるファイルを全て検索したところ、1769個ほど見つかりました。
その中で!ifdefディレクティブを使用しているのは極わずかで、Makefile.winという名称のものがいくつかあっただけでした。
しかもそれらは最後の方にincludeディレクティブも使っていました。
例えば、MozillaFirefox3.0のソースコードにあるmakefaileの内、firefox-3.0-source.tar\mozilla\dbm\src\Makefile.winは「include <$(DEPTH)/config/rules.mak>等」、という一文がある一方、その他のifなどのディレクティブは頭に!をつけられており、全体としてはBmake(多分ターゲットはMSVC++だと思いますが。)です。
これはBmakeではエラーになるはずなのですが、動作機構は不明です。

また、条件付マクロというテクニックで、ある値が定義されていれば左値を、定義されてなければ右値を使ってマクロ置換するテクニックがあったので、これでディレクティブをマクロ置換してやろうと考えました。しかし、ディレクティブをマクロ定義することはできないようでこれも失敗しています。

#INCLUDE というマクロを定義して、
INCLUDE = $(_GNUMAKE_?include:!include)
#マクロをディレクティブ命令として使う
$(INCLUDE) testmake.mk

それぞれのmake専用makefileを作るのは簡単ですが、新しいプログラムを追加するたびに複数のmakefileを書き直すのは避けたいのです。
長々と書きましたが、解決策として次の2つのいずれかのようなものがあれば教えていただきたいです。

1. ifやincludeディレクティブに代わる、GNUmakeとBmake両方に使えるテクニック。
2. 起動したmakeによって条件分岐、もしくは読み込むファイルを切り替えるテクニック。

よろしくお願いいたします。

開発環境
OS: winXP
コンパイラ: 「Borland C++ Builder 6.0」「Borland C++ Compiler 5.5.1」「gcc version 3.4.5 (mingw special)」
make: 「MAKE Version 5.2 (C++ BuilderとC++ Compiler 5.5.1はおなじmakeを使用している模様)」「GNU Make version 3.79.1」

参考文献
1. 「GNU Make 第3版」オライリージャパン、2005年
2. 「C言語逆引き大辞典」秀和システム、2003年
3. 「GNUソフトウェアプログラミング」、?年

A 回答 (2件)

たいへんよく調べられているようなので、より良い方法がありそうですが、そこまでMakefileを複雑にさせる方法もありですが、


ご自身のソフトを広く配布するのでなければ、
makefile.B
から
makefile.GCC
を自動生成するくらい、あなたなら簡単そうに思えます。
    • good
    • 0
この回答へのお礼

ご助言ありがとうございます。
>makefile.GCC
>を自動生成する
ということですが、autoconfとautomakeを使うという解釈でよろしいでしょうか?
まったく使用したことがないので試してみたのですが、どちらもGNU系のツールで、Windows環境に単独では対応してないようです。
msys用のパッケージがあったのでインストールして、今やり方を調べているところですが、一筋縄ではいきそうもありません。
現在、Tacosan氏の助言を参考に、3種類のmakefileを作るという方法で対応してみました。
時間はかかりますが、せっかくですので、autoconfもできるようになっておこうと思います。
ありがとうございました。

お礼日時:2010/07/28 17:03

GNU make 用には GNUmakefile という名前にするのはどうだろうか.


もちろん共通なものは両方から include するようにして.

この回答への補足

今後、同じ内容で質問される方のために補足で情報をまとめときます。参考までに。
同じ環境内でGNUMakeとBorlandMake(MSVC++のmakeであるnmakeとほぼ互換)を使用できるようにする。
依存関係ファイルは書式が共通なので、ひとつのファイルにまとめる。ファイル名「ComonMakefile.in」。
このファイルを読み込むmakeファイルを2系統作る。ファイル名指定無しで、デフォルトで読み込むファイル名の違いを使って、二つのmakeを使い分ける。
GNUMakeは最初に「GNUmakefile」というファイルを読み込むので、このファイルにGNUmake特有の設定やincludeを行う。
Borland Makeは最初に「makefile」を読み込む(Win環境ではMakefileと同じ)ので、このファイルにBmake特有の設定や !include などを行う。
以下に3つのファイルの例を挙げときます。

「GNUmakefile」

# コンパイルとリンク
CC = gcc -o
#コンパイルのみ(compile only)
CCO = gcc -c -o
# リソースの付加
RC = #
# ファイルの消去
RM = rm -f
# 通常使うプログラムの依存関係makefile
include ComonMakefile.in
# 一個ずつコンパイルするときに、フルネームでなく短いターゲット名を使うためのメイクファイル
include sname.mk
# 正式ではない、テスト段階のプログラムのメイクファイル
include testmake.mk

「makefile」

# コンパイルとリンク
CC = bcc32 -e
# コンパイルのみ(compile only)
CCO = bcc32 -c -o
# リソースの付加
RC = brc32 -v
# ファイルの消去
RM = del
# 通常使うプログラムの依存関係makefile
!include ComonMakefile.in
# 一個ずつコンパイルするときに、フルネームでなく短いターゲット名を使うためのメイクファイル
!include sname.mk
# 正式ではない、テスト段階のプログラムのメイクファイル
!include testmake.mk


「ComonMakefile.in」

# サフィックスルール
.c.exe:
____CC $(*<).c

ALLEXE = hello.exe helloC.exe
all: $(ALLEXE)
clean:
____$(RM) *.obj
____$(RM) *.tds
____$(RM) icon\*.res
____$(RM) *.bak

hello.exe: hello.obj Lib-helloprint.obj
____$(CC)hello.obj Lib-helloprint.obj
helloC.exe: helloC.obj Lib-helloprint.obj
____$(CC)helloC.obj Lib-helloprint.obj

# 本体の依存関係
hello.obj: hello.c
____$(CCO)hello.obj hello.c
helloC.obj: helloC.c
____$(CCO)helloC.obj helloC.c

# ライブラリの依存関係

Lib-helloprint.obj: Lib-helloprint.c
____$(CCO)Lib-helloprint.obj Lib-helloprint.c Lib-testprint.h

補足日時:2010/07/28 17:12
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
依存関係ファイルを共有にし、それを読み込むファイルを切り替えるということですね?
調べてみたところ、
GNUMakeは、「GNUmakefile」、「makefile」、「Makefile」の順でファイルを探す。
それ以外のmakeは「makefile」か「Makefile」というファイルを探す。
ということですので、この方法で良さそうです。考えてみたら、includeされるファイルを切り替えるより、最初に読み込まれるファイルを切り替えて共有の依存関係を読み込むほうが自然ですね・・・。

ご助言を参考に以下の3ファイルを作り、現在正常に動いております。
GNUmakefile ・・・・・GNUMakeに読み込まれて、GNUMake用のマクロを設定し、依存関係ファイルComonMakefile.inを読み込む。
makefile ・・・・・・BorlandMakeに読み込まれて、BMake用のマクロを設定し、ComonMakefile.inを読み込む。
ComonMakefile.in・・・依存関係と、マクロを使った明示的な構築ルール、サフィックスルールを設定する。

これでうまくいきそうです。ありがとうございました。

お礼日時:2010/07/28 17:01

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!