Open4

C API定義を作っている本人も把握していない問題にどう立ち向かうか

okuokuokuoku

gcc -dM

gccやclangには "定義されたCマクロをダンプする" 機能があるので、これを活用するとヘッダが定義するマクロを抽出できる。

  1. git grep -h "#include <" include > dump.h のようにして、APIヘッダがincludeしているヘッダの集合をダンプする
  2. ( dump.h からシステムに存在しないヘッダを除去する )
  3. gcc -E -dM dump.h | sort > before.h のようにして、APIヘッダがincludeしているヘッダによって定義されるマクロの一覧を抽出する (これには __unix のようなシステムが事前定義しているマクロも含まれる)
  4. gcc -E -dM include/SDL.h | sort > after.h のようにして、APIヘッダが定義しているマクロを抽出する
  5. git diff --no-index before.h after.h | grep ^\\+ で追加分を求める

例えば Cygwinで実行すると

いくつかおかしい点がある。

  • SDLはCygwinを歴史的事情によりWin32プラットフォームと見做しているため、 WIN32 等がSDLによって定義されている
  • _SDL_locale_h は他のinclude guardマクロの命名規則と異なっている
  • (既にissueに上がっているように、) AUDIO_S32MSB などいくつかのAPIマクロは SDL_ のプレフィックスを持たない

cl.exe /PD

ドキュメントによると /PD オプションでVisual Studioでも相応のことができるらしい。

https://docs.microsoft.com/ja-jp/cpp/build/reference/compiler-options-listed-by-category?view=msvc-170

/PD すべてのマクロ定義を出力します。

これで行けるんだろうか。。.hは直接は処理できなさそうなので

cl : Command line warning D9024 : unrecognized source file type 'dump.h', object file assumed

includeだけするソースコードを別途与えることにした。

dump.c
#include "dump.h"

これで cl /Zc:preprocessor /PD dump.c > beforewin32.h のようにするとマクロがダンプできた。

pp-trace

Clangには pp-trace ツールがあるのでもっと賢く実施できる。

clangは大抵のプラットフォームで gcc や cl.exe のエミュレーションを提供しているので、 ↑ のような方法でマクロやプリプロセスの結果をダンプして比較しつつ、clangの pp-trace に掛けるのが確実だろう。

okuokuokuoku

ASTを使う

... Doxygen のようなドキュメントツールはヘッダをパースすることで enum やその他のAPI要素のリストを出力できる。はず。

また、clangのASTはjson形式でダンプでき、ときどき異常なjsonを出力するのも修正( https://reviews.llvm.org/D108441#change-I7KZj5Lh9yQ8 )されている。