2010年03月09日
Clang を VisualStudio 2008 でビルドしてみる
Clang (クラン(グ)) は、C/C++/Objective-C のコンパイラフロントエンドです。バックエンドに LLVM (Low-Level Virtual machine) を使います。(GCC をバックエンド(アセンブラ & リンカ代わり) として使い、通常の実行形式を生成することもできます。逆に、GCC のミドルエンド以降を LLVM 向けに改造した llvm-gcc というフロントエンドも存在します。)
ライセンスが BSD ライク なので、FreeBSD が Clgan で GCC を置き換えようとする動きがあったりと、徐々に注目を集めています。
Getting Started: Building and Running Clang を見る限り、Windows 上では VisualStudio 2005/2008 でビルドできるそうなので、さっそく試してみました。
ライセンスが BSD ライク なので、FreeBSD が Clgan で GCC を置き換えようとする動きがあったりと、徐々に注目を集めています。
Getting Started: Building and Running Clang を見る限り、Windows 上では VisualStudio 2005/2008 でビルドできるそうなので、さっそく試してみました。
ソース取得のために Subversion、VS solution/project ファイルの生成のために cmake が必要です。
(テストを走らせるためには、Python と GnuWin32 tools も必要です。MinGW や cygwin の grep では上手く動かないそうです。)
LLVM と Clang をチェックアウトします。レポジトリが 2 つに分かれています。svn update などの際も両方で update する必要があります。
LLVM のディレクトリトップで LLVM.sln を作ります。
今回は clang プロジェクト(フロントエンドとコンパイラドライバ)のみを右クリックでビルドしました。
特に問題なくビルドできました。(MinGW や cygwin でビルドする際には、注意深く関連するパッケージ群のバージョンを揃える必要があるようで、なかなか大変そうです。)
今回はバックエンドの LLVM をビルドしていないので、アセンブリプログラムの生成までですが、ちゃんと LLVM のアセンブリプログラムが生成されていることが確認できます。
(テストを走らせるためには、Python と GnuWin32 tools も必要です。MinGW や cygwin の grep では上手く動かないそうです。)
LLVM と Clang をチェックアウトします。レポジトリが 2 つに分かれています。svn update などの際も両方で update する必要があります。
C:\>svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm C:\>cd llvm\tools C:\llvm\tools>svn co http://llvm.org/svn/llvm-project/cfe/trunk clangLLVM リビジョン 97702、Clang リビジョン 97700 でチャレンジ。
LLVM のディレクトリトップで LLVM.sln を作ります。
C:\llvm\tools>cd .. C:\llvm>cmake -G "Visual Studio 9 2008"LLVM.sln を普通に VS 2008 で開いてビルドします。
今回は clang プロジェクト(フロントエンドとコンパイラドライバ)のみを右クリックでビルドしました。
特に問題なくビルドできました。(MinGW や cygwin でビルドする際には、注意深く関連するパッケージ群のバージョンを揃える必要があるようで、なかなか大変そうです。)
今回はバックエンドの LLVM をビルドしていないので、アセンブリプログラムの生成までですが、ちゃんと LLVM のアセンブリプログラムが生成されていることが確認できます。
C:\llvm>cd bin\Debug\ C:\llvm\bin\Debug>cat t.c #include <stdio.h> int main(int argc, char *argv[]) { printf("hello, world\n"); return 0; } C:\llvm\bin\Debug>clang -S -emit-llvm -o - t.c ; ModuleID = 't.c' target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 2:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" target triple = "i686-pc-win32" @.str = private constant [14 x i8] c"hello, world\0A\00" ; <[14 x i8]*> [#uses=1 ] define i32 @main(i32 %argc, i8** %argv) nounwind { entry: %retval = alloca i32, align 4 ; <i32*> [#uses=3] %argc.addr = alloca i32, align 4 ; <i32*> [#uses=1] %argv.addr = alloca i8**, align 4 ; <i8***> [#uses=1] store i32 0, i32* %retval store i32 %argc, i32* %argc.addr store i8** %argv, i8*** %argv.addr %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([14 x i8]* @. str, i32 0, i32 0)) ; <i32> [#uses=0] store i32 0, i32* %retval %0 = load i32* %retval ; <i32> [#uses=1] ret i32 %0 } declare i32 @printf(i8*, ...)