Visual Studio 2015 Update 1でコンパイラが追加されました。Visual C++でコンパイルしたオブジェクトコードとリンクできるClangです。デバッグ情報なども互換で、おそらくVC++でコンパイルしたものと遜色なく扱えるものと思います。
名称はClang with Microsoft CodeGenのようです。Clang/C2という表記も見かけます。オリジナルのClangそのままではなく、後段の最適化・コード生成の部分をVisual C++のもの(c2.dll)に取り替えたものだからです。
より詳しい紹介と導入方法はClang with Microsoft CodeGenがでたので試す – Qiitaを見ると良いでしょう。
さて、このClang/C2をコマンドプロンプトで使ってみました。それについて書きます。
コマンドラインで使うための準備
VisualStudio 2015 x86 Native Tools コマンドプロンプトを起動します。そうしたら、このコマンドを実行します。途中で改行されているかもしれませんが、実際には1行です。
SET PATH=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\Clang 3.7\bin;%PATH%
これで準備完了です。
2016年8月27日追記: Visual Studio 2015 Update 2あたりからパスがC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\Clang 3.7\bin\x86
に変わっています。
Hello world
まずはHello worldを書いてみましょう。
// hello.cpp: clangでコンパイルする #include <iostream> void ShowHelloWorld() { std::cout << "Hello world" << std::endl; } |
// main.cpp: clでコンパイルする void ShowHelloWorld(); int main() { ShowHelloWorld(); } |
これを以下のコマンドラインでコンパイル・実行します。
T:\>clang -c -o hello.obj hello.cpp T:\>cl /Fe hello.exe main.cpp hello.obj T:\>hello.exe Hello world
見てのとおり、hello.cppはclang、main.cppはcl (Visual C++)でコンパイルし、リンクしています。extern "C"
は使っていませんが、ちゃんとリンクできて動いています。
これでもいけます。
T:\>cl /c main.cpp T:\>clang -o hello.exe hello.cpp main.cpp T:\>hello.exe Hello world
例外処理
次は例外処理を使ってみます。
// throw.cpp: clangでコンパイルする #include <stdexcept> #include <string> [[noreturn]] void throw_with_msg(const std::string& msg) { throw std::runtime_error(msg); } |
// main.cpp: clでコンパイルする #include <iostream> #include <stdexcept> #include <typeinfo> [[noreturn]] void throw_with_msg(const std::string& msg); int main() { try { throw_with_msg("my error"); } catch (const std::exception& e) { std::cout << "type: " << typeid(e).name() << std::endl; std::cout << "what: " << e.what() << std::endl; } } |
T:\>clang -fexceptions -o throw.obj -c throw.cpp T:\>cl /EHsc /Fe throw.exe main.cpp throw.obj T:\>throw.exe type: class std::runtime_error what: my error
例外処理も動きます。例外処理を通じてC++オブジェクトも受け渡せていますし、typeidも使えます。
ランタイムライブラリを選ぶ
このclangでコンパイルする際には、clと同じVisual C++のランタイムライブラリが使用されます。上記コードでstd::coutオブジェクトやstd::string型を使っていてうまくいったのは、そういうわけです。
ランタイムの種類はプリプロセッサ定義で選べます。違う種類を混在させると、リンクで失敗したり警告が出たりします。そこはcl.exeだけでコンパイルするときと同じです。
- DLL版ランタイム (/MD)
clang -D_DLL -c -o hello.obj hello.cpp cl /MD /Fe hello.exe main.cpp hello.obj
- DLL版デバッグ用ランタイム (/MDd)
clang -D_DLL -D_DEBUG -c -o hello.obj hello.cpp cl /MDd /Fe hello.exe main.cpp hello.obj
- 静的リンク版ランタイム (/MT)
clang -c -o hello.obj hello.cpp cl /MT /Fe hello.exe main.cpp hello.obj
- 静的リンク版デバッグ用ランタイム (/MTd)
clang -D_DEBUG -c -o hello.obj hello.cpp cl /MTd /Fe hello.exe main.cpp hello.obj
感想
前々から作っていると公表されていたのですが、やはり実際触ってみると驚きです。別世界だと思っていた2つのコンパイラが協同するのですから。
従来からのVisual C++コンパイラ(cl.exe)との使い分けをどうしたら良いのか、これから考えないといけないですね。
スポンサード リンク |