创建 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 位置的 configure 脚本,以及支持来自单个源代码目录的多个对象目录的能力。
如果您想设计自己的构建系统,研究其他项目和 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<库基本名称>
添加到LIBS
变量。 LLVM 构建系统将在与静态库相同的位置查找动态库。例如,要链接
libsample.so
,您的Makefile
中将包含以下行LIBS += -lsample
请注意,LIBS
必须在 Makefile 中 Makefile.common
包含之后出现。
杂项变量¶
CFLAGS
& CPPFLAGS
此变量可用于向 C 和 C++ 编译器分别添加选项。 它通常用于添加选项,告诉编译器搜索头文件的其他目录的位置。
强烈建议您附加到
CFLAGS
和CPPFLAGS
,而不是覆盖它们。 LLVMMakefile
可能已经包含您可能不想覆盖的有用选项。
目标代码的放置¶
构建的库和可执行文件的最终位置将取决于您执行的是 Debug
、Release
还是 Profile
构建。
库
所有库(静态和动态)都将存储在
PROJ_OBJ_ROOT/<type>/lib
中,其中 type 对于调试、优化或性能分析构建分别是Debug
、Release
或Profile
。
可执行文件
所有可执行文件都将存储在
PROJ_OBJ_ROOT/<type>/bin
中,其中 type 对于调试、优化或性能分析构建分别是Debug
、Release
或Profile
。
更多帮助¶
如果您有任何问题或需要创建 LLVM 项目的任何帮助,LLVM 团队将非常乐意为您提供帮助。 您可以随时将您的问题发布到 Discourse 论坛。