使用 CMake 构建 LLVM¶
简介¶
CMake 是一个跨平台构建生成器工具。CMake 不会构建项目,它会生成构建工具(GNU make、Visual Studio 等)构建 LLVM 所需的文件。
如果**您是新贡献者**,请从LLVM 系统入门页面开始。此页面面向从旧版 configure/make 系统迁移过来的现有贡献者。
如果您非常渴望获得一个功能正常的 LLVM 构建,请转到快速入门部分。如果您是 CMake 新手,请先阅读CMake 基本用法,然后在您了解操作后返回快速入门部分。 选项和变量部分是自定义构建的参考。如果您已经熟悉 CMake,则建议从这里开始。
此页面面向 LLVM CMake 构建的用户。如果您正在寻找有关修改 LLVM CMake 构建系统的信息,您可能需要查看CMake 入门页面。它对 CMake 语言进行了基本概述。
快速入门¶
我们在这里使用命令行、非交互式 CMake 接口。
从下载并安装 CMake。最低要求版本为 3.20.0。
打开一个 Shell。您的开发工具必须通过 PATH 环境变量从此 Shell 中访问。
创建一个构建目录。不支持在源代码目录中构建 LLVM。切换到此目录
$ mkdir mybuilddir $ cd mybuilddir
在 Shell 中执行此命令,将path/to/llvm/source/root替换为 LLVM 源代码树的根路径
$ cmake path/to/llvm/source/root
CMake 将检测您的开发环境,执行一系列测试,并生成构建 LLVM 所需的文件。CMake 将对所有构建参数使用默认值。有关您可以修改的构建参数列表,请参阅选项和变量部分。
如果 CMake 无法检测到您的工具集,或者它认为环境不够正常,则可能会失败。在这种情况下,请确保您打算使用的工具集是 Shell 中唯一可访问的工具集,并且 Shell 本身是开发环境的正确 Shell。例如,如果您的 PATH 环境变量中可以访问 POSIX Shell,CMake 将拒绝构建 MinGW Makefile。您可以强制 CMake 使用给定的构建工具;有关说明,请参阅下面的用法部分。您可能还需要控制 LLVM 启用的目标或构建的 LLVM 组件;请参阅下面的常用 LLVM 相关变量。
CMake 完成运行后,继续使用 IDE 项目文件或从构建目录启动构建
$ cmake --build .
--build
选项告诉cmake
调用底层构建工具(make
、ninja
、xcodebuild
、msbuild
等)。当然,可以直接调用底层构建工具,但
--build
选项是可移植的。LLVM 构建完成后,从构建目录安装它
$ cmake --build . --target install
--target
选项带有install
参数以及--build
选项,告诉cmake
构建install
目标。可以通过调用构建目录中生成的
cmake_install.cmake
脚本在安装时设置不同的安装前缀$ cmake -DCMAKE_INSTALL_PREFIX=/tmp/llvm -P cmake_install.cmake
CMake 基本用法¶
本节解释 CMake 的基本方面,您在日常使用中可能需要用到这些方面。
CMake 提供了大量的文档,包括 html 文件和通过 cmake
可执行文件本身访问的在线帮助。执行cmake --help
以获取更多帮助选项。
CMake 允许您指定构建工具(例如,GNU make、Visual Studio 或 Xcode)。如果未在命令行上指定,CMake 会尝试根据您的环境猜测要使用哪个构建工具。一旦它识别出您的构建工具,CMake 就会使用相应的生成器为您的构建工具创建文件(例如,Makefile 或 Visual Studio 或 Xcode 项目文件)。您可以使用命令行选项-G "Name of the generator"
显式指定生成器。要查看系统上可用的生成器列表,请执行
$ cmake --help
这将在帮助文本的末尾列出生成器名称。
生成器的名称区分大小写,并且可能包含空格。因此,您应该在引号中完全按照cmake --help
输出中列出的方式输入它们。例如,要专门为 Visual Studio 12 生成项目文件,您可以执行
$ cmake -G "Visual Studio 12" path/to/llvm/source/root
对于给定的开发平台,可能存在多个合适的生成器。如果您使用 Visual Studio,“NMake Makefiles”是可以用于使用 NMake 构建的生成器。默认情况下,CMake 选择开发环境支持的最具体的生成器。如果您想要备用生成器,则必须使用-G
选项告诉 CMake。
选项和变量¶
变量自定义构建的生成方式。选项是布尔变量,可能的值为 ON/OFF。选项和变量在 CMake 命令行上定义如下
$ cmake -DVARIABLE=value path/to/llvm/source
您可以在初始 CMake 调用之后设置变量以更改其值。您还可以取消定义变量
$ cmake -UVARIABLE path/to/llvm/source
变量存储在 CMake 缓存中。这是一个名为CMakeCache.txt
的文件,存储在cmake
生成的构建目录的根目录中。不建议手动编辑它。
变量在 CMake 缓存中列出,并在本文档的后面列出,变量名称和类型之间用冒号分隔。您也可以在 CMake 命令行上指定变量和类型
$ cmake -DVARIABLE:TYPE=value path/to/llvm/source
常用 CMake 变量¶
以下是一些经常使用的 CMake 变量,以及简要说明。有关完整文档,请查阅 CMake 手册,或执行cmake --help-variable VARIABLE_NAME
。请参阅下面的常用 LLVM 相关变量,了解控制 LLVM 功能和启用子项目的常用变量信息。
- CMAKE_BUILD_TYPE:STRING
这配置了
make
或ninja
构建的优化级别。可能的值
构建类型
优化
调试信息
断言
最适合
Release
速度优先
否
否
LLVM 和 Clang 用户
Debug
无
是
是
LLVM 开发人员
RelWithDebInfo
速度优先
是
否
也需要调试的用户
MinSizeRel
大小优先
否
否
磁盘空间受限时
优化使 LLVM/Clang 运行速度更快,但可能是逐步调试的障碍。
带有调试信息的构建可能会使用大量的 RAM 和磁盘空间,并且通常运行速度较慢。您可以通过使用
lld
来提高 RAM 使用率,请参阅LLVM_USE_LINKER选项。断言是帮助您查找错误的内部检查。启用时,它们通常会降低 LLVM 和 Clang 的速度,但在开发过程中可能很有用。您可以手动设置LLVM_ENABLE_ASSERTIONS以覆盖CMAKE_BUILD_TYPE的默认值。
如果您使用的是 Visual Studio 或 Xcode 等 IDE,则应使用 IDE 设置来设置构建类型。
注意:在 Windows(使用 MSVC 或 clang-cl 构建)上,CMake 的RelWithDebInfo设置不会启用与Release相同的优化。使用LLVM_ENABLE_PDB设置的Release构建类型可能是更好的选择。
- CMAKE_INSTALL_PREFIX:PATH
构建“install”目标时 LLVM 将安装到的路径。
- CMAKE_{C,CXX}_FLAGS:STRING
分别在编译 C 和 C++ 源文件时使用的额外标志。
- CMAKE_{C,CXX}_COMPILER:STRING
指定要使用的 C 和 C++ 编译器。如果您安装了多个编译器,CMake 可能不会默认使用您希望使用的编译器。
很少使用的 CMake 变量¶
以下是一些很少使用的 CMake 变量,以及简要说明和 LLVM 相关的注释。有关完整文档,请查阅 CMake 手册,或执行cmake --help-variable VARIABLE_NAME
。
- CMAKE_CXX_STANDARD:STRING
设置构建 LLVM 时要遵循的 C++ 标准。可能的值为 17 和 20。LLVM 需要 C++17 或更高版本。默认为 17。
- CMAKE_INSTALL_BINDIR:PATH
相对于 CMAKE_INSTALL_PREFIX 的可执行文件安装路径。默认为“bin”。
- CMAKE_INSTALL_DOCDIR:PATH
相对于 CMAKE_INSTALL_PREFIX 的文档安装路径。默认为“share/doc”。
- CMAKE_INSTALL_INCLUDEDIR:PATH
相对于 CMAKE_INSTALL_PREFIX 的头文件安装路径。默认为“include”。
- CMAKE_INSTALL_MANDIR:PATH
相对于 CMAKE_INSTALL_PREFIX 的手册页文件安装路径。默认为“share/man”。
CMake 缓存¶
最近,LLVM 和 Clang 一直在添加一些更复杂的构建系统功能。利用这些新功能通常涉及在命令行上传递的 CMake 变量的复杂链。Clang 提供了一组 CMake 缓存脚本,使这些功能更容易使用。
CMake 缓存文件是使用 CMake 的 -C 标志使用的
$ cmake -C <path to cache file> <path to sources>
CMake 缓存脚本在隔离的范围内处理,只有缓存的变量在主配置运行时保持设置。除非指定了 FORCE 选项,否则 CMake 缓存变量不会重置已设置的变量。
关于 CMake 缓存的一些说明
命令行参数的顺序很重要
-C 之前指定的 -D 参数在缓存处理之前设置,并且可以在缓存文件内部读取
-C 之后指定的 -D 参数在缓存处理之后设置,并且在缓存文件内部未设置
所有 -D 参数都将覆盖缓存文件设置
CMAKE_TOOLCHAIN_FILE 在缓存文件和命令行参数之后进行评估
建议所有 -D 选项都应在 -C 之前指定
有关通过缓存文件支持的一些高级构建配置的更多信息,请参阅高级构建配置。
执行测试¶
当构建check-all目标时执行测试。例如,如果您使用的是 Makefile,请在构建目录的根目录中执行此命令
$ make check-all
在 Visual Studio 上,您可以通过构建“check-all”项目来运行测试。有关测试的更多信息,请参阅LLVM 测试基础设施指南。
交叉编译¶
有关如何使用 CMake 进行交叉编译的通用说明,请参阅此 wiki 页面。它会详细解释,可能看起来令人生畏,但并非如此。在 wiki 页面上,有一些示例,包括工具链文件。转到Information how to set up various cross compiling toolchains
部分以获取快速解决方案。
另请参阅LLVM 相关变量部分,了解交叉编译时使用的变量。
在您的项目中嵌入 LLVM¶
从 LLVM 3.5 开始,CMake 构建系统将 LLVM 库导出为可导入的 CMake 目标。这意味着 LLVM 的客户端现在可以可靠地使用 CMake 来开发他们自己的基于 LLVM 的项目,以针对已安装的 LLVM 版本,而不管它是如何构建的。
这是一个简单的 CMakeLists.txt 文件示例,它导入 LLVM 库并使用它们来构建一个简单的应用程序simple-tool
。
cmake_minimum_required(VERSION 3.20.0)
project(SimpleProject)
find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
# Set your project compile flags.
# E.g. if using the C++ header files
# you will need to enable C++11 support
# for your compiler.
include_directories(${LLVM_INCLUDE_DIRS})
separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
add_definitions(${LLVM_DEFINITIONS_LIST})
# Now build our tools
add_executable(simple-tool tool.cpp)
# Find the libraries that correspond to the LLVM components
# that we wish to use
llvm_map_components_to_libnames(llvm_libs support core irreader)
# Link against LLVM libraries
target_link_libraries(simple-tool ${llvm_libs})
当在 CONFIG 模式下使用(如上例所示)时,find_package(...)
指令将在各种位置查找 LLVMConfig.cmake
文件(有关详细信息,请参阅 cmake 手册)。它创建一个 LLVM_DIR
缓存条目以保存找到 LLVMConfig.cmake
的目录,或允许用户指定目录(例如,通过将 -DLLVM_DIR=/usr/lib/cmake/llvm
传递给 cmake
命令或通过在 ccmake
或 cmake-gui
中直接设置它)。
此文件位于两个不同的位置。
<LLVM_INSTALL_PACKAGE_DIR>/LLVMConfig.cmake
,其中<LLVM_INSTALL_PACKAGE_DIR>
是 LLVM CMake 模块作为已安装的 LLVM 版本的一部分安装的位置。这通常是 lib 目录中的cmake/llvm/
。在 Linux 上,这通常是/usr/lib/cmake/llvm/LLVMConfig.cmake
。<LLVM_BUILD_ROOT>/lib/cmake/llvm/LLVMConfig.cmake
,其中<LLVM_BUILD_ROOT>
是 LLVM 构建树的根目录。**注意:这仅在使用 CMake 构建 LLVM 时可用。**
如果 LLVM 安装在操作系统的正常安装前缀中(例如,在 Linux 上,这通常是 /usr/
),find_package(LLVM ...)
将自动找到 LLVM(如果已正确安装)。如果 LLVM 未安装或您希望直接针对 LLVM 构建树进行构建,则可以使用前面提到的 LLVM_DIR
。
LLVMConfig.cmake
文件设置了各种有用的变量。值得注意的变量包括
LLVM_CMAKE_DIR
LLVM CMake 目录的路径(即包含 LLVMConfig.cmake 的目录)。
LLVM_DEFINITIONS
在针对 LLVM 构建时应使用的预处理器定义列表。
LLVM_ENABLE_ASSERTIONS
如果 LLVM 使用断言构建,则设置为 ON,否则设置为 OFF。
LLVM_ENABLE_EH
如果 LLVM 使用启用的异常处理 (EH) 构建,则设置为 ON,否则设置为 OFF。
LLVM_ENABLE_RTTI
如果 LLVM 使用运行时类型信息 (RTTI) 构建,则设置为 ON,否则设置为 OFF。
LLVM_INCLUDE_DIRS
包含 LLVM 头文件的目录的包含路径列表。
LLVM_PACKAGE_VERSION
LLVM 版本。此字符串可用于 CMake 条件,例如,
if (${LLVM_PACKAGE_VERSION} VERSION_LESS "3.5")
。LLVM_TOOLS_BINARY_DIR
包含 LLVM 工具(例如
llvm-as
)的目录的路径。
请注意,在上面的示例中,我们将 simple-tool
链接到几个 LLVM 库。库列表是通过使用 llvm_map_components_to_libnames()
CMake 函数确定的。有关可用组件的列表,请查看运行 llvm-config --components
的输出。
请注意,对于 LLVM < 3.5,使用 llvm_map_components_to_libraries()
而不是 llvm_map_components_to_libnames()
。这现在已弃用,将在 LLVM 的未来版本中删除。
在源代码外开发 LLVM 传递¶
可以从 LLVM 的源代码树之外开发 LLVM 传递(即针对已安装或构建的 LLVM)。下面提供了项目布局示例。
<project dir>/
|
CMakeLists.txt
<pass name>/
|
CMakeLists.txt
Pass.cpp
...
<project dir>/CMakeLists.txt
的内容
find_package(LLVM REQUIRED CONFIG)
separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
add_definitions(${LLVM_DEFINITIONS_LIST})
include_directories(${LLVM_INCLUDE_DIRS})
add_subdirectory(<pass name>)
<project dir>/<pass name>/CMakeLists.txt
的内容
add_library(LLVMPassname MODULE Pass.cpp)
请注意,如果您打算将来在某个时间点将此传递合并到 LLVM 源代码树中,使用 LLVM 的内部 add_llvm_library
函数(带 MODULE 参数)可能更有意义,方法是……
将以下内容添加到 <project dir>/CMakeLists.txt
(在 find_package(LLVM ...)
之后)
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
include(AddLLVM)
然后将 <project dir>/<pass name>/CMakeLists.txt
更改为
add_llvm_library(LLVMPassname MODULE
Pass.cpp
)
完成传递开发后,您可能希望将其集成到 LLVM 源代码树中。您可以通过两个简单的步骤实现
将
<pass name>
文件夹复制到<LLVM root>/lib/Transforms
目录。将
add_subdirectory(<pass name>)
行添加到<LLVM root>/lib/Transforms/CMakeLists.txt
。
编译器/平台特定主题¶
特定编译器和/或平台的说明。
Windows¶
- LLVM_COMPILER_JOBS:STRING
使用 msbuild 或 Visual Studio 构建时,指定每个项目使用的最大并行编译作业数。仅支持 Visual Studio 2010 CMake 生成器。0 表示使用所有处理器。默认为 0。
- CMAKE_MT:STRING
使用 clang-cl 编译时,最近的 CMake 版本将默认选择 llvm-mt 作为清单工具,而不是 Microsoft 的 mt.exe。这通常会导致如下错误:
-- Check for working C compiler: [...]clang-cl.exe - broken [...] MT: command [...] failed (exit code 0x1) with the following output: llvm-mt: error: no libxml2 ninja: build stopped: subcommand failed.
要解决此错误,请设置 CMAKE_MT=mt。