2015年10月21日水曜日

GCCは同名ヘッダのどれをインクルードするのか?

GCCに標準のディレクトリ以外からincludeするヘッダファイルを探してもらいたい場合、-Idir オプションで指定する。-Idir1 -Idir2のように複数指定すれば、指定した順に探してもらえる。…と思っていたら、困ってしまった。

簡単な例をアップした。この中には、以下のようにfoo.hが3つある。

test_include/
  +- inc1/
  |    +- foo.h
  +- inc2/
  |    +- foo.h
  |    +- bar.h : #include "foo.h"
  +- inc3/
       +- foo.h
       +- baz.h : #include "bar.h"
この状態で-Iinc1 -Iinc2 -Iinc3と指定してコンパイルすると、どのディレクトリのfoo.hがインクルードされるのか?

まず#include "foo.h"した場合。大方の予想通り、インクルードされるのはinc1/foo.h。これはいい。

次に#include "bar.h"した場合。inc2/bar.hがインクルードされるのは分かるのだが、そこから更にinc2/foo.hがインクルードされるのだ。bar.hから間接的に#includeする際には、inc1/より先にinc2/から探されてしまうようだ。

最後に#include "baz.h"した場合。inc3/baz.hからinc2/bar.hがインクルードされるのは良いとして、そこからインクルードされるのはinc2/foo.h。

プリプロセッサは、#includeディレクティブに遭遇するたびに検索ディレクトリリストの先頭から探すのだとばかり思っていたら、#includeが入れ子になっている場合は、直前にヘッダを見つけたディレクトリから検索を始めている? どうも、+librescanを付けないVCSのライブラリ検索みたいな感じの振る舞いに見える。なお、GCCではなくClangを使ってみても結果は同じだった。このあたりの仕様は規格で定められているのだろうか?

同名のヘッダをあちこちに置くのが悪いと言われたらその通りなのだけれど、一部のヘッダだけテスト用のものに差し替えたりしたいとき、ちょっと困る。

0 件のコメント:

コメントを投稿