rootcint の error を回避する

ROOT で自作の class を作るときに、rootcint という command を使って CINT 用の dictionary の作成を行います。これをしないと、CINT からの呼び出しが出来ません (はず)。

Mac で rootcint を使った場合、解析させる header file の中身によっては、ちゃんと rootcint が解釈できないときがあります。例えば、FTDI の配布する ftd2xx.h を読み込ませると、次のような error が出てしまいます。

$ make
Generating dictionary ...
rootcint -f src/TargetUSBDict.cxx -c -p inc/TBasePacket.h inc/TCommandPacket.h inc/TPacketDataWord.h inc/TResponsePacket.h inc/TSampleData.h inc/TTargetUtil.h inc/TUSBInterface.h inc/LinkDef.h
Error: class,struct,union or type __builtin_va_list not defined  /usr/include/i386/_types.h:96:
Error: Too many '}' /usr/include/sys/_select.h:57:
Error: Symbol pthread_cond_teCondVar is not defined in current scope  inc/ftd2xx.h:68:
Error: Symbol pthread_mutex_teMutex is not defined in current scope  inc/ftd2xx.h:69:
Error: Missing closing brace for the block opened around line 200.
Error: Unexpected end of file (G__exec_statement()) /var/tmp/tmp.0.NXjaqd_cint.cxx:2:
Warning: Error occurred during reading source files
Warning: Error occurred during dictionary source generation
!!!Removing src/TargetUSBDict.cxx src/TargetUSBDict.h !!!
Error: rootcint: error loading headers...
make: *** [src/TargetUSBDict.cxx] Error 1

ROOT Talk を眺めると、rootcint に -p という引数をつければ大丈夫だという記述もあるのですが、うまくいきません。そこで、自作の class の header に、以下のように追記することで回避しました。#ifdef で囲んであるので、GCC で compile されるときは完全に無視され一切悪さをしないので、大丈夫です。

#ifdef __CINT__
#undef __GNUC__
#define _SYS__SELECT_H_
struct pthread_cond_t;
struct pthread_mutex_t;
#endif

合計で 4 つの対処をしているので、順番に説明します。まず 1 つ目は、__builtin_va_list が定義されていないというものです。

Error: class,struct,union or type __builtin_va_list not defined  /usr/include/i386/_types.h:96:

これは、/usr/include/i386/_types.h の 96 行目に次のような記述があるので、

#if (__GNUC__ > 2)
typedef __builtin_va_list       __darwin_va_list;       /* va_list */
#else
typedef void *                  __darwin_va_list;       /* va_list */
#endif

__GNUC__ を undef することで読み飛ばしてしまいます。

#undef __GNUC__

次の error は、/usr/include/sys/_select.h 内の括弧の数をちゃんと勘定できていません。

Error: Too many '}' /usr/include/sys/_select.h:57:

これはもう面倒くさいので、_SYS_SELECT_H_ を define することによって、_select.h 自体を完全無視させてしまいます。

#define _SYS__SELECT_H_

最後は、pthread_cond_t と pthread_mutex_t という 2 つの struct が宣言されていないと怒られます。

Error: Symbol pthread_cond_teCondVar is not defined in current scope  inc/ftd2xx.h:68:
Error: Symbol pthread_mutex_teMutex is not defined in current scope  inc/ftd2xx.h:69:

ちゃんと /usr/include/pthread.h で宣言されているはずで、実際の動作には問題ないのですが、 rootcint が正しく動作しないので、struct を前方宣言してしまうことで対処します。

struct pthread_cond_t;
struct pthread_mutex_t;