Getting Started with the LLVM System(Part 1)
概述
欢迎来到LLVM项目!
LLVM项目有多个组件。该项目的核心本身被称为“LLVM”。它包含处理中间表示(Intermediate Representations,IR)并将其转换为对象文件所需的所有工具、库和头文件。工具包括汇编程序、反汇编程序、位代码分析器和位代码优化器。它还包含基本的回归测试。
还有一个重要的组件是Clang前端。这个组件将C、C++、Objective C和Objective C++代码编译成LLVM bitcode,并使用LLVM将其转换成目标文件。
LLVM中还有其他组件,包括libc ++ C ++标准库,LLD链接器等。
LLVM源码下载及构建
LLVM入门文档可能已过期。 因此,我们可以通过Clang入门文档来学习LLVM。
我们可以通过以下步骤获取和配置LLVM:
- 获取LLVM源码(包换相关子程序,如Clang)
$ git clone https://github.com/llvm/llvm-project.git
windows平台的源码获取方式为:
$ git clone --config core.autocrlf=false https://github.com/llvm/llvm-project.git
为了节省存储空间和加快代码获取时间,您可能需要进行浅层克隆。例如,如果想到获取最近版本的LLVM,可以使用以下命令:
$ git clone --depth 1 https://github.com/llvm/llvm-project.git
- 配置及构建LLVM和Clang
$ cd llvm-project
$ mkdir build
$ cd build
$ cmake -G <generator> [options] ../llvm
一些常用的生成器(generator):
- Ninja - 用于生成Ninja构建文件。大多数llvm开发人员使用Ninja。
- Unix Makefiles - 用于生成与make兼容的并行makefiles。
- Visual Studio - 用于生成Visual Studio项目和解决方案。
- Xcode - 用于生成Xcode项目。
一些常用的选项(options):
- -DLLVM_ENABLE_PROJECTS=’…’ - 子项目列表,当构建子项目时,子项目之间用分号来分隔。可以包括以下任何一个:clang,clang-tools-extra,libcxx,libcxxabi,libunwind,lldb,compiler-rt,lld,polly或debuginfo-tests。例如,要构建LLVM,Clang,libcxx和libcxxabi,请使用-DLLVM_ENABLE_PROJECTS =“clang; libcxx; libcxxabi”。
- -DCMAKE_INSTALL_PREFIX=directory - 指定要安装LLVM工具和库的完整路径名(默认为 /usr/local)
- -DCMAKE_BUILD_TYPE=type - type的有效选项是Debug,Release,RelWithDebInfo和MinSizeRel。默认为Debug。
- -DLLVM_ENABLE_ASSERTIONS=On - 编译时启用断言(对于Debug构建,默认为Yes,对于所有其他构建类型,默认为No)。
用cmake --build . [–target ]命令或上述指定的构建系统编译。
- 当target为默认值(即 cmake --build . 或 make)将构建所有LLVM。
- 当target为check-all(即ninja check-all)将运行回归测试以确保一切正常。
- CMake将为每个工具和库生成构建target,大多数LLVM子项目都会生成自己的check- target。
- 用串行构建会很慢。要提高速度,请尝试运行并行构建。Ninja是默认并行,对于make,使用选项-j NN,其中NN是并行作业的数量,例如可用CPU的数量。
更多信息,请参阅CMake。
如果出现“内部编译器错误(ICE)”或测试失败,请参阅下文。
环境要求
在开始使用LLVM之前,请查看下面列出的环境要求。提前知道你需要什么硬件和软件,这可能会帮你省去一些麻烦。
硬件
LLVM可在以下主机平台上工作:
注意:
- 仅奔腾处理器及更高版本支持代码生成
- 仅32位ABI支持代码生成
- 要在基于Win32的系统上使用LLVM模块,可以使用-DBUILD_SHARED_LIBS=on配置LLVM。
调试构建需要大量时间和磁盘空间。仅限LLVM的构建将需要大约1-3 GB的空间。LLVM和Clang的完整构建将需要大约15-20GB的磁盘空间。具体的空间要求将因系统而异。(由于所有调试信息以及库静态链接到多个工具中,所以需要很多空间)。
如果空间受限,则只能选构建一部分工具和目标。Release版本需要的空间要少得多。
理论上LLVM大件可以在其他平台上编译,但是不能保证能编译成功。如果编译成功,LLVM实用程序应该能够汇编、反汇编、分析和优化LLVM bitcode。代码生成也应该是有效的,尽管生成的本机代码可能无法在你的平台工作。
软件
编译LLVM需要安装多个软件包。下表列出了所需的软件包。Package列是LLVM所依赖的软件包的常用名称。“Version”列提供包的“已知可用”版本。Notes列描述了LLVM如何使用该包,并提供了其他详细信息。
注意:
- 只需要C和C++,所以不需要为LLVM构建其他语言。具体版本信息见下文。
- 仅当您希望在llvm/test目录中运行自动测试套件时才需要。
- 可选,向选定的LLVM工具添加压缩/解压缩功能。
- 可选,您可以使用CMake支持的任何其他构建工具。
另外,编译主机通常会有大量的Unix实用程序。如下:
- ar — 归档库构建器
- bzip2 — bzip2文件压缩命令
- bunzip2 — bzip2文件解压缩命令
- chmod — 修改文件权限
- cat — 连接文件并打印到标准输出设备上
- cp — 拷贝文件
- date — 打印当前日期/时间
- echo — 打印到标准输出
- egrep — 扩展正则表达式搜索实用程序
- find — 查找文件/目录
- grep — 正则表达式搜索实用程序
- gzip — gzip文件压缩命令
- gunzip — gzip文件解压缩命令
- install — 安装目录/文件
- mkdir — 创建目录
- mv — 移动(重命名)文件
- ranlib — 归档符号表构建器
- rm — 删除文件和目录
- sed — 用于转换输出的SED流编辑器
- sh — 用于生成构建脚本的bourne shell
- tar — 打包命令
- test — 在文件系统中测试东西
- unzip — zip文件解压命令
- zip — zip文件压缩命令
C++主机工具链,编译器和标准库
LLVM对主机C++编译器非常苛刻,因此会暴露编译器中的错误。我们还试图紧跟C++的改进和发展。因此,我们需要一个C++现代主机工具链,编译器和标准库,以便建立LLVM。
LLVM是使用编码标准中的C++子集编写的。为了实施这种语言版本,我们检查最流行的主机工具链,以了解构建系统中的特定最低版本:
- Clang 3.5
- Apple Clang 6.0
- GCC 5.1
- Visual Studio 2019
这些工具链路的旧版本也可以工作,但需要使用一个特殊选项强制构建系统,而不是一个真正受支持的主机平台。还要注意的是,这些编译器的旧版本经常会崩溃或导致LLVM编译错误。
对于非主流的主机工具链,如ICC或XLC,请注意,需要使用最新的版本来支持LLVM中使用的所有C++特性。
我们已知一部分作为主机工具链路使用会失败的软件版本。包括一些链接器。
gnu ld 2.16.x. 当“.gnu.linkonce.t.*”在废弃部分定义时,一些2.16.x版本的ld链接器将产生非常长的警告消息。这些告警消息是可以忽略的,并且链接是正确的。这些信息可以使用LD 2.17屏蔽。
gnu-binutils 2.17:binutils 2.17包含一个bug,它在构建llvm时会耗费很多时间来链接(分钟而不是秒)。我们建议升级到较新版本(2.17.50.0.4或更高版本)。
gnu-binutils 2.19.1gold:这个版本的gold包含一个bug,它在使用位置无关代码构建LLVM时会导致间歇性故障。我们建议升级到较新版本的gold。
获取现代主机C++工具链
本节主要适用于Linux和较旧的BSD。在macOS上使用的Xcode已经能满足要求,最多可能需要升级。Windows没有“系统编译器”,因此必须安装Visual Studio 2019(或更高版本)或最新版本的mingw64。FreeBSD 10.0及更新版本的系统编译器采用了现代的Clang。
然而,一些版本的Linux和一些其他或更老的BSD有时使用的是非常老的GCC版本。这些步骤试图帮助您在这样的系统上升级编译器。但是,最好还是用最新版并符合这些要求的编译器。请注意,安装Clang和libc++的早期版本作为主机编译器是很有诱惑力的,但是直到最近,libc++还没有经过良好的测试或设置,无法在Linux上构建。因此,本指南建议只使用libstdc++和现代GCC作为初始主机,然后使用Clang(可能还有libc++)。
第一步是安装最新的GCC工具链。用户最常见的版本要求是UbuntuPrecise,12.04LTS。对于这个版本,最简单的方法是安装工具链测试PPA,并使用它安装现代GCC。在ask ubuntu stack exchange和github gist上有一个非常好的讨论,其中包含更新的命令。然而,并非所有用户都可以使用PPA,而且还有许多其版本,所以从源代码构建和安装GCC可能是必要的(或者只是有用的,如果您在这里进行编译器开发的话)。现在也很容易做到。
安装GCC 5.1.0的简单步骤:
% gcc_version=5.1.0
% wget https://ftp.gnu.org/gnu/gcc/gcc-${gcc_version}/gcc-${gcc_version}.tar.bz2
% wget https://ftp.gnu.org/gnu/gcc/gcc-${gcc_version}/gcc-${gcc_version}.tar.bz2.sig
% wget https://ftp.gnu.org/gnu/gnu-keyring.gpg
% signature_invalid=`gpg --verify --no-default-keyring --keyring ./gnu-keyring.gpg gcc-${gcc_version}.tar.bz2.sig`
% if [ $signature_invalid ]; then echo "Invalid signature" ; exit 1 ; fi
% tar -xvjf gcc-${gcc_version}.tar.bz2
% cd gcc-${gcc_version}
% ./contrib/download_prerequisites
% cd ..
% mkdir gcc-${gcc_version}-build
% cd gcc-${gcc_version}-build
% $PWD/../gcc-${gcc_version}/configure --prefix=$HOME/toolchains --enable-languages=c,c++
% make -j$(nproc)
% make install
有关更多详细信息,请查看GCC wiki,我从中获得了大部分信息。
一旦拥有了GCC工具链,就可以配置LLVM的构建,以便主机编译器和C++标准库使用新的工具链。因为libstdc++的新版本不在系统库搜索路径上,所以需要传递额外的链接器标志,以便在链接时(-l)和运行时(-rpath)找到它。如果您正在使用cmake,则此调用将生成工作的二进制文件:
% mkdir build
% cd build
% CC=$HOME/toolchains/bin/gcc CXX=$HOME/toolchains/bin/g++ \
cmake .. -DCMAKE_CXX_LINK_FLAGS="-Wl,-rpath,$HOME/toolchains/lib64 -L$HOME/toolchains/lib64"
如果设置rpath失败,大多数llvm二进制文件在启动时都会失败,在加载类似libstdc++.so.6程序会报错:version `GLIBCXX_3.4.20’ not found。这意味着您需要调整-rpath链接器标志。
当您构建Clang时,您需要让它访问现代C++标准库,以便在引导程序中使用它作为您的新主机。有两种简单的方法可以做到这一点,要么构建(安装)libc++和clang,然后将其与-stdlib=libc++编译和链接标志一起使用,要么将clang安装到与gcc相同的前缀($home/toolchains)。clang将在自己的前缀中查找libstdc++并在使用它。您还可以为clang添加一个显式前缀,以便使用–gcc toolchain=/opt/my/gcc/prefix标志查找gcc工具链,在使用刚刚构建的clang引导时将其传递给编译和链接命令。