Clang工具


文档摘要

为了第一个测试项目,创建一个简单的Clang工具,该工具运行编译器,并检查提供的源文件的语法。先创建一个所谓的树外LLVM项目,即一个将使用LLVM但位于主LLVM源树外的项目。 创建项目需要执行以下几项操作: 必须构建和安装所需的LLVM库和头文件 需要为测试项目创建一个构建配置文件 使用LLVM的源代码必须创建 从第一步开始,安装Clang支持库和头文件。使用以下CMake配置命令: cmake -G Ninja -DCMAKEBUILDTYPE=Debug -DCMAKEINSTALLPREFIX=..

为了第一个测试项目,创建一个简单的Clang工具,该工具运行编译器,并检查提供的源文件的语法。先创建一个所谓的树外LLVM项目,即一个将使用LLVM但位于主LLVM源树外的项目。

创建项目需要执行以下几项操作:

  • 必须构建和安装所需的LLVM库和头文件

  • 需要为测试项目创建一个构建配置文件

  • 使用LLVM的源代码必须创建

从第一步开始,安装Clang支持库和头文件。使用以下CMake配置命令:

cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug
-DCMAKE_INSTALL_PREFIX=../install -DLLVM_TARGETS_TO_BUILD="X86"
-DLLVM_ENABLE_PROJECTS="clang" -DLLVM_USE_LINKER=gold
-DLLVM_USE_SPLIT_DWARF=ON -DBUILD_SHARED_LIBS=ON ../llvm

图 1.12: LLVM CMake配置,用于简单的语法检查Clang工具

这里只启用了一个项目:clang。所有其他选项都是我们调试构建的标准配置。该命令必须从LLVM源树中创建的构建文件夹中运行。

重要提示 图1.12中指定的配置将在整本书中作为默认构建配置使用。

使用动态库的配置,除了减少大小外,还有简化依赖项指定的优点。只需要指定项目直接依赖的动态库,动态链接器将处理其余部分。

所需的库和头文件可以通过以下命令安装:

库和头文件将安装到通过CMAKE_INSTALL_PREFIX选项指定的文件夹中。

再为项目创建两个文件:

  • CMakeLists.txt: 项目配置文件

  • TestProject.cpp: 项目源代码

项目配置文件,CMakeLists.txt,将通过LLVM_HOME环境变量接受LLVM安装文件夹的路径。该文件如下所示:

图 1.13: 用于简单语法检查Clang工具的CMake文件

  • 第2行:指定了项目名称(syntax-check)。这也是可执行文件的名称。

  • 第4-7行:测试LLVM_HOME环境变量。

  • 第10行:设置了LLVM CMake帮助器的路径。

  • 第11行:从第10行指定的路径加载LLVM CMake包。

  • 第14行:指定了编译的源文件。

  • 第16行:设置了相应的编译标志:-fno-rtti。当LLVM没有构建RTTI时,为了减少代码和可执行文件大小
    1,这个标志是必需的。

  • 第18-22行:指定要链接到我们程序的必需库

工具源码如下:

#include "clang/Frontend/FrontendActions.h" // clang::SyntaxOnlyAction
#include "clang/Tooling/CommonOptionsParser.h" #include
"clang/Tooling/Tooling.h" #include "llvm/Support/CommandLine.h" //
llvm:🆑:extrahelp

namespace llvm:🆑:OptionCategory TestCategory("Test project");
llvm:🆑:extrahelp
CommonHelp(clang::tooling::CommonOptionsParser::HelpMessage); //
namespace

int main(int argc, const char **argv)
llvm::Expected<clang::tooling::CommonOptionsParser> OptionsParser =
clang::tooling::CommonOptionsParser::create(argc, argv, TestCategory);
if (!OptionsParser) llvm::errs() << OptionsParser.takeError(); return
1; clang::tooling::ClangTool Tool(OptionsParser->getCompilations(),
                               OptionsParser->getSourcePathList());
return Tool.run(
  clang::tooling::newFrontendActionFactory<clang::SyntaxOnlyAction>()
          .get());

图 1.14: SyntaxCheck.cpp

  • 第7-9行:大多数编译器工具都有一套相同的命令行参数。LLVM命令行库 2
    提供了一些API来处理编译器命令选项。第7行设置了该库,在第8-10行设置了相应的帮助信息。

  • 第13-18行:解析命令行参数。

  • 第19-24行:创建并运行Clang工具。

  • 第22-23行:使用clang::SyntaxOnlyAction前端动作,将在输入文件上运行语法和语义检查。

必须指定LLVM安装文件夹的路径来构建工具。如之前所述,路径必须通过LLVM_HOME环境变量指定。配置命令(见图1.12)将路径指定为LLVM项目源树中的安装文件夹,所以可以按照以下方式构建工具:

export LLVM_HOME=<...>/llvm-project/install mkdir build cd build cmake
-G Ninja .. ninja

图 1.15: syntax-check构建命令

可以按照以下方式运行工具:

`cd build` ./syntax-check –help USAGE: syntax-check [options]
<source0> [... <sourceN>] ...

图 1.16: syntax-check –help 的输出

如果在一个C++源文件上运行程序,它将直接退出;但在一个有语法错误的C++文件上运行,会产生错误消息:

$`./syntax-check mainbroken.cpp -- -std=c++17
mainbroken.cpp:2:11: error: expected ';' after return statement
return 0
^
;
1 error generated.
Error while processing mainbroken.cpp.
\end{shell}

\begin{center}
图 1.17: 在语法错误文件上运行syntax-check
\end{center}

图1.17中使用'-{}-'将附加参数传递给编译器,具体指定C++17,选项'-std=c++17'。

还可以使用LLDB调试器运行工具:

\begin{shell}`$ <...>/llvm-project/install/bin/lldb  ./syntax-check  –
 main.cpp  – -std=c++17

图 1.18: 调试器下运行syntax-check

以syntax-check为主程序,将main.cpp源文件作为工具的参数(图1.18)。还可以向syntax-check可执行文件传递编译标志(-std=c++17)。

可以设置断点,并按照以下方式运行程序:

图 1.19: LLDB的交互演示,用于Clang工具测试项目

在clang::ParseAST函数中设置了一个断点(图1.19,第1行)。该函数是源代码解析的主要入口点。第3行运行程序,并在第16行继续执行断点后的程序。

本书的后续章节中,将使用相同的调试技术来研究Clang的源码。

  1. LLVM社区. LLVM编码标准. 2023. URL
    https://llvm.org/docs/CodingStandards.html

  2. LLVM社区. CommandLine 2.0库手册. 2023. URL
    https://llvm.org/docs/CommandLine.html


发布者: 作者: 转发
评论区 (0)
U