2014/05/27

clangのPythonバインディングでObjective-Cのソースコードをパースしてみる

clangPythonバインディング でObjective-Cも読み込めるはずなので、試してみました。

設置

Apple LLVMではPythonバインディングを利用できないっぽいので、次の2つのURLから、LLVMとPythonバインディングを落としてきます。

そして、$HOME/dev以下に次のように展開しておきます。

$ cd ~/dev
$ tar zxvf clang+llvm-3.4-x86_64-apple-darwin10.9.tar.gz clang+llvm-3.4-x86_64-apple-darwin10.9
$ ln -s clang+llvm-3.4-x86_64-apple-darwin10.9 clang
$ tar zxvf clang-3.4.src.tar.gz clang-3.4/bindings/python 

実行

先ほどダウンロードしてきたPythonバインディングの中に、ソースコードをパースして結果をダンプするサンプルスクリプトがあるのでそれを実行してみます。

次のように環境変数を設定して、ファイルを実行するだけです。

$ export PYTHONPATH=$HOME/dev/clang-3.4/bindings/python/
$ export LD_LIBRARY_PATH=$(~/dev/clang/bin/llvm-config --libdir)

$ python $HOME/dev/clang-3.4/bindings/python/examples/cindex/cindex-dump.py MySample.h -ObjC -c -m64 

なお、-ObjC -c -m64はlibclangに渡されるオプションです。

  • -cでパースだけさせるようにしたほうがよい
  • -ObjCを指定してObjective-Cとしてコンパイルさせる (-x objective-cだとうまくいかなかった)
  • モダンランタイムなソースとしてコンパイルするには-m64を付ける
  • -fobjc-arcを付けると結果が変わる (メソッドcopyとかにCursorKind.UNEXPOSED_ATTRなノードが追加される)

実行例

試しに適当なObjective-Cのヘッダファイルを作って、それをcindex-dump.pyでダンプした結果は次のようになります。

CursorKind.OBJC_INTERFACE_DECLなどと出力されていることがわかります。

$ cat MySample.h
#import <Foundation/NSObject.h>
@class NSURL;
@class NSString;

@interface MySample : NSObject
@property (retain) NSURL* url;
- (NSString*)path;
@end

$ python $HOME/dev/clang-3.4/bindings/python/examples/cindex/cindex-dump.py MySample.h -ObjC -c -m64 

                       :
           {'children': [{'children': [],
                          'definition id': None,
                          'extent.end': <SourceLocation file 'MySample.h', line 5, column 31>,
                          'extent.start': <SourceLocation file 'MySample.h', line 5, column 23>,
                          'id': None,
                          'is_definition': False,
                          'kind': CursorKind.OBJC_SUPER_CLASS_REF,
                          'location': <SourceLocation file 'MySample.h', line 5, column 23>,
                          'spelling': None,
                          'usr': ''},
                         {'children': [{'children': [],
                                        'definition id': None,
                                        'extent.end': <SourceLocation file 'MySample.h', line 6, column 25>,
                                        'extent.start': <SourceLocation file 'MySample.h', line 6, column 20>,
                                        'id': None,
                                        'is_definition': False,
                                        'kind': CursorKind.OBJC_CLASS_REF,
                                        'location': <SourceLocation file 'MySample.h', line 6, column 20>,
                                        'spelling': None,
                                        'usr': ''}],
                          'definition id': None,
                          'extent.end': <SourceLocation file 'MySample.h', line 6, column 30>,
                          'extent.start': <SourceLocation file 'MySample.h', line 6, column 1>,
                          'id': None,
                          'is_definition': False,
                          'kind': CursorKind.OBJC_PROPERTY_DECL,
                          'location': <SourceLocation file 'MySample.h', line 6, column 27>,
                          'spelling': 'url',
                          'usr': 'c:objc(cs)MySample(py)url'},
                         {'children': [{'children': [],
                                        'definition id': None,
                                        'extent.end': <SourceLocation file 'MySample.h', line 7, column 12>,
                                        'extent.start': <SourceLocation file 'MySample.h', line 7, column 4>,
                                        'id': None,
                                        'is_definition': False,
                                        'kind': CursorKind.OBJC_CLASS_REF,
                                        'location': <SourceLocation file 'MySample.h', line 7, column 4>,
                                        'spelling': None,
                                        'usr': ''}],
                          'definition id': None,
                          'extent.end': <SourceLocation file 'MySample.h', line 7, column 19>,
                          'extent.start': <SourceLocation file 'MySample.h', line 7, column 1>,
                          'id': None,
                          'is_definition': False,
                          'kind': CursorKind.OBJC_INSTANCE_METHOD_DECL,
                          'location': <SourceLocation file 'MySample.h', line 7, column 14>,
                          'spelling': 'path',
                          'usr': 'c:objc(cs)MySample(im)path'},
                         {'children': [],
                          'definition id': None,
                          'extent.end': <SourceLocation file 'MySample.h', line 6, column 30>,
                          'extent.start': <SourceLocation file 'MySample.h', line 6, column 27>,
                          'id': None,
                          'is_definition': False,
                          'kind': CursorKind.OBJC_INSTANCE_METHOD_DECL,
                          'location': <SourceLocation file 'MySample.h', line 6, column 27>,
                          'spelling': 'url',
                          'usr': 'c:objc(cs)MySample(im)url'},
                         {'children': [{'children': [],
                                        'definition id': None,
                                        'extent.end': <SourceLocation file 'MySample.h', line 6, column 30>,
                                        'extent.start': <SourceLocation file 'MySample.h', line 6, column 27>,
                                        'id': None,
                                        'is_definition': True,
                                        'kind': CursorKind.PARM_DECL,
                                        'location': <SourceLocation file 'MySample.h', line 6, column 27>,
                                        'spelling': 'url',
                                        'usr': 'c:MySample.h@121objc(cs)MySample(im)setUrl:@url'}],
                          'definition id': None,
                          'extent.end': <SourceLocation file 'MySample.h', line 6, column 30>,
                          'extent.start': <SourceLocation file 'MySample.h', line 6, column 27>,
                          'id': None,
                          'is_definition': False,
                          'kind': CursorKind.OBJC_INSTANCE_METHOD_DECL,
                          'location': <SourceLocation file 'MySample.h', line 6, column 27>,
                          'spelling': 'setUrl:',
                          'usr': 'c:objc(cs)MySample(im)setUrl:'}],
            'definition id': None,
            'extent.end': <SourceLocation file 'MySample.h', line 8, column 5>,
            'extent.start': <SourceLocation file 'MySample.h', line 5, column 1>,
            'id': None,
            'is_definition': False,
            'kind': CursorKind.OBJC_INTERFACE_DECL,
            'location': <SourceLocation file 'MySample.h', line 5, column 12>,
            'spelling': 'MySample',
            'usr': 'c:objc(cs)MySample'}
                       :

関連リンク

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。