2013年7月24日水曜日

Cygwin環境でのmakeエラー

Cygwin環境でmakeを走らせると、

"複数のターゲットパターンです. 中止."

のような意味不明なエラーが出てしまいました。

以前はちゃんととmakeできていたはずですが、先日購入したVostro270sに環境を移した時に新しくインストールしたCygwinのmakeのバージョン違いが原因であろうことはだいたい推測がつきました。
単純に、makeのバージョンを下げる(今使っているのは3.82.90、以前はたしか3.79だったような)という方法もとれるのだけれど、それでは前進になっていないので、ちょっと調べることにしました。

しかし、ググってもほとんど情報がありません。あまり、この問題に遭遇する人はいないのかもしれません。見つかったのは、これとかこれくらいです。

問題は、自動生成された依存ファイル(*.d)にありました。同じCygwin環境でも、他のコンパイラを使う別プロジェクトでは、同じmakeを使ってもちゃんとビルドできます。もちろん、同じような依存ファイル自動生成makefileで動かしています。その別プロジェクトで生成される*.dと、問題の出る*.dファイルを比べると、違いはすぐに判りました。

依存ファイル(*.d)のパスに、DOS/Windows形式のパスが含まれていると、makeは上のエラーを出すことが分かりました。つまり、DOS/Windows形式のパスには、バックスラッシュが含まれているのが原因でしょう。

ということは、解決方法は2つになります。

  1. makeがDOS/Windows形式の依存ファイルを認識できるようにする。

  2. gccが-MDオプションで生成する依存ファイルのパスにDOS/Windows形式のパスを生成させないようにする。
1の方は、古いmakeに置き換えるというのも一つの手段ですが、こちらの方法はとらないことにします。
2の方はgccにパッチを当てることになりますが、残念ながらそのgccのソースが手元にないし、そういうパッチを作るにはそれなりに調査の時間がかかりそうなので、こちらも採用しないことにします。

代わりに、gccが生成した依存ファイルに含まれるDOS/Windows形式のパスを、UNIX形式のパスに変換することにしました。これなら、makefile中でsedとかを使って文字列変換するだけで対応できそうです。

というわけで、(かなり強引な)変換スクリプトをmakefileに入れました。

 cat < $(@F:.o=/d) | sed -e "s/.:[\]cygwin//g" | sed -e "s/[\]/\//g" | sed -e "s/[/]$$/\\\/" > $(@F:.o=.d)

ふう。
依存ファイル.dを読みだして、[ドライブ名:\cygwin]で始まるパスを消して、バックスラッシュを全部スラッシュに置き換えて、行末のスラッシュだけは再度バックスラッシュに戻し、最後に元の依存ファイルに書き戻す、ということをしています。
これを、makefile中の$(CC) -MD の次の行に挿入することで解決しました。

0 件のコメント:

コメントを投稿