LoginSignup
0
0

More than 5 years have passed since last update.

MacでC#(Mono)からlibclangのライブラリを読み込む方法

Last updated at Posted at 2015-03-18

背景

  • MacでCソースの構文解析を行いたくて、libclangで解析することに
  • libclang(C言語)で解析用ソースを書くのは大変そう
  • C#でlibclangを使用できるClangSharpがNuGetで公開されているのを発見
  • 公式で公開されているビルド済みのlibclang.dylibだとDllNotFoundExceptionが発生して使えない

原因と解決策

原因はlibclang.dylibx86_64(64bit)向けにビルドされているのに対して、Xamarin Studioでビルドして生成される実行ファイルがi386(32bit)向けになっているため、アーキテクチャが異なると怒られる

Xamarin Studio は現状x86_64向けの実行ファイルは生成できないようなので、clangのソースコードをビルドしてi386向けのlibclang.dylibを生成する。

またソースに標準で付いているmake環境でi386向けのバイナリをビルドしようとしたところ途中でビルドエラーが発生したため、Cmake + ninja1でビルドする。

環境

  • Mac OSX 10.10 Yosemite
  • Xamarin Studio 5.7.1
  • clang 3.6

clangビルド

  • LLVMのSVNリポジトリから最新版ソースをチェックアウト
$ svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
$ cd llvm/tools
$ svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
$ cd ../../
$ cd llvm/tools/clang/tools
$ svn co http://llvm.org/svn/llvm-project/clang-tools-extra/trunk extra
$ cd ../../../../
$ cd llvm/projects
$ svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt
$ cd ../../
  • Cmakeをインストール
$ cd llvm
$ git clone git://cmake.org/stage/cmake.git
$ cd cmake
$ git checkout next
$ ./bootstrap
$ make
$ sudo make install
  • ninjaをインストール
$ cd llvm
$ git clone https://github.com/martine/ninja.git
$ cd ninja
$ git checkout release
$ ./bootstrap.py
$ sudo cp ninja /usr/bin/
  • Cmakeninja用コンフィグファイルを生成しビルド23
$ mkdir llvm/build
$ cd llvm/build
$ cmake -G Ninja ../llvm -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-arch i386" -DCMAKE_CXX_FLAGS="-arch i386"
$ ninja
  • llvm/build/lib以下にlibclang.3.6.dylibが生成される

使い方

  1. Xamarin Studioを起動して、新規C# コンソールプロジェクトを作成
  2. メニューのプロジェクト->Add NuGet Packages...を開く
  3. clang.sharpで検索し、Add Packageでインストール
  4. 実行フォルダと同じディレクトリにlibclang.3.6.dylibをコピー
  5. libclang.dylibにリネーム
  6. 解析用のソースを記述する
main.c
#include <stdio.h>

int main(void)
{
    printf("Hello, World!");
}
Program.cs
using System;
using ClangSharp;

namespace ClangNet
{
    class MainClass
    {
        /// <summary>
        /// Main Method
        /// </summary>
        /// <param name="args">The command-line arguments.</param>
        public static void Main(string[] args)
        {
            /* Create Index */
            var index = new Index(true, true);

            /* Clang Arguments */
            var arg = new string[1]{ "" };

            /* Create Translation Units */
            var tu = index.CreateTranslationUnit("src/main.c", arg, null, TranslationUnitFlags.DetailedPreprocessingRecord);

            /* Creation Success */
            if(tu != null)
            {
                /* Get Translation Unit Cursor */
                var cursor = tu.Cursor;

                /* Visit Children */
                cursor.VisitChildren(VisitChildrenCallback);

                /* Dispose Translation Unit */
                tu.Dispose();
            }

            /* Dispose Index */
            index.Dispose();
        }

        /// <summary>
        /// Visit Children
        /// </summary>
        /// <returns>Child Visit Result</returns>
        /// <param name="cursor">Cursor</param>
        /// <param name="parent">Parent</param>
        public static Cursor.ChildVisitResult VisitChildrenCallback(Cursor cursor, Cursor parent)
        {
            /* Dump Cursor Kind & Cursor Spelling */
            Console.WriteLine("{0} : {1}", cursor.Kind, cursor.Spelling);

            /* Visit Recursively */
            return Cursor.ChildVisitResult.Recurse;
        }
    }
}

実行結果
MacroDefinition : __llvm__
MacroDefinition : __clang__
MacroDefinition : __clang_major__

~ 省略 ~

FunctionDecl : main
CompoundStmt : 
CallExpr : printf
UnexposedExpr : printf
DeclRefExpr : printf
UnexposedExpr : 
UnexposedExpr : 
StringLiteral : "Hello, World!"

  1. ninja : makeより高速なビルドシステム 

  2. -DCMAKE_BUILD_TYPE=Release : Releaseビルド 

  3. -DCMAKE_C_FLAGS="-arch i386" -DCMAKE_CXX_FLAGS="-arch i386" : i386向けのバイナリを生成 

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0