我着手编写一个基于 Clang 的工具,可以将 range-based for 循环转换为编译器内部的版本。随后,我对结构化绑定(structured bindings)和 lambda 也做了同样的处理。最终,我完成的内容远远超出了最初的计划。它可以展示运算符在何处被调用,以及编译器在哪些位置进行了类型转换。C++ Insights 能够推导出 auto 或 decltype 背后的类型。其目标是生成可编译的代码,不过并非在所有情况下都能实现。
例如,你可以查看 lambda、range-based for 循环或 auto 的转换结果。当然,你也可以转换任何其他 C++ 代码片段。
亲自试试吧。C++ Insights 可在线使用:cppinsights.io。
我并不声称所有内容都完全正确。我目前也正在致力于支持新标准的特性,例如 C++20。请记住,C++ Insights 基于 Clang 及其对 AST 的理解。
自发布 C++ Insights 以来,我做过几场关于它的演讲,例如在 C++ now 大会上。以下是幻灯片和视频。
C++ Insights 既可以在 Clang 源码树内构建,也可以在其外部构建。
使用 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。
git clone https://github.com/andreasfertig/cppinsights.git
mkdir build && cd build
cmake -G"Ninja" ../cppinsights
ninja
生成的二进制文件(insights)位于 build 文件夹中。
在 Clang 源码树内构建 C++ Insights 的最简单方法是使用 LLVM_EXTERNAL_PROJECTS 选项。
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 启用的选项:
最好在配置时指定架构:
cmake -DCMAKE_OSX_ARCHITECTURES=arm64 ../cppinsights
与 Cevelop 配合使用
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 编辑的乐趣吧。
insights <YOUR_CPP_FILE> -- -std=c++17
当涉及系统头文件包含路径(system-include paths)时,事情会变得复杂。这些路径被硬编码在二进制文件中,似乎来自于构建 C++ Insights 时所用的编译器。为解决这个问题,请查看 scripts/getinclude.py。该脚本尝试从编译器收集系统头文件包含路径。不带选项时,getinclude.py 使用 g++。你也可以将其他编译器作为第一个参数传入。
./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 一起使用:
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 的位置:
./cppinsights Insights.cpp -- --gcc-toolchain=${GCC_11_2_0_INSTALL_PATH} -std=c++20
其中 “${GCC_11_2_0_INSTALL_PATH}” 是你自行构建的 GCC 的安装目录。Clang 的该选项说明见这里。
还有一个 GitHub 项目设置了包含最新 C++ Insights 版本的 Docker 容器:C++ Insights - Docker
C++ Insights @ Vim
Vim 插件可在这里获取。
Neovim 插件可在这里获取。
Visual Studio Code 扩展可在 VS Code 插件市场获取:C++ Insights - VSCode Extension。
至少在 macOS 上,你可以通过 Homebrew 安装 C++ Insights,感谢这个 formula。