建立 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.common 之後出現在 Makefile 中。

其他變數

CFLAGS & CPPFLAGS

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

強烈建議您附加到 CFLAGSCPPFLAGS,而不是覆寫它們。LLVM Makefiles 可能已經包含您可能不想覆寫的有用選項。

物件程式碼的放置位置

建置的函式庫和可執行檔的最終位置將取決於您執行的是 DebugReleaseProfile 建置。

函式庫

所有函式庫(靜態和動態)都將儲存在 PROJ_OBJ_ROOT/<type>/lib 中,其中 typeDebugReleaseProfile,分別用於偵錯、最佳化或分析建置。

可執行檔

所有可執行檔都將儲存在 PROJ_OBJ_ROOT/<type>/bin 中,其中 typeDebugReleaseProfile,分別用於偵錯、最佳化或分析建置。

進一步協助

如果您有任何問題或需要任何關於建立 LLVM 專案的協助,LLVM 團隊非常樂意提供協助。您可以隨時將您的問題發佈到 Discourse 論壇