移植性の高い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ソフトウェアプログラミング」、?年
No.2
- 回答日時:
たいへんよく調べられているようなので、より良い方法がありそうですが、そこまでMakefileを複雑にさせる方法もありですが、
ご自身のソフトを広く配布するのでなければ、
makefile.B
から
makefile.GCC
を自動生成するくらい、あなたなら簡単そうに思えます。
ご助言ありがとうございます。
>makefile.GCC
>を自動生成する
ということですが、autoconfとautomakeを使うという解釈でよろしいでしょうか?
まったく使用したことがないので試してみたのですが、どちらもGNU系のツールで、Windows環境に単独では対応してないようです。
msys用のパッケージがあったのでインストールして、今やり方を調べているところですが、一筋縄ではいきそうもありません。
現在、Tacosan氏の助言を参考に、3種類のmakefileを作るという方法で対応してみました。
時間はかかりますが、せっかくですので、autoconfもできるようになっておこうと思います。
ありがとうございました。
No.1ベストアンサー
- 回答日時:
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
回答ありがとうございます。
依存関係ファイルを共有にし、それを読み込むファイルを切り替えるということですね?
調べてみたところ、
GNUMakeは、「GNUmakefile」、「makefile」、「Makefile」の順でファイルを探す。
それ以外のmakeは「makefile」か「Makefile」というファイルを探す。
ということですので、この方法で良さそうです。考えてみたら、includeされるファイルを切り替えるより、最初に読み込まれるファイルを切り替えて共有の依存関係を読み込むほうが自然ですね・・・。
ご助言を参考に以下の3ファイルを作り、現在正常に動いております。
GNUmakefile ・・・・・GNUMakeに読み込まれて、GNUMake用のマクロを設定し、依存関係ファイルComonMakefile.inを読み込む。
makefile ・・・・・・BorlandMakeに読み込まれて、BMake用のマクロを設定し、ComonMakefile.inを読み込む。
ComonMakefile.in・・・依存関係と、マクロを使った明示的な構築ルール、サフィックスルールを設定する。
これでうまくいきそうです。ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 英語 ①普通名詞の所有格+②普通名詞で、①普通名詞に定冠詞の意味を付加したい場合の表現方法等について 23 2022/09/30 12:47
- 英語 「再び」の接頭辞”re-"を有する単語と文末に"again"を付けた表現のニュアンスに違いについて 1 2022/12/13 12:40
- その他(Microsoft Office) エクセルのマクロについて教えてください。 5 2023/01/21 09:39
- Excel(エクセル) 【マクロ】フォルダAからダBへファイルを、ファイルの更新日時の条件で、1つづつ移動するには? 3 2022/08/25 09:56
- 英語 There are various anatomical and mucogingival cond 3 2022/05/05 10:28
- C言語・C++・C# Makefileのechoの展開について 2 2022/07/26 07:35
- UNIX・Linux Linuxについて質問です。 以下のような設定をしたMakefileを作成するにはどう記述すればよい 1 2023/02/03 20:10
- その他(ソフトウェア) Makefileが実行できない 2 2022/07/28 23:49
- Visual Basic(VBA) 特定の文字を簡単な操作で半角スペースに変換するか削除したい 2 2022/11/01 10:35
- Visual Basic(VBA) VBA アドインについて お詳しい方 ご教授をお願いします。 相談事項 現在以下の対応を実施した所、 1 2022/11/02 16:53
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
0除算して、落ちるプログラムと...
-
コンパイラについて
-
コンパイルできない
-
変数(関数)名の頭に_
-
C++ で、「)」が必要 というエ...
-
C言語
-
Eclipseの環境設定について
-
sprintfを用いたフォーマット文...
-
io.hをincludeするとそのような...
-
コンパイラの制限 : ヒープの領...
-
C言語のオススメ統合開発環境(...
-
FORTRANとC++の連動について
-
コンパイラフラグ(compiler fla...
-
C言語のワーニングメッセージの...
-
秀丸エディタでのC言語環境(ハ...
-
ブラウザ上でクライアント側で...
-
65536は2の何乗なのでしょうか?
-
あるプログラムのコマンドライ...
-
VBAでユーザーフォームが自動的...
-
正しい五十音順について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
0除算して、落ちるプログラムと...
-
C++ で、「)」が必要 というエ...
-
コンパイルできない
-
C++でアボート(Abort)で処理が...
-
変数(関数)名の頭に_
-
Visual C++とVisual C++.NETの違い
-
Eclipseの環境設定について
-
volatile修飾について
-
コンパイラについて
-
linuxのセキュリティ対策と致し...
-
__extension__
-
io.hをincludeするとそのような...
-
コンパイラフラグ(compiler fla...
-
PICマイコンによる乱数の表示に...
-
conio.h? curses.h?
-
【エラー】Cpadで初めてコンパイル
-
ABAQUS ユーザーサブルーチン...
-
関数の戻り値による変数の初期化
-
Delphiの逆コンパイル
-
プリコンパイラとは?
おすすめ情報