移植性の高いmakefileの作成

このQ&Aのポイント
  • C言語ソースファイルをmakeツールでビルドする際の移植性向上のための問題について。BorlandのmakeツールとGCC系列のMinGWを使用する場合の問題点と対策方法を検討している。
  • BorlandのmakeツールとGCC系列のMinGWを同一のmakefileで対応する方法について検討している。ifdefやincludeディレクティブの互換性の問題があり、条件分岐やファイルの切り替えのテクニックを探している。
  • FireFox3.0のソースコードを参考に移植性の高いmakefileの記述方法を模索している。ifdefやincludeディレクティブの違いによる文法エラーの解決策を求めている。条件付マクロのテクニックも試したが失敗している。
回答を見る
  • ベストアンサー

移植性の高いmakefileの作成

移植性の高い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ソフトウェアプログラミング」、?年

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

GNU make 用には GNUmakefile という名前にするのはどうだろうか. もちろん共通なものは両方から include するようにして.

kolona
質問者

お礼

回答ありがとうございます。 依存関係ファイルを共有にし、それを読み込むファイルを切り替えるということですね? 調べてみたところ、 GNUMakeは、「GNUmakefile」、「makefile」、「Makefile」の順でファイルを探す。 それ以外のmakeは「makefile」か「Makefile」というファイルを探す。 ということですので、この方法で良さそうです。考えてみたら、includeされるファイルを切り替えるより、最初に読み込まれるファイルを切り替えて共有の依存関係を読み込むほうが自然ですね・・・。 ご助言を参考に以下の3ファイルを作り、現在正常に動いております。 GNUmakefile ・・・・・GNUMakeに読み込まれて、GNUMake用のマクロを設定し、依存関係ファイルComonMakefile.inを読み込む。 makefile ・・・・・・BorlandMakeに読み込まれて、BMake用のマクロを設定し、ComonMakefile.inを読み込む。 ComonMakefile.in・・・依存関係と、マクロを使った明示的な構築ルール、サフィックスルールを設定する。 これでうまくいきそうです。ありがとうございました。

kolona
質問者

補足

今後、同じ内容で質問される方のために補足で情報をまとめときます。参考までに。 同じ環境内で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

その他の回答 (1)

  • noyuo
  • ベストアンサー率39% (33/84)
回答No.2

たいへんよく調べられているようなので、より良い方法がありそうですが、そこまでMakefileを複雑にさせる方法もありですが、 ご自身のソフトを広く配布するのでなければ、 makefile.B から makefile.GCC を自動生成するくらい、あなたなら簡単そうに思えます。

kolona
質問者

お礼

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

関連するQ&A

  • C言語のmakefileについて

    C言語のmakefileについて質問です。 例えば下記makefileでは、“CC”というマクロを“gcc”という文字列で再定義しています。 しかし中には(1)『CC = gcc』という定義なしでいきなり(2)『$(CC) -o hello $(objs)』 でコンパイルしているmakefileを見るのですが、その場合(2)は何でコンパイルされているのでしょうか。($(CC)の中身はCC??GCC?ACC??) ※下記ターゲット名等はサンプルです。 ------------------ # Makefile objs = hello.o edajima.o CC = gcc hello: $(objs) $(CC) -o hello $(objs) .PHONY: clean clean: $(RM) hello $(objs)

  • gdbデバッグのためのmakefile作成

    現在Ubuntu Linuxでgccプログラミングを行っています。現在、ソースコードをいくつかのファイルに分割して作成しています。コンパイル時はmakefileを使用してmakeして実行ファイルを作成しています。 現在のプログラムをgdbでデバッグできるようにしたいと思っているのですが、 その場合のmakefileはどのようにして書けば良いのかをご教示頂きますよう、お願い致します。 現在のmakefile内容 https://sourceforge.jp/projects/cc1101driver/scm/svn/blobs/2319/trunk/20140411/Makefile #test #CC = gcc #test:main.c event.c exe: main.o event.o env.o audio.o task.o comm.o menu_show_status.o gcc -o exe main.o event.o env.o audio.o task.o comm.o menu_show_status.o -lpthread main.o:main.c gcc -c main.c event.o:event.c gcc -c event.c env.o:env.c gcc -c env.c audio.o:audio.c gcc -c audio.c task.o:task.c gcc -c task.c comm.o:comm.c gcc -c comm.c menu_show_status.o:menu_show_status.c gcc -c menu_show_status.c

  • ファイルをフォルダに入れて構造化する

    私は趣味でCプログラムをしているのですが、自分の書いたプログラムのファイルが多くなった場合フォルダにまとめたいのですが、メインのファイルと違う階層になるのでメインのファイルで #include hoge.h と書いても"インクルードファイル hoge.hが見つかりません"と出ます。 どうすればhoge.hをコンパイラが検索してくれるのでしょうか? Borland C++ Compiler,VC++でできる方法を教えてください(できれば両方がいいです) 環境はwindows ちなみにbcc developer という Borland C++ Compiler をGUIで操作できるツールを使ってます 宜しくお願いします

  • Makefile と <math.h>

    C言語初心者です,Vine Linuxを使用しています. Makefileを用いたコンパイルをしたいのですが,あるcコード中にある,「sqrt」でコンパイラからエラー警告が出ます. エラーコード: gcc -o p001 pMain001.o pIo001.o pFnc001.o pFnc001.o(.text+0x214): In function 'sqr_Rt': : undefined reference to 'sqrt' collect2: ld はステータス 1 で終了しました make: *** [p001] エラー 1 Makefile: #Makefile for p001 CC = gcc p001: pMain001.o pIo001.o pFnc001.c $(CC) -o p001 pMain001.o pIo001.o pFnc001.o pMain001.o: pMain001.c pIo001.c p001.h $(CC) -c pMain001.c pIo001.c pIo001.o: pIo001.c p001.h $(CC) -lm pIo001.o pIo001.c pFnc001.o: pFnc001.c p001.h $(CC) -c p001.o pFnc001.c プログラムの概要: p001.hには,構造体定義と関数プロトタイプ宣言. pIo001.cには,キーからの入力と,出力の関数. pFnc001.cにはp001.hにある定義を用いた関数があり,この中にsqrtを使う関数がある. pMain001.cではpIo001.cとpFnc001.cにある関数を利用し,入出力を行う. Makefileの記述が間違っているような気がしてならないんですが,何せ勉強不足なものでよくわかりません. <math.h>はp001.hでインクルードしていますが,これは違いますか? 長文を読んで下さってありがとうございます,「ココおかしい」などの指摘お待ちしています;;

  • BCC Developerについて。

    Borland C++ Compiler、BCC Developerを使って #include <stdio.h> void main(){ printf("Hello C world.\n"); } をメイクしてみたのですが、 インクルードファイル 'stdio.h' をオープンできない 、と表示されコンパイルできませんでした。 環境設定は、コンパイラにbbc32.exeを指定すればいいだけなんでしょうか?よろしくお願いします。

  • Makefileについて

    同じディレクトリに、同名のa.plとa.cファイルが存在します。 それぞれは単独では問題なく動きます。 しかし、Makefileを使ってこれらのファイルを一緒に実行させたいのですが、make allrunでa.pl、a.cが実行された後に make: *** [allrun] エラー 14 と出てしまいます。 結果的には全て実行できた形になるのですが、エラーと出ているのでどうも不安です。 勉強中の身なので説明がうまくいっていないと思いますが、どうやればよいのか教えてください。 Makefileの中身は CC = gcc all:a a a:a.c $(CC) -o a a.c -lm allrun:a a ./a.pl ./a.out clean: -rm ./a -rm ./a です。

    • ベストアンサー
    • Perl
  • Makefileについて

    makeファイルの書き方で悩んでいます。 makeファイルは書いたことがなく、ほとんど丸写しです。 私がしたいのは、 (1)run:部分で削除するファイルがなかった場合、エラーとなり次の行へ進みません。なくても(エラーでも/エラー回避して)次の行へ進む方法が知りたいです。 もうひとつは(2)run:部分で、cleanを実行し、makeしてrunを実行させる方法が知りたいです。 --------------以下、サンプルMakefileです。 CC = gcc OBJS = main.o sub.o PROG = test.exe .c.o: $(CC) -c $< -o $@ $(PROG) : $(OBJS) $(CC) $(OBJS) -o $(PROG) $(OBJS) : Makefile clean: rm -f *.o $(PROG) run: rm *.log <---- (1)ここでファイルがないとエラーで止まる $(PROG) all:   <-- (2)[clean]を実行して、makeして、[run]を実行させたい 以上です。

  • C++とmakefileの実行について

    人工知能の本を購入し、付属のCDにプログラムが入っておりました。プログラムには、C++でかかれておりと最後の方にmakefileというものが書かれており、どのように実行したらいいか困っております。コンパイラはBorlandのbcc55を使っております。学生で知識もないため、つたない質問で申し訳ないですが不明な点は質問など頂けると幸いです。みなさんよろしくお願いします。

  • 【エラー】Cpadで初めてコンパイル

    Cpad for Borlandで以下のようなソースを書きコンパイルをしましたが、失敗し、行き詰っております。 当方、初プログラミングに挑戦しております。 <環境> OS:XP(HOME) コンパイラ:Borland C++ Compiler エディタ:Cpad for Borland <動作状況> ソース: #include <stdio.h> int main ( void ) { printf(mori); return 0; } エラー情報: 「コンパイルに失敗しました。 ファイル"ファイル"D:\source\test1.exe"は存在しません」 参考情報(参考にならないかもしれませんが…): ・コンパイラはDドライブにインストールしております。 ・コンパイラのパスはD:\borland\bcc55\Bin\bcc32.exeです。 以上、よろしくお願いいたします。

  • 初めてのプログラミング

    学校の授業でC言語(C++ではありません)を勉強することになりました 学校ではvisual c++ 6.0を使用しています。 自宅のPCにも全く同じ物をDLしようとしましたがありませんでした。 そこでいろいろ調べてみて エディタ:CPad コンパイラ:Borland C++ Compiler をDLしてインストールしました。 エディタは問題なく使用できるのですがコンパイラをうまく使うことが出来ない為、実行も出来ません #include <stdio.h> int main(void) { 本文・・・ return(0); } って感じにエディタに記述して、拡張子を.cにして保存 その後コンパイルしようとしても出来ず・・・ もしかしてBorland C++ Compiler のコンパイラではC言語はコンパイル出来ないのでしょうか? 調べてもよくわからないので教えていただけないでしょうか? お願いします