创建 LLVM 项目¶
概述¶
LLVM 构建系统旨在方便构建使用 LLVM 头文件、库和工具的第三方项目。为了使用这些功能,项目的 Makefile
必须执行以下操作
设置
make
变量。Makefile
需要设置几个变量才能使用 LLVM 构建系统PROJECT_NAME
- 项目的名称。LLVM_SRC_ROOT
- LLVM 源代码树的根目录。LLVM_OBJ_ROOT
- LLVM 对象树的根目录。PROJ_SRC_ROOT
- 项目源代码树的根目录。PROJ_OBJ_ROOT
- 项目对象树的根目录。PROJ_INSTALL_ROOT
- 根安装目录。LEVEL
- 从当前目录到项目根目录($PROJ_OBJ_ROOT)
的相对路径。
包含来自
$(LLVM_OBJ_ROOT)
的Makefile.config
。包含来自
$(LLVM_SRC_ROOT)
的Makefile.rules
。
您可以通过两种方式设置所有这些变量
您可以编写自己的
Makefile
,并在其中硬编码这些值。您可以使用预制的 LLVM 示例项目。此示例项目包含
Makefile
、一个可用于配置 LLVM 位置的配置脚本,以及支持从单个源目录生成多个对象目录的功能。
如果您想设计自己的构建系统,研究其他项目和 LLVM Makefile
可能会提供足够的信息来编写您自己的 Makefile
。
源代码树布局¶
为了使用 LLVM 构建系统,您需要组织您的源代码,以便它能够从构建系统的功能中受益。主要的是,您希望您的源代码树布局看起来类似于 LLVM 源代码树布局。
在您的顶级目录下,您应该有以下目录
lib
此子目录应包含所有库源代码。对于您构建的每个库,您将在 **lib** 中有一个目录,其中包含该库的源代码。
库可以是目标文件、归档文件或动态库。 **lib** 目录只是一个方便的库放置位置,因为它将所有库都放在一个以后可以从中链接的目录中。
include
此子目录应包含项目中任何全局的头文件。全局是指这些头文件被项目中的多个库或可执行文件使用。
通过将您的头文件放在 **include** 中,LLVM 构建系统将自动找到它们。例如,如果您有一个名为 **include/jazz/note.h** 的文件,那么您的源文件只需使用 **#include “jazz/note.h”** 即可包含它。
tools
此子目录应包含所有可执行文件的源代码。对于您构建的每个程序,您将在 **tools** 中有一个目录,其中包含该程序的源代码。
test
此子目录应包含验证代码是否正常工作的测试。自动化测试尤其有用。
目前,LLVM 构建系统提供了对测试的基本支持。LLVM 系统提供了以下内容
LLVM 在
llvm/test
中包含回归测试。这些测试由 Lit 测试工具运行。此测试过程使用实际测试用例中的RUN
行来确定如何运行测试。有关更多详细信息,请参阅 LLVM 测试基础设施指南。LLVM 包含一个名为
llvm-test
的可选软件包,该软件包提供已知可以使用 Clang 前端编译的基准测试和程序。您可以使用这些程序来测试您的代码,收集统计信息,并将其与当前的 LLVM 性能统计信息进行比较。目前,无法将您的测试直接挂接到
llvm/test
测试工具中。您只需要找到一种方法来自己使用该目录中提供的源代码。
通常,您需要先构建 **lib** 目录,然后构建 **tools** 目录。
编写 LLVM 风格的 Makefile¶
LLVM 构建系统提供了一种方便的方式来构建库和可执行文件。大多数项目的 Makefile 只需要定义几个变量。下面列出了可以设置的变量及其功能
必需变量¶
LEVEL
此变量是从此
Makefile
到项目源代码顶级目录的相对路径。例如,如果您的源代码位于/tmp/src
中,那么/tmp/src/jump/high
中的Makefile
将LEVEL
设置为"../.."
。
构建子目录的变量¶
DIRS
这是一个空格分隔的子目录列表,这些子目录应该被构建。它们将按照指定的顺序依次构建。
PARALLEL_DIRS
这是一个可以并行构建的目录列表。在构建 DIRS 中的目录之后,将构建这些目录。
OPTIONAL_DIRS
这是一个目录列表,如果它们存在,则可以构建,但如果它们不存在,则不会导致错误。它们按照列出的顺序依次构建。
构建库的变量¶
LIBRARYNAME
此变量包含将要构建的库的基本名称。例如,要构建名为
libsample.a
的库,则应将LIBRARYNAME
设置为sample
。
BUILD_ARCHIVE
默认情况下,库是一个
.o
文件,该文件直接链接到程序中。要构建归档文件(也称为静态库),请设置BUILD_ARCHIVE
变量。
SHARED_LIBRARY
如果在您的 Makefile 中定义了
SHARED_LIBRARY
,则将构建共享(或动态)库。
构建程序的变量¶
TOOLNAME
此变量包含将要构建的程序的名称。例如,要构建名为
sample
的可执行文件,则应将TOOLNAME
设置为sample
。
USEDLIBS
此变量包含一个空格分隔的库列表,这些库应链接到程序中。这些库必须是来自您的 **lib** 目录的库。库必须在没有其
lib
前缀的情况下指定。例如,要链接libsample.a
,您将USEDLIBS
设置为sample.a
。请注意,这仅适用于静态链接库。
LLVMLIBS
此变量包含一个空格分隔的库列表,这些库应链接到程序中。这些库必须是 LLVM 库。库必须在没有其
lib
前缀的情况下指定。例如,要链接执行 IR 变换的驱动程序,您可以将LLVMLIBS
设置为以下最小的库集:LLVMSupport.a LLVMCore.a LLVMBitReader.a LLVMAsmParser.a LLVMAnalysis.a LLVMTransformUtils.a LLVMScalarOpts.a LLVMTarget.a
。请注意,这仅适用于静态链接库。LLVM 分为大量静态库,您需要的库列表可能比上面列出的库列表长得多。要查看完整的库列表,请使用:
llvm-config --libs all
。如以下所述,使用LINK_COMPONENTS
可以避免设置LLVMLIBS
。
LINK_COMPONENTS
此变量包含一个空格分隔的组件列表,LLVM
Makefile
将这些组件传递给llvm-config
工具以生成程序的链接行。例如,要链接所有 LLVM 库,请使用LINK_COMPONENTS = all
。
LIBS
要链接动态库,请将
-l<library base name>
添加到LIBS
变量中。LLVM 构建系统将在与静态库相同的位置查找动态库。例如,要链接
libsample.so
,您将在您的Makefile
中添加以下行LIBS += -lsample
请注意,LIBS
必须在包含 Makefile.common
之后出现在 Makefile 中。
其他变量¶
CFLAGS
& CPPFLAGS
此变量可用于分别向 C 和 C++ 编译器添加选项。它通常用于添加告知编译器搜索头文件的其他目录位置的选项。
强烈建议您追加到
CFLAGS
和CPPFLAGS
,而不是覆盖它们。LLVM 的Makefiles
中可能已经包含了一些有用的选项,您可能不想覆盖它们。
目标代码的放置位置¶
构建的库和可执行文件的最终位置将取决于您是进行 Debug
、Release
还是 Profile
构建。
库
所有库(静态和动态)都将存储在
PROJ_OBJ_ROOT/<type>/lib
中,其中 type 分别为Debug
、Release
或Profile
,用于调试、优化或概要分析构建。
可执行文件
所有可执行文件都将存储在
PROJ_OBJ_ROOT/<type>/bin
中,其中 type 分别为Debug
、Release
或Profile
,用于调试、优化或概要分析构建。
更多帮助¶
如果您有任何疑问或需要任何帮助来创建 LLVM 项目,LLVM 团队将非常乐意提供帮助。您始终可以在 Discourse 论坛 上发布您的问题。