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;