Build LLVM+Clang from source code with mingw

這邊不筆記一下不行,人老了沒辦法記這麼詳細了,發揮打遊戲查攻略的精神搜尋資料和嘗試錯誤!! 這也太難,光是編譯就可以讓一堆人打退堂鼓了…

我就是想在 win7 + mingw 環境下用 clang ! 官網都不提供只好自己來編譯了。

Reference

Requirement: 確定都有寫進 system path

  • mingw32 或 mingw32-w64
  • cmake
  • python 2 或 python 3 都可以
  • 我的 OS: windows 7 64-bit,有人則是在 linux 系統中編譯 cross-platform target 比較好設定,網路上的步驟也幾乎都是 linux 系統指令

Downloads: 一堆 source code 還要放在特定的結構目錄下才能正常編譯

  • LLVM source code: 重新命名資料夾 llvm
  • Clang source code: 重新命名資料夾為 clang,放在 llvm/tools/
  • clang-tools-extra source code: (optional) 重新命名資料夾為 extra,放在 llvm/tools/clang/tools/, 這樣才有些其他 clang tool. eg. AST matcher
  • compiler-rt source code: (optional) 重新命名資料夾為 compiler-rt,放在資料夾 llvm/projects/
  • 其他 source code 幾乎都是放在 llvm/projects/ 目錄下

Steps

  1. 執行 cmake-gui,設定好 source & build path
  2. 執行 configure,選 mingw build
  3. 找到 CMAKE_BUILD_TYPE,輸入值 Release 或 MinSizeRel,才可以編譯比較小的 LLVM,否則 lib大小很驚人
  4. 執行 generate,確定沒有錯誤訊息
  5. cmd 進入 build 目錄下,執行 mingw32-make 編譯
  6. 同目錄執行 mingw32-make install 完成 install目錄 (官方文件提示要先 mingw32-make check-all,但 win7 環境下都失敗不管它了)
  7. lib 目錄下要 include 的東西太多可以 archive 起來,之後要引入 linker 比較方便,這裡範例使用 thin archive,只打包檔名,並非真的打包所有 *.a。在 llvm/lib/ 目錄下輸入
    ar -rcT libclang.a *.a
  8. 以後要 link clang 只要 link libclang.a 即可。若使用官網提供 VC++ 編譯好的 binary,則是可以在 link time 時將 libclang.lib 當成 object file 來 link 。

這樣編譯好的 clang.exe 基本上還是使用 mingw 的 standard library,需要 mingw 的 runtime 才能執行,使用 clang.exe  前確保 mingw 有設定進 system path

編譯好的懶人包

Clang AST dump

設計一個 main.cpp ,嘗試用 clang 把 AST 印出來,兩種指令都可以,如果有引入其他 lib 可能會 dump 出一堆東西(如 #include<time.h>),畢竟 clang 預設指令不含 preprocessor,不會去認這是不是 standard library

#define NUM 10
int   REG_A;
float REG_B      = NUM;
int   REG_C[NUM] = {0};

extern void autog();

void autoGen(const float &in) {
	REG_A = NUM;
}
clang-check.exe -ast-dump main.cpp --

TranslationUnitDecl 0x351a40 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x351f90 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x351ca0 '__int128'
|-TypedefDecl 0x352000 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x351cc0 'unsigned __int128'
|-TypedefDecl 0x352098 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x352060 'char *'
|   `-BuiltinType 0x351ae0 'char'
|-TypedefDecl 0x352100 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'char *'
| `-PointerType 0x352060 'char *'
|   `-BuiltinType 0x351ae0 'char'
|-VarDecl 0x352170 <D:\workspace\clangparser\Release\main.cpp:2:1, col:7> col:7 used REG_A 'int'
|-VarDecl 0x352238 <line:3:1, line:1:13> line:3:7 REG_B 'float' cinit
| `-ImplicitCastExpr 0x3522c0 <line:1:13> 'float' <IntegralToFloating>
|   `-IntegerLiteral 0x3522a0 <col:13> 'int' 10
|-VarDecl 0x352360 <line:4:1, col:22> col:7 REG_C 'int [10]' cinit
| `-InitListExpr 0x352430 <col:20, col:22> 'int [10]'
|   |-array filler
|   | `-ImplicitValueInitExpr 0x352478 <<invalid sloc>> 'int'
|   `-IntegerLiteral 0x3523c8 <col:21> 'int' 0
|-FunctionDecl 0x3524e0 <line:6:1, col:19> col:13 autog 'void (void)' extern
`-FunctionDecl 0x3526a0 <line:8:1, line:10:1> line:8:6 autoGen 'void (const float &)'
  |-ParmVarDecl 0x3525d0 <col:14, col:27> col:27 in 'const float &'
  `-CompoundStmt 0x4d6e300 <col:31, line:10:1>
    `-BinaryOperator 0x4d6e2d8 <line:9:2, line:1:13> 'int' lvalue '='
      |-DeclRefExpr 0x4d6e290 <line:9:2> 'int' lvalue Var 0x352170 'REG_A' 'int'
      `-IntegerLiteral 0x4d6e2b8 <line:1:13> 'int' 10
clang -Xclang -ast-dump -fsyntax-only main.cpp

TranslationUnitDecl 0x37a6ed0 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x37a7420 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x37a7130 '__int128'
|-TypedefDecl 0x37a7490 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x37a7150 'unsigned __int128'
|-TypedefDecl 0x37a7528 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x37a74f0 'char *'
|   `-BuiltinType 0x37a6f70 'char'
|-TypedefDecl 0x37a7590 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'char *'
| `-PointerType 0x37a74f0 'char *'
|   `-BuiltinType 0x37a6f70 'char'
|-VarDecl 0x37a7600 <main.cpp:2:1, col:7> col:7 used REG_A 'int'
|-VarDecl 0x37a76c8 <line:3:1, line:1:13> line:3:7 REG_B 'float' cinit
| `-ImplicitCastExpr 0x37a7750 <line:1:13> 'float' <IntegralToFloating>
|   `-IntegerLiteral 0x37a7730 <col:13> 'int' 10
|-VarDecl 0x37a77f0 <line:4:1, col:22> col:7 REG_C 'int [10]' cinit
| `-InitListExpr 0x37a78c0 <col:20, col:22> 'int [10]'
|   |-array filler
|   | `-ImplicitValueInitExpr 0x37a7908 <<invalid sloc>> 'int'
|   `-IntegerLiteral 0x37a7858 <col:21> 'int' 0
|-FunctionDecl 0x37a7970 <line:6:1, col:19> col:13 autog 'void (void)' extern
`-FunctionDecl 0x37a7b30 <line:8:1, line:10:1> line:8:6 autoGen 'void (const float &)'
  |-ParmVarDecl 0x37a7a60 <col:14, col:27> col:27 in 'const float &'
  `-CompoundStmt 0x5362c40 <col:31, line:10:1>
    `-BinaryOperator 0x5362c18 <line:9:2, line:1:13> 'int' lvalue '='
      |-DeclRefExpr 0x5362bd0 <line:9:2> 'int' lvalue Var 0x37a7600 'REG_A' 'int'
      `-IntegerLiteral 0x5362bf8 <line:1:13> 'int' 10