人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

【C言語】includeしてるファイルを全て(再帰的に)表示するツールってありますか?
もしくは検索するアルゴリズムを教えて頂けると嬉しいです。

例:a.hファイルがincludeしてるファイルを調べたい

a.h は b.h と c.h を include してる。
b.h は d.h と e.h を include してる。
c.h は f.h を include してる。
d.h は ...

結果:a.h は b.h, c.h,d.h,e.h.....をincludeしてます。

という感じ。同一階層ではなく色々な階層にヘッダファイルが散らばってます。
(どの階層にあるかは不明です)(フォルダ数は数十万以上あるので個別指定は不可能です)
ちなみにgcc -M 【ファイル名】は同一階層しか検索できませんでした。

●質問者: ねぎ
●カテゴリ:コンピュータ
✍キーワード:C言語 gcc アルゴリズム ファイル フォルダ
○ 状態 :終了
└ 回答数 : 5/5件

▽最新の回答へ

1 ● t_shiono
●20ポイント

makedependで十分ではないでしょうか?

http://xjman.dsl.gr.jp/man/man1/makedepend.1x.html

何かの参考になれば。

◎質問者からの返答

ありがとうございます。m(_ _)m

おぉ。こんなツールがあるんですね。

・・・これってmakefileが無いと動作しないんですかね?

(自宅環境でmakefileが無い状態で実行したらmakedepend: error: [mM]akefile is not present

と表示されてしまいました。自分でmakefileを作ったら実行できました。)

会社の開発環境がちょっと特殊で、perlでバッチ処理を走らせてビルドを掛けてるので、

もしかしたら通常のCにあるようなmakeファイルが無いかも知れないんです。。

(ソースだけで2GBオーバー、数十万ファイルあるので全容を把握できてません)

まずは会社の開発環境にmakefileがあるか確認してみます。

ありがとうございました!


2 ● practicalscheme
●20ポイント

gcc -H はいかがですか。

こんな感じで階層表示してくれます。

(gccにはビルド時に渡すのと同じオプションを渡す必要があります。

あと、-Mでもシステムヘッダを含む全てのヘッダを出してくれるはずですが…)

$ gcc -std=gnu99 -H -DHAVE_CONFIG_H -I. -I./../gc/include -g -O2 -fPIC -fomit-frame-pointer -march=i686 -DUSE_I686_PREFETCH -c vm.c
. gauche.h
.. ./gauche/config.h
.. /usr/include/stdio.h
... /usr/include/features.h
.... /usr/include/sys/cdefs.h
..... /usr/include/bits/wordsize.h
.... /usr/include/gnu/stubs.h
..... /usr/include/bits/wordsize.h
..... /usr/include/gnu/stubs-32.h
... /usr/lib/gcc/i386-redhat-linux/4.1.2/include/stddef.h
... /usr/include/bits/types.h
.... /usr/include/bits/wordsize.h
.... /usr/include/bits/typesizes.h
... /usr/include/libio.h
 :
◎質問者からの返答

ありがとうございます。m(_ _)m

おぉ。ディレクトリ情報も表示してくれるのは有難いですね。

・・・ですが、ちょっと調べてみたのですが上記オプションは下記のような意味合いですよね?

→GNU規格とC99規格を組み合わせてコンパイルする

→ディレクトリ付きで表示する

→不明。。(?_?;

→ヘッダファイルのディレクトリを指定する

→デバッグ情報を生成する

→最適化する

→動的リンクに適する位置非依存コードを(中略)回避する

→フレーム・ポインタをレジスタ内に保持しない

→指定したCPUだけで動作するようにする。速い。

→不明。。(?_?;

→コンパイルのみを行う

いや。ディレクトリ付きで表示してくれるのは大変ありがたいので参考には

なったのですが、t_shiono様への返信に書いたように会社の開発環境が特殊で

通常のシステムファイルのようにヘッダファイルの位置を環境変数などで

持っていないため、単純にgcc -Mやgcc -Hでは表示してくれないんですよ。。

(stdio.hなどはgcc -Hで上記のように表示してくれますが、自作ヘッダ

ファイルはディレクトリを指定しないと検索してくれないみたいです。。)

環境チームという名前のチームがあるのでそこに聞けば色々分かると思うのですが、

複数の会社で開発を行っている為、コンパイル環境の詳細などを現実的に聞くことが

出来ないんです。。(環境チームは別会社が担当)

・・・まぁビルドを掛ける際に走らせてるperlを解析すれば良い話なのですが、

そこに時間を掛けるくらいだったら力技でincludeファイルをgrep掛けまくる

方が現実的かなと思いまして。

ちなみに-Iオプションでディレクトリを指定するのは現実的に不可能です。

(数十万以上あるので)(ある程度はヘッダファイルの位置が決まってますが、

自分の担当ソース以外、どこにヘッダファイルがあるのか正確な情報は

ほとんど分かりません)

もし認識違いでしたらご容赦ください&教えて頂ければうれしいです。m(_ _)m


3 ● dev_zer0
●20ポイント

http://www.linux.or.jp/JM/html/GNU_gcc/man1/gcc.1.html

やはり、gcc -Mでmakefileを作成させるのが一番手っ取り早い気がします。

ちなみに、gcc -Mだとマニュアルの抜粋を引用すると

見つからないヘッダファイルは生成されたファイルであり、

それらはソースファイルと同じディレクトリに存在するとみなします。

とあるので-Iオプションでヘッダが存在する場所を指定する必要があります

# そのヘッダが存在する箇所が散らばっているらしいですけど...


取り合えず、ヘッダが存在するディレクトリを片っ端から-Iオプションに

追加してはどうでしょうか?

# ヘッダファイル名が被っていると色々ややこしいことになりますが...

ヘッダが存在するディレクトリを取ってくる方法はbashなら

for f in $(find /usr -name '*.h'); do

dirname $f;

done | sort -u

で/usr配下のヘッダが存在するディレクトリを求めることが出来ます。

◎質問者からの返答

えーとですね。。一度全ソースディレクトリを*.hでgrep掛けたのですが

ヘッダファイルだけで数十万ファイルあったんですよ。。

正確には調べてないですが、単純に1フォルダに100個ヘッダファイル

があったとして計算しても数千フォルダ。。orz いやもっと少ないかも知れないですが。。

そんなにたくさんのディレクトリを-Iオプションで指定できるものなんですかねぇ?

もしどんなに多くても指定可能というのであれば、もうこの際ダメ元で試してみます。

#ちなみにファイル名は基本的に命名規則に則ってるハズだから被ってない。。と思います。


4 ● d金魚
●20ポイント

私はこういうのを調べる場合にはdoxygen + graphvizを使います。グラフィカルに表示してくれるのでとても見やすいです。

資料が古めですが導入方法です。

http://d.hatena.ne.jp/studiokingyo/searchdiary?word=doxygen%a4%f...

また、最近ではgoogle:doxygen frontendがあるようです。

しばらくプログラミングからはなれているので今ではもっとスマートな方法があるのかもしれません。

◎質問者からの返答

おおっ!これは素晴らしいですね。

今度試してみます。ありがとうございます。m(_ _)m


5 ● しおり
●20ポイント

includeしてるファイルを全て(再帰的に)表示するツールってありますか?

(中略)

同一階層ではなく色々な階層にヘッダファイルが散らばってます。

(どの階層にあるかは不明です)(フォルダ数は数十万以上あるので個別指定は不可能です)

そういう特殊なものは公開されていないと思います。

もしくは検索するアルゴリズムを教えて頂けると嬉しいです。

厳密なものでもないし性能も考えていませんが、こんな感じでできると思います。

(C/C++ では面倒だし、Perl はとうの昔に捨てたので、Ruby で書きました。)


find_headers:

#!/usr/local/bin/ruby

require 'find'
require 'set'

def put_usage
 $stderr.puts "Usage: #{$0} dir1 [dir2...] file"
end

def find_file(dirs, file)
 pattern = Regexp.new("/#{Regexp.escape(file)}$")
 for dir in dirs
 Find.find(dir) do |path|
 next unless FileTest.file? path
 if pattern =~ path
 return path
 end
 end
 end
 return nil
end

def find_headers(dirs, hfile)
 hpaths = Set.new
 File.foreach(hfile) do |line|
 next unless /^\s*#\s*include\s*[<"]([^>"]+)[>"]/ =~ line
 file = $1
 path = find_file(dirs, file)
 if path.nil?
 $stderr.puts "warning: #{file}: not found"
 hpaths << file
 else
 hpaths << path
 hpaths |= find_headers(dirs, path)
 end
 end
 return hpaths
end

if ARGV.size < 2
 put_usage
 exit 1
end

file = ARGV.pop
dirs = ARGV
hpaths = find_headers(dirs, file)

print(file, ': ', hpaths.to_a.join(', '), "\n")

実行例:

% find_headers /usr/include /usr/include/stdio.h
/usr/include/stdio.h: /usr/include/sys/_types.h, /usr/include/machine/_types.h, /usr/include/sys/_null.h, /usr/include/sys/cdefs.h
◎質問者からの返答

おおっ!!素晴らしい!!まさにコレ!というソースをありがとうございます!!

Rubyは触ったことないので上記の詳細は良く分かりませんが、早速インストールして試してみます。

ありがとうございました!!m(_ _)m

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ