建立 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

您可以透過兩種方式設定所有這些變數:

  • 您可以編寫自己的 Makefiles 來硬編碼這些值。

  • 您可以使用預先建立的 LLVM 範例專案。此範例專案包含 Makefiles、一個可用於設定 LLVM 位置的設定指令碼,以及從單一原始碼目錄支援多個物件目錄的功能。

如果您想設計自己的建構系統,研究其他專案和 LLVM 的 Makefiles 應該可以提供足夠的資訊,讓您了解如何編寫自己的 Makefiles

原始碼樹狀結構

為了使用 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 Makefiles 會將這些組件傳遞給 llvm-config 工具,以便為程式產生連結行。例如,要與所有 LLVM 程式庫連結,請使用 LINK_COMPONENTS = all

LIBS

要鏈接動態函式庫,請將 -l<函式庫 基本 名稱> 加入 LIBS 變數中。LLVM 建置系統會在與靜態函式庫相同的位置尋找動態函式庫。

例如,要鏈接 libsample.so,您可以在 Makefile 中加入以下行:

LIBS += -lsample

請注意,LIBS 必須在 Makefile 中包含 Makefile.common 之後出現。

其他變數

CFLAGSCPPFLAGS

這些變數可用於分別為 C 和 C++ 編譯器新增選項。它們通常用於新增選項,告訴編譯器搜尋標頭檔的其他目錄位置。

強烈建議您將選項附加到 CFLAGSCPPFLAGS 中,而不是覆蓋它們。LLVM Makefile 中可能已經有一些您不想覆蓋的有用選項。

物件碼放置位置

已建置函式庫和可執行檔的最終位置取決於您是進行 除錯發佈 還是 效能分析 建置。

函式庫

所有函式庫(靜態和動態)都將儲存在 PROJ_OBJ_ROOT/<類型>/lib 中,其中 *類型* 分別是 除錯發佈效能分析,分別表示除錯、優化或效能分析建置。

可執行檔

所有可執行檔都將儲存在 PROJ_OBJ_ROOT/<類型>/bin 中,其中 *類型* 分別是 除錯發佈效能分析,分別表示除錯、優化或效能分析建置。

進一步協助

如果您有任何問題或需要任何關於建立 LLVM 專案的幫助,LLVM 團隊非常樂意為您服務。您隨時可以在 Discourse 論壇 上發布您的問題。