计算机科学丛书
点击查看第二章
点击查看第三章
LLVM编译器实战教程
Getting Started with LLVM Core Libraries
[巴西] 布鲁诺·卡多索·洛佩斯(Bruno Cardoso Lopes) 著
拉斐尔·奥勒(Rafael Auler)
过敏意 冷静文 译
第1章 构建和安装LLVM
LLVM基础架构适用于多种Unix环境(GNU/Linux、FreeBSD、Mac OS X)和Windows环境。在本章中,我们将逐步介绍在所有这些系统中使用LLVM之前的必要准备步骤。在部分系统上有相应的LLVM和Clang预构建软件包,但也可以从源代码编译它们。
LLVM初学者必须考虑以下情况:基于LLVM编译器的基本设置均包括LLVM和Clang库及工具包。因此,本章中的所有操作说明均针对构建和安装两个方面。在本书中,我们将重点介绍LLVM 3.4版本。然而,需要注意的是,LLVM正在积极发展,是一个年轻的项目,因此,它很可能会有一些变更。
本章将介绍以下主题:
- 了解LLVM版本
- 使用预构建的二进制文件安装LLVM
- 使用包管理器安装LLVM
- 从源代码构建用于Linux的LLVM
- 从源代码构建用于Windows和Visual Studio的LLVM
- 从源代码构建用于Mac OS X和Xcode的LLVM
1.1 了解LLVM版本
得益于许多程序员的贡献,LLVM项目得以快速更新。从10年前的第一次发布到版本3.4,其SVN(即Subversion,这是一个用于开源代码的版本控制系统)存储库包含了超过20万次提交。仅在2013年,该项目就有近3万次新的提交。因此,新功能不断被引入,有些功能也迅速被淘汰。正如任何大型项目一样,开发人员有着较短的开发周期,需要在项目运行良好并通过各种测试时发布稳定的检查点,从而允许用户在使用经过良好测试的版本的同时,体验最新的功能。
LLVM项目在整个发展历史上采用了每年发布两个稳定版本的策略。每次更新都将次要版本号增加1。例如,从版本3.3到版本3.4的更新是次要版本更新。一旦次要号码达到9,下一个版本会将主版本号增加1,就像LLVM 2.9之后更新的LLVM 3.0。与其前任版本相比,主要修订版本的更新不一定会产生很大的变化。但与上一个主要版本相比,这个主要版本的更新一般代表近5年来编译器的发展过程。
依赖于LLVM的项目通常使用其trunk(主干)版本,即SVN存储库中最新可用的版本,然而使用这个版本的代价在于这个版本可能不稳定。最近,从版本3.4开始,LLVM社区致力于修正发布,引入新的修订版本号。这项工作的第一个产品是LLVM 3.4.1。修正发布的目的是将主干分支修复的补丁包不添加任何新特性地移植到最新版本,从而保持完整的兼容性。修正发布应该出现在上一次发布的3个月之后。由于这个新系统还处于起步阶段,本章将重点介绍LLVM 3.4的安装。LLVM 3.4的预构建软件包数量较大,但只要遵循我们的操作说明,就应该能够顺利地构建LLVM 3.4.1或任何其他版本。
1.2 获取预构建包
为了使在你的系统上安装软件的任务变得容易,LLVM贡献者为特定平台准备了预编译的二进制文件,你可以不用自己编译。在某些情况下,编译一个软件可能很棘手,它可能需要一些时间,并且只有你在使用不同的平台或积极地从事项目开发工作时才需要。因此,如果你想要快速入门LLVM,可以使用预构建软件包。但是在本书中,我们将鼓励你直接从LLVM源代码树入手,你应该准备好自己从源代码树编译LLVM。
获取LLVM的预构建包的方法有两种:可以通过官方网站获取已发布的二进制文件的软件包,也可以从第三方GNU/Linux发行版和Windows安装程序获取。
1.2.1 获取官方预构建二进制文件
对于版本3.4,可从LLVM官网下载针对以下系统的预构建软件包:
通过访问http://www.llvm.org/releases/download.html ,并查看与想要下载的版本相关的“Pre-built Binaries”部分,可以查看不同版本的所有选项。例如,要在Ubuntu 13.10上下载并执行系统范围的LLVM安装,需要获取该文件的URL,并使用以下命令:
至此,LLVM和Clang就可以使用了。请记住,你需要永久地更新系统的PATH环境变量,因为我们在最后一行所做的更新仅对当前shell会话有效。你可以使用简单的命令执行Clang来测试安装是否成功,比如打印你刚刚安装的Clang版本:
如果在运行Clang时遇到问题,请尝试直接从安装位置运行二进制代码,以确保你没有遇到PATH变量错误配置的问题。如果问题还没有解决,则你下载的预构建文件可能与你的系统环境不兼容。请记住,在编译时二进制文件需要与特定版本的动态库链接。如果运行应用程序时出现链接错误,就说明你下载的预构建二进制文件与系统不兼容。
如果要在除Windows以外的其他系统中安装预构建的软件包,可以遵循相同的步骤。针对Windows的预构建软件包提供了一个易于使用的安装程序,它可以在Program Files文件夹的子文件夹中建立LLVM树结构。安装程序还提供了自动更新PATH环境变量的选项,使你能在任何命令提示符窗口中运行Clang可执行文件。
1.2.2 使用软件包管理器
软件包管理器应用程序可用于各种系统,也是获取和安装LLVM/Clang二进制文件的简单方法。对于大多数用户来说,这通常是安装LLVM和Clang的首选方法,因为它会自动处理依赖关系的问题,并确保你的系统与所安装的二进制文件兼容。
例如,在Ubuntu(10.04及更高版本)中,应该使用以下命令:
在Fedora 18中,使用类似的命令行,但包管理器不同:
使用快照包更新
也可以从每日构建的源代码快照构建软件包,这类快照包含来自LLVM子版本控制库的最新修改(commit)。这些快照很有用,尤其是对于LLVM开发人员和希望测试早期版本的用户,以及希望以主流开发成果使本地项目保持最新的第三方用户。
Linux
通过Debian和Ubuntu Linux(i386和amd64)软件库,可以从LLVM 版本控制库中下载每日编译的快照。你可以在http://llvm.org/apt查看更多详细信息。例如,要在Ubuntu 13.10上安装LLVM和Clang的每日发行版,请使用以下命令序列:
Windows
特定LLVM/Clang快照的Windows安装程序可从 http://llvm.org/builds/的“Windows snapshot builds”部分下载。最终的LLVM/Clang工具默认安装于C:ProgramFilesLLVMbin(该位置可能会根据发行版本而有所变化)。请注意,有一个单独的Clang驱动程序可模仿Visual C++ 中的cl.exe,名为clang-cl.exe。如果你打算使用经典的GCC兼容驱动程序,请使用clang.exe。
1.3 从源代码构建
在没有预构建的二进制文件的情况下,可以先获取源代码,然后从头构建LLVM和Clang。从源代码构建能够更好地了解LLVM结构。此外,你可以微调配置参数,以获取定制的编译器。
1.3.1 系统要求
若要查看支持LLVM的平台的更新列表,可以访问http://llvm.org/docs/
GettingStarted.html#hardware 。另外,http://llvm.org/docs/GettingStarted .
html#software列出了一系列更新的编译LLVM软件的先决条件。例如,在Ubuntu系统中,可以使用以下命令解决软件依赖关系:
如果正在使用包含过时软件包的旧版Linux发行版,请尽量更新系统。LLVM源代码对用于执行构建的C++编译器非常苛刻,如果依赖旧的C++编译器,可能导致构建失败。
1.3.2 获取源代码
LLVM源代码以BSD风格的许可证进行分发,可以从官网或SVN存储库中下载。如果要下载3.4版本的源代码,可以访问网站http://llvm.org/releases/download.html#3.4 ,或按如下步骤直接下载并准备用于编译的源代码。请注意,你总是需要Clang和LLVM,但是clang-tools-extra包是可选的。不过如果你打算练习在第10章中的教程,那么你将需要使用该包。有关构建其他项目的信息,请参阅下一章。请使用以下命令下载并安装LLVM、Clang和Clang Extra Tools:
1.3.2.1 SVN
要直接从SVN存储库中获取源代码,请确保你的系统上安装了SVN软件包。下一步,你需要决定是使用存储库中的最新版本,还是稳定版本。如果想要最新版本(在trunk中),假设你已进入想要放置源代码的目标文件夹中,则可以使用以下命令序列:
如果要使用稳定版本(例如版本3.4),请在所有命令中将trunk/替换为tags/RELEASE_34/final。你可能还希望轻松地浏览LLVM SVN存储库,以查看提交历史记录、日志和源码树,要这样做,可以访问http://llvm.org/viewvc 。
1.3.2.2 Git
你还可以从与SVN同步的Git镜像存储库中获取源代码:
1.3.3 构建和安装LLVM
下面将解释构建和安装LLVM的各种方法。
1.3.3.1 使用由自动工具生成的配置脚本
构建LLVM的标准方法是使用通过GNU自动工具创建的配置脚本,来生成针对特定平台的Makefile文件。该构建系统支持不同的配置选项,被广泛采用。
请花点时间使用以下命令看一看可能的选项:
部分解释如下:
- --enable-optimized:此选项允许我们在关闭调试支持和启用优化的情况下编译LLVM/Clang。默认情况下,此选项已关闭。如果你使用LLVM库进行开发,则建议使用调试支持并禁用优化,但是,由于缺少优化会使LLVM性能明显下降,因此应该在部署时舍弃这种配置。
- --enable-assertions:此选项在代码中启用断言。在开发LLVM核心库时,此选项非常有用。默认情况下打开。
- --enable-shared:此选项允许我们将LLVM/Clang库构建为共享库,并将LLVM工具与它们进行链接。如果打算在LLVM构建系统之外开发一个工具,并希望动态链接到LLVM库,那么应该将其打开。此选项默认情况下关闭。
- --enable-jit:此选项为支持它的所有目标启用即时编译。默认情况下打开。
- --prefix:此选项指定LLVM/Clang工具和库的安装目录的路径。例如,如果设置为--prefix =/usr/local/llvm,将在/usr/local/llvm/bin中安装二进制文件,并在/usr/local/llvm/lib中安装库文件。
- --enable-targets:此选项允许我们选择编译器输出代码的目标集。值得一提的是,LLVM能够执行交叉编译,也就是可以编译在其他平台(如ARM、MIPS等)上运行的程序。此选项定义要在代码生成库中包含哪些后端。默认情况下,所有目标都会被编译,但你可以通过指定你需要的目标来节省编译时间。
在使用相应参数运行configure后,还需要使用经典的make和make install两个命令完成构建。接下来我们给你展示一个例子。
使用Unix构建和配置LLVM
在这个例子中,我们将使用一系列命令构建一个未优化(即调试模式下)的LLVM/Clang,该方法适合于任何基于Unix的系统或Cygwin。不同于之前的例子中那样安装在/usr/local/llvm目录下,我们将在主目录下构建并安装它,以解释如何在没有root权限的情况下安装LLVM。这是作为开发人员工作时的惯例。这样,你还可以维护已安装的多个版本。如果需要,可以将安装文件夹更改为/usr/local/llvm,从而进行系统范围的安装。只需记住在创建安装目录时使用sudo,并运行make install命令。要使用的命令序列如下:
在本节中,我们将创建一个单独的目录来保存对象文件(即中间构建副产品),不要将它构建在用于保存源文件的同一文件夹中。请使用以下命令及上一节中介绍过的选项:
编译和安装所有组件需要一些时间。请注意,构建脚本还将处理你下载并放入LLVM源代码树的其他存储库。没有必要单独配置Clang或Clang其他工具。
要检查构建是否成功,可以使用echo $? shell命令。$? shell变量返回在shell会话中运行的最后一个进程的退出代码,而echo命令将其打印到屏幕。因此,在make命令之后要立即运行此命令,这一点很重要。如果构建成功,则make命令将始终返回0,与成功执行完毕的任何其他程序一样:
你可以配置shell的PATH环境变量,以便轻松访问最近安装的二进制文件,并通过查询Clang版本进行首次测试:
1.3.3.2 使用CMake和Ninja
除了传统的配置脚本以外,还可以为LLVM选择另一种基于CMake的跨平台构建系统。CMake可以按与配置脚本相同的方式为你的平台生成专门的Makefile文件,而且CMake更灵活,还可以为其他系统(如Ninja、Xcode和Visual Studio)生成构建文件。
另一方面,Ninja是一个小而快速的构建系统,可以替代GNU Make及其相关的Makefile文件。如果你对Ninja背后的动机和故事感兴趣,请访问http://aosabook.org/en/posa/ninja.html 。你可以将CMake配置为生成Ninja构建文件而不是Makefile文件,即你可以选择是使用CMake和GNU Make,还是使用CMake和Ninja。
然而,如果使用后者,你可以在更改LLVM源代码并重新编译时感受到非常短的周转时间。如果你打算在LLVM源代码树中开发工具或插件,并依赖于LLVM构建系统来编译项目,则特别适合这样做。
请确保你已安装CMake和Ninja。例如,在Ubuntu系统中,可以使用以下命令检验:
带有CMake的LLVM还提供了许多可以定制构建的选项。有关这些选项的完整列表,请访问http://llvm.org/docs/CMake.html 。我们先前已经介绍过基于自动工具的系统,以下是对应于该系统配置集合的选项列表。这些标志的默认值与相应的配置脚本标志的默认值相同:
- CMAKE_BUILD_TYPE:这是一个字符串值,用于指定构建是Release还是Debug。Release构建相当于在配置脚本中使用--enable-optimized标志,而Debug构建相当于使用--disable-optimized标志。
- CMAKE_ENABLE_ASSERTIONS:这是一个布尔值,对应于--enable-assertions配置标志。
- BUILD_SHARED_LIBS:这是一个布尔值,对应于-enable-shared配置标志,用于确定库是共享还是静态。Windows平台不支持共享库。
- CMAKE_INSTALL_PREFIX:这是一个字符串值,对应于--prefix配置标志,用于提供安装路径。
- LLVM_TARGETS_TO_BUILD:这是要构建的目标的列表,以分号分隔,大致对应于--enable-targets配置标志中使用的逗号分隔的目标列表。
要设置任何这些参数值对,请将-DPARAMETER=value参数标志提供给cmake命令。
使用CMake和Ninja为Unix构建
我们将重复前面使用配置脚本时的相同示例,但这次使用CMake和Ninja来构建它:
首先,创建一个目录来包含构建及安装文件:
请记住,这个文件夹不能是存放LLVM源文件的同一个文件夹。然后,用你选择的一组选项启动CMake:
应当将/PATHTOSOURCE替换为你的LLVM源文件夹的绝对路径。如果想使用传统的GNU Make文件,可以忽略-G Ninja参数。现在,使用ninja或make(具体取决于你的选择)完成构建。对于ninja,使用以下命令:
对于make,使用以下命令:
与前面一样,可以通过简单的命令来检查构建是否成功。记住,一定要在最后一条构建命令之后立即使用它,因为它会返回在当前shell会话中运行的最后一个程序的退出值:
如果上面的命令返回零,则操作成功。最后,请配置你的PATH环境变量,并使用你的新编译器:
解决构建错误
如果构建命令返回非零值,则表示发生错误。在这种情况下,Make或Ninja会打印错误,使其对你可见。请重点关注提示的第一个错误,以找到解决方案。对于稳定的LLVM版本,常见的错误是你的系统使用了不满足版本要求的软件。最常见的问题是使用过时的编译器。例如,使用GNU g ++版本4.4.3构建LLVM 3.4时,在成功编译一半以上的LLVM源文件之后,将导致以下编译错误:
你可以更改LLVM源代码来规避这个问题(如果你在线搜索或者自己查看源码,将会发现如何执行此操作),但是,无法修补每个想要编译的LLVM版本。更新编译器要简单得多,当然也是最合适的解决方案。
一般来说,在稳定版本中遇到构建错误时,请注意你的系统与推荐设置相比有什么区别。请记住,稳定版本已经在几个平台上进行了测试。另一方面,如果你正在尝试构建一个不稳定的SVN版本,则最近的提交可能会影响针对你的系统的构建,因此恢复到之前可用的SVN版本更为简便。
1.3.3.3 使用其他Unix方法
一些Unix系统提供的软件包管理器可以从源文件自动构建和安装应用程序。它们提供了一个在你的系统上经过测试的源代码编译平台,并且还尝试解决包依赖性问题。我们现在将在构建和安装LLVM和Clang的环境中评估这些平台:
- 对于使用MacPorts的Mac OS X,可以使用以下命令:
- 对于使用Homebrew的Mac OS X,可以使用以下命令:
- 对于使用ports的FreeBSD 9.1,可以使用以下命令(请注意,从FreeBSD 10开始,Clang是默认编译器,因此它已经安装):
- 对于Gentoo Linux,可以使用以下命令:
1.3.4 Windows和Microsoft Visual Studio
要在Microsoft Windows上编译LLVM和Clang,可以使用Microsoft Visual Studio 2012和Windows 8执行以下步骤:
- 获取Microsoft Visual Studio 2012。
- 从http://www.cmake.org 下载并安装CMake工具的官方二进制发行版。在安装过程中,请确保选中“Add CMake to the system PATH for all users”选项。
- CMake将生成Visual Studio配置和构建LLVM所需的项目文件。首先运行cmake-gui图形工具。然后,单击“Browse Source…”按钮并选择LLVM源代码目录。接下来,单击“Browse Build”按钮,并选择一个目录来放置CMake生成的文件(随后Visual Studio将使用它),如图1-1所示。
- 单击“Add Entry”并定义CMAKE_INSTALL_PREFIX以包含LLVM工具的安装路径,如图1-2所示。
- 此外,可以使用LLVM_TARGETS_TO_BUILD定义支持的目标集,如图1-3所示。你可以选择添加任何其他条目,以定义我们之前讨论过的CMake参数。
- 单击“Configure”按钮。会有一个弹出窗口询问该项目要使用的生成器和编译器,请选择“Use default native compilers”,对于Visual Studio 2012,请选择“Visual Studio 11”选项。单击“Finish”,如图1-4所示。
- 配置结束后,单击“Generate”按钮。然后,Visual Studio解决方案文件LLVM.sln会被写入指定的构建目录中。请转到此目录并双击此文件,随后将在Visual Studio中打开LLVM解决方案。
- 若要自动构建和安装LLVM/Clang,请在左侧的树状视图窗口中找到“CMakePredefinedTargets”,再右键单击“INSTALL”,然后选择“Build”选项。预定义的INSTALL目标将指示系统构建和安装所有LLVM/Clang工具和库,如图1-5所示。
- 要选择性地构建和安装特定的工具或库,请在左侧的树列表视图窗口中选择相应的项目,再右键单击该项目,然后选择“Build”选项。
- 将LLVM二进制文件安装目录添加到系统的PATH环境变量中。
在我们的例子中,安装目录是C:Program Files(x86)LLVMinstallbin。要直接测试安装而不更新PATH环境变量,请在命令提示符窗口中执行以下命令:
1.3.5 Mac OS X和Xcode
尽管可以通过使用前面描述的常规Unix指令为Mac OS X编译LLVM,但也可以使用Xcode进行编译:
- 获取Xcode副本。
- 下载并安装位于http://www.cmake.org的CMake 工具的官方二进制发行版。确保选中“Add CMake to the system PATH for all users”选项。
- CMake能够生成Xcode使用的项目文件。首先运行cmake-gui图形化工具。然后,如图1-6所示,单击“Browse Source”按钮并选择LLVM源代码目录。接下来,单击“Browse Build”按钮,然后选择一个目录用于存放CMake生成的文件,这些文件将被Xcode使用。
- 单击“Add Entry”并定义CMAKE_INSTALL_PREFIX以包含LLVM工具的安装路径,如图1-7所示。
- 另外,可以使用LLVM_TARGETS_TO_BUILD来定义支持的目标集。可以选择添加任何其他条目,以定义我们之前讨论的CMake参数,如图1-8所示。
- Xcode不支持生成LLVM位置无关代码(PIC)库。单击“Add Entry”并添加LLVM_ENABLE_PIC变量,它是BOOL类型,不要选中复选框,如图1-9所示。
- 单击“Configure”按钮。将弹出窗口要求你指定该项目使用的生成器和编译器。选择“Use default native compilers”和“Xcode”。点击“Finish”按钮结束进程,如图1-10所示。
- 配置结束后,单击“Generate”按钮,然后LLVM.xcodeproj文件会被写入之前指定的构建目录中。转到此目录并双击此文件以便在Xcode中打开LLVM项目。
- 要构建和安装LLVM/Clang,请选择“install”,如图1-11所示。
- 接下来,点击“Product”菜单,然后选择“Build”选项,如图1-12所示。
- 将LLVM二进制文件安装目录添加到系统的PATH环境变量中。
在我们的示例中,安装二进制文件的文件夹是/Users/Bruno/llvm/install/bin。要测试安装,请使用安装目录中的clang工具,如下所示:
1.4 总结
本章详细介绍如何通过官方构建的软件包使用预构建的二进制文件、第三方软件包管理器和每天的快照来安装LLVM和Clang。此外,还详细介绍了如何在不同的操作系统环境中使用标准的Unix工具和IDE从源文件构建项目。
在下一章中,我们将介绍如何安装LLVM中其他可能对你非常有用的项目。这些外部项目通常用于实现在主LLVM SVN存储库之外开发并且单独发布的工具。