使用 CMake 建置 LLVM¶
簡介¶
CMake 是一個跨平台的建置產生器工具。CMake 不會建置專案,它會產生您的建置工具(GNU make、Visual Studio 等)建置 LLVM 所需的檔案。
如果您是新的貢獻者,請從LLVM 系統入門頁面開始。本頁面是為從傳統 configure/make 系統轉移過來的現有貢獻者所設計。
如果您真的急於取得可運作的 LLVM 建置版本,請前往快速開始章節。如果您是 CMake 新手,請從基本 CMake 用法開始,然後在您了解自己在做什麼之後,再回到快速開始章節。選項與變數章節是自訂建置的參考。如果您已經有 CMake 經驗,這是建議的起點。
本頁面是為 LLVM CMake 建置的使用者所設計。如果您正在尋找有關修改 LLVM CMake 建置系統的資訊,您可能需要查看CMake Primer頁面。它包含了 CMake 語言的基本概述。
快速開始¶
我們在此使用命令列、非互動式的 CMake 介面。
下載並安裝 CMake。最低要求版本為 3.20.0。
開啟 shell。您的開發工具必須可以透過 PATH 環境變數從此 shell 存取。
建立建置目錄。不支援在原始碼目錄中建置 LLVM。cd 到此目錄
$ 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
除了
--build
選項外,具有install
參數的--target
選項告知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 "產生器名稱"
明確指定產生器。若要查看系統上可用的產生器列表,請執行
$ cmake --help
cmake --help
這將在說明文字的末尾列出產生器名稱。
$ cmake -G "Visual Studio 12" path/to/llvm/source/root
產生器的名稱區分大小寫,並且可能包含空格。因此,您應該完全按照 cmake --help
輸出中列出的名稱輸入它們,並加上引號。例如,若要專門為 Visual Studio 12 產生專案檔案,您可以執行
cmake -G "Visual Studio 12" path/to/llvm/source
對於給定的開發平台,可能有多個適當的產生器。如果您使用 Visual Studio,“NMake Makefiles” 是您可以使用的產生器,用於使用 NMake 進行建置。依預設,CMake 會選擇您的開發環境支援的最特定的產生器。如果您想要替代產生器,您必須使用 -G
選項告知 CMake。
$ cmake -DVARIABLE=value path/to/llvm/source
$ cmake -UVARIABLE path/to/llvm/source
變數自訂建置的產生方式。選項是布林變數,可能的值為 ON/OFF。選項和變數在 CMake 命令列上定義,如下所示
cmake -DVARIABLE_NAME=value path/to/llvm/source
$ cmake -DVARIABLE:TYPE=value path/to/llvm/source
您可以在初始 CMake 呼叫後設定變數以變更其值。您也可以取消定義變數
cmake -UVARIABLE_NAME path/to/llvm/build
- 變數儲存在 CMake 快取中。這是一個名為
CMakeCache.txt
的檔案,儲存在您的建置目錄的根目錄中,由cmake
產生。不建議您自行編輯它。 變數在 CMake 快取中以及本文稍後的部分中列出,變數名稱和類型以冒號分隔。您也可以在 CMake 命令列上指定變數和類型
cmake -DVARIABLE_NAME:TYPE=value path/to/llvm/source
以下是一些常用的 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 的預設值。
如果您使用 IDE(例如 Visual Studio 或 Xcode),您應該使用 IDE 設定來設定建置類型。
- 注意:在 Windows 上(使用 MSVC 或 clang-cl 建置),CMake 的 RelWithDebInfo 設定不會啟用與 Release 相同的最佳化。使用 Release 建置類型並設定 LLVM_ENABLE_PDB 可能是一個更好的選擇。
CMAKE_INSTALL_PREFIX:PATH
建置 llvm 工具鏈可能會使用大量資源,尤其是在連結時。當您使用 Ninja 產生器時,這些選項可讓您限制平行處理。例如,為了避免 OOM 或進入交換空間,在 32GB 機器上,允許每個 15GB 可用 RAM 僅執行一個連結作業,請指定 -G Ninja -DLLVM_PARALLEL_LINK_JOBS=2
。
LLVM_TARGETS_TO_BUILD:STRING
- 控制啟用哪些目標。例如,您可能只需要啟用您的原生目標,例如
-DLLVM_TARGETS_TO_BUILD=X86
。 LLVM_USE_LINKER:STRING
- 覆寫系統的預設連結器。例如,使用
lld
和-DLLVM_USE_LINKER=lld
。 - 以下是一些少用的 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 快取¶
最近,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 目標時執行。例如,如果您正在使用 Makefiles,請在您的建置目錄的根目錄中執行此命令
$ 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/
),如果正確安裝了 LLVM,則 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
如果使用異常處理 (EH) 啟用建置 LLVM,則設定為 ON,否則為 OFF。
LLVM_ENABLE_RTTI
如果使用執行階段型別資訊 (RTTI) 建置 LLVM,則設定為 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 passes¶
可以開發 LLVM passes 在 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)
請注意,如果您希望將此 pass 在未來某個時間點合併到 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
)
當您完成 pass 的開發後,您可能會希望將其整合到 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 作為 Manifest Tool,而不是 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。