HN 日本語サマリー

← 一覧へ戻る
プログラミング

C++ Insights – コンパイラの目でソースコードを見る

C++ Insights – See your source code with the eyes of a Compiler (github.com)

22 pointsby rramadass1 コメント

要約

C++ Insightsは、コンパイラがソースコードに対して行う内部的な変換や、通常は隠されている処理を可視化するClangベースのソース・トゥ・ソース変換ツールです。ラムダ式、範囲ベースforループ、autoキーワード、構造化束縛などのC++の機能を、コンパイラがどのように解釈・展開するかを、コンパイラが生成するコードに近い形で理解できるようにします。これにより、C++の学習者や開発者は、コードが実際にどのように機能するかをより深く理解することができます。

全文翻訳

C++ Insights - コンパイラの目でソースコードを見る。 目次 What Why Building Usage Get Involved Support What C++ Insightsは、ソース・トゥ・ソース変換を行うClangベースのツールです。C++ Insightsの目標は、通常意図的にバックグラウンドで行われることを可視化することです。それは、コンパイラが私たちを機能させるために行う魔法についてのものです。 例えば、このコードを見てみましょう。 class Base { }; class Derived : public Base { }; int main() { Derived d; Derived d2 = d; d2 = d; Base& b = d; } 特別なことは何もありません。もちろん、コンパイルされます。これはコンパイラからの視点です。 class Base { public: // inline constexpr Base() noexcept = default; // inline constexpr Base(const Base &) noexcept = default; // inline constexpr Base & operator=(const Base &) noexcept = default; }; class Derived : public Base { public: // inline constexpr Derived() noexcept = default; // inline constexpr Derived(const Derived &) noexcept = default; // inline constexpr Derived & operator=(const Derived &) noexcept = default; }; int main() { Derived d; Derived d2 = Derived(d); d2.operator=(d); Base & b = static_cast<Base&>(d); return 0; } コンパイラ提供のすべての特殊メンバ関数と、DerivedからBaseへのアップキャストが見えます。 Why C++ Insightsは、ソース・トゥ・ソース変換を行うClangベースのツールです。C++ Insightsの目標は、通常意図的にバックグラウンドで行われることを可視化することです。それは、コンパイラが私たちを機能させるために行う魔法についてのものです。あるいは、コンパイラのクラスを通して見ることです。 2017年、私はC++11、C++14、C++17で導入された新しい機能のいくつかを調べ始めました。ラムダ式、範囲ベースforループ、構造化束縛のような素晴らしい機能です。私はそれらをまとめて講演しました。スライドとビデオはオンラインで見つけることができます。 しかし、そのすべての研究と私のトレーニングや教育の一部が、コンパイラの目で物事を見ることができたらどうなるだろうかと考え始めさせました。確かに、ASTダンプはあります。少なくともClangには。Compiler Explorerのようなツールで、コンパイラがC++ソーススニペットから生成するコードを見ることができます。しかし、私たちが目にするのはアセンブラです。ASTもCompiler Explorerの出力も、私がコードを書く言語ではありません。そのため、私はこの出力にあまり慣れていません。さらに、学生にC++を教える際に、ASTを見せて、それがすべてであると説明しても、私にとってはあまり満足のいくものではありませんでした。 私は、範囲ベースforループをコンパイラの内部バージョンに変換できるClangベースのツールを書き始めました。次に、構造化束縛とラムダ式についても同様のことを行いました。最終的には、当初計画していた以上のことを行いました。演算子がどこで呼び出されるか、コンパイラがキャスティングを行う場所を示します。C++ Insightsは、autoまたはdecltypeの背後にある型を推測できます。目標は、コンパイル可能なコードを生成することです。しかし、これはすべての場所で可能ではありません。例えば、ラムダ式、範囲ベースforループ、またはautoの変換を見ることができます。もちろん、他のC++スニペットも変換できます。自分で見てください。 C++ Insightsはオンラインで利用可能です: cppinsights.io。それでも、やるべきことはあります。私はすべてを正しく行うと主張するわけではありません。現在、C++20のような新しい標準の機能もサポートするように取り組んでいます。C++ InsightsはClangとそのASTの理解に基づいていることを覚えておいてください。 私はC++ Insightsをリリースして以来、C++ Insightsについていくつかの講演を行いました。例えば、C++ Nowでです。ここにスライドとビデオがあります。 Building C++ Insightsは、Clangソースツリーの内側または外側でビルドできます。 Windowsでのビルド Readme_Windows.mdを参照してください。 Arch Linuxでのビルド extra/clangを使用してビルドするには、次の追加フラグを使用します。 -DINSIGHTS_USE_SYSTEM_INCLUDES=off -DCLANG_LINK_CLANG_DYLIB=on -DLLVM_LINK_LLVM_DYLIB=on INSIGHTS_USE_SYSTEM_INCLUDESをオフにする必要がある理由については、#186を参照してください。extra/clangおよびextra/llvmは、/usr/lib/{libclangAST.so,libLLVM*.a,libLLVM.so}を提供します。libclangAST.soはlibLLVM.soを必要とし、libLLVM*.a(libLLVM.soではなく)がリンクされると競合が発生します。https://bugs.archlinux.org/task/60512を参照してください。 Clangの外側でのビルド Clangのインストールが検索パスにある必要があります。 ```bash git clone https://github.com/andreasfertig/cppinsights.git mkdir build && cd build cmake -G"Ninja" ../cppinsights ninja ``` 結果のバイナリ(insights)はbuildフォルダにあります。 Clangの内側でのビルド Clangソースツリーの内側でC++ Insightsをビルドする最も簡単な方法は、LLVM_EXTERNAL_PROJECTSオプションを使用することです。 ```bash git clone https://github.com/llvm/llvm-project.git git clone https://github.com/andreasfertig/cppinsights.git mkdir build cd build cmake -G Ninja -D=CMAKE_BUILD_TYPE=Release -DLLVM_EXTERNAL_PROJECTS=cppinsights -DLLVM_EXTERNAL_CPPINSIGHTS_SOURCE_DIR=<PATH/TO/cppinsights> [INSIGHTS CMAKE OPTIONS] ../llvm-project/llvm ninja ``` cmakeオプション cmakeで有効にできるオプションがいくつかあります。 Option | Description | Default INSIGHTS_STRIP | ビルド後にinsightをストリップ | ON INSIGHTS_STATIC | 静的リンクを使用 | OFF INSIGHTS_COVERAGE | コードカバレッジを有効にする | OFF INSIGHTS_USE_LIBCPP | テストにlibc++を使用 | OFF DEBUG | デバッグを有効にする | OFF ARM on macOSでのビルド 設定時にアーキテクチャを指定するのが最善のようです。 ```bash cmake -DCMAKE_OSX_ARCHITECTURES=arm64 ../cppinsights ``` Cevelopでの使用 ```bash git clone https://github.com/andreasfertig/cppinsights.git mkdir build_eclipse cd build_eclipse cmake -G"Eclipse CDT4 - Unix Makefiles" ../cppinsights/ ``` その後、CevelopでImport -> General -> Existing Project into Workspaceを選択します。build_eclipseを選択します。Cevelopでの編集をお楽しみください。 Usage C++ Insightsの使用は非常に簡単です。 ```bash insights <YOUR_CPP_FILE> -- -std=c++17 ``` システムインクルードパスに関しては、状況は複雑になります。これらのパスはバイナリにハードコードされており、C++ Insightsがビルドされたコンパイラから来ているようです。これを支援するために、scripts/getinclude.pyを確認してください。このスクリプトは、コンパイラからシステムインクルードパスを収集しようとします。オプションなしの場合、getinclude.pyはg++を使用します。別のコンパイラを最初の引数として渡すこともできます。例を挙げます。 ```bash ./scripts/getinclude.py -isystem/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1 -isystem/usr/local/include -isystem/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.3.0/include -isystem/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -isystem/usr/include ``` このスクリプトはC++ Insightsと組み合わせて使用できます。 ```bash insights <YOUR_CPP_FILE> -- -std=c++17 \ `./scripts/getinclude.py` ``` カスタムGCCインストールのための注意 カスタムビルドのGCCコンパイラ(例: gcc-11.2.0)があり、デフォルトのシステムパスにインストールされていない場合、ビルド後にClangは正しいlibstdc++パス(GCCのSTL)を見つけるのに失敗します。この状況に陥った場合は、`--gcc-toolchain=/path/GCC-1x.x.x/installed/path`を使用して、Clang/C++ InsightsにSTLの場所を伝えることができます。 ```bash ./cppinsights Insights.cpp -- --gcc-toolchain=${GCC_11_2_0_INSTALL_PATH} -std=c++20 ``` ここで`${GCC_11_2_0_INSTALL_PATH}`は、カスタマイズビルドされたGCCのインストールディレクトリです。Clangのオプションについては、こちらで説明されています。 Dockerコンテナですぐに使用可能 最新のC++ Insightsバージョンを含むDockerコンテナを設定する別のGitHubプロジェクトもあります: C++ Insights - Docker Plugins / Extensions / Packages C++ Insights @ Vim Vim用のプラグインはこちらで入手可能です。 C++ Insights @ Neovim Neovim用のプラグインはこちらで入手可能です。 C++ Insights @ VSCode VS CodeマーケットプレイスでVS Codeの拡張機能があります: C++ Insights - VSCode Extension。 C++ Insights @ brew 少なくともmacOSでは、このフォーミュラのおかげでHomebrew経由でC++ Insightsをインストールできます: brew install cppinsights Shell autocomplete bash、zsh、fish用の補完スクリプトがあります。これらは、C++ Insightsオプション(説明を含む)および--の後に続くClangオプションを補完します。ソースからビルドすると、補完スクリプトはシェルに自動的にインストールされます。