MyFirstTypoFix¶
簡介¶
本教學將引導您完成對 LLVM 進行變更,並將其貢獻回 LLVM 專案的流程。
注意
此處展示的程式碼變更僅為範例,並非您實際上應提交給 LLVM 專案的內容。對於您對 LLVM 的第一個實際變更,程式碼將會不同,但本指南的其餘部分仍然適用。
我們將對 Clang 進行變更,但 LLVM 其他部分的步驟是相同的。即使我們將進行的變更很簡單,我們也將涵蓋諸如建置 LLVM、執行測試和程式碼審查等步驟。這是良好的實務,您將為進行更大的變更做好準備。
我們假設您
知道如何使用編輯器,
具備基礎 C++ 知識,
知道如何在您的系統上安裝軟體,
熟悉命令列,
具備 git 的基礎知識。
我們要做的變更¶
Clang 對於無限遞迴有一個警告
$ echo "void foo() { foo(); }" > ~/test.cc
$ clang -c -Wall ~/test.cc
test.cc:1:12: warning: all paths through this function will call itself [-Winfinite-recursion]
這已經夠清楚了,但並不是很吸引人。讓我們稍微改進一下措辭
test.cc:1:12: warning: to understand recursion, you must first understand recursion [-Winfinite-recursion]
相依性¶
我們需要一些工具
git:用於簽出 LLVM 原始碼,
C++ 編譯器:用於編譯 LLVM 原始碼。您會需要最新版本 <host_cpp_toolchain> 的 Clang、GCC 或 Visual Studio。
CMake:用於設定如何在您的系統上建置 LLVM,
ninja:執行 C++ 編譯器以(重新)建置 LLVM 的特定部分,
python:用於執行 LLVM 測試。
以 Ubuntu 為例
$ sudo apt-get install git clang cmake ninja-build python
建置 LLVM¶
簽出¶
原始碼儲存在 Github 上 的一個大型儲存庫(「單一儲存庫」)中。
下載可能需要一段時間!
$ git clone https://github.com/llvm/llvm-project.git
這將建立一個名為「llvm-project」的目錄,其中包含所有原始碼。(匿名簽出是可以的 - 推送提交使用不同的機制,我們稍後會看到。)
設定您的工作區¶
在我們可以建置程式碼之前,我們必須透過執行 CMake 來設定確切的建置方式。CMake 結合來自三個來源的資訊
您做出的明確選擇(這是偵錯建置嗎?)
從您的系統偵測到的設定(程式庫安裝在哪裡?)
專案結構(哪些檔案是「clang」的一部分?)
首先,建立一個用於建置的目錄。通常,這是 llvm-project/build
。
$ mkdir llvm-project/build
$ cd llvm-project/build
現在,執行 CMake
$ cmake -G Ninja ../llvm -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS=clang
如果一切順利,您會看到很多「執行測試」的行,最後
Configuring done
Generating done
Build files have been written to: /path/llvm-project/build
您應該在目前目錄中看到一個 build.ninja
檔案。
讓我們稍微分解一下最後一個命令
-G Ninja:告訴 CMake 我們將使用 ninja 進行建置,並建立
build.ninja
檔案。../llvm:這是「主要」LLVM 專案原始碼的路徑
兩個 -D 旗標設定 CMake 變數,這會覆寫 CMake/專案預設值
CMAKE_BUILD_TYPE=Release:以最佳化模式建置,這是(令人驚訝地)最快的選項。
如果您想在偵錯工具下執行,您應該使用預設的 Debug(完全未最佳化,並且會導致 >10 倍的測試執行速度變慢)或 RelWithDebInfo,這是一個折衷方案。
預設情況下,
Release
建置中未啟用斷言。您可以使用LLVM_ENABLE_ASSERTIONS=ON
來啟用它們。LLVM_ENABLE_PROJECTS=clang:這列出了您有興趣建置的 LLVM 子專案,以及 LLVM 本身。可以列出多個專案,以分號分隔,例如
clang;lldb
。在本範例中,我們將對 Clang 進行變更,因此我們僅新增 clang。
最後,建立 llvm-project/build/compile-commands.json
的符號連結(或複製)到 llvm-project/
中
$ ln -s build/compile_commands.json ../
(這對於建置和測試不是絕對必要的,但允許諸如 clang-tidy、clang-query 和 clangd 之類的工具在您的原始碼樹中工作)。
建置和測試¶
最後,我們可以建置程式碼了!首先執行此操作很重要,以確保我們在進行變更之前處於良好狀態。但是要建置什麼?在 ninja 中,您指定一個目標。如果我們只想建置 clang 二進位檔,我們的目標名稱是「clang」,我們執行
$ ninja clang
我們第一次建置會非常慢 - Clang + LLVM 是很多程式碼。但是增量建置很快:ninja 只會重新建置已變更的部分。當它最終完成時,您應該有一個可運作的 clang 二進位檔。嘗試執行
$ bin/clang --version
還有一個用於建置和執行所有 clang 測試的目標
$ ninja check-clang
這是 LLVM 中的常見模式:check-llvm 是所有針對 LLVM 核心的檢查,其他專案具有類似 check-lldb
、check-flang
等的目標。
進行變更¶
變更¶
我們需要找到包含錯誤訊息的檔案。
$ git grep "all paths through this function" ..
../clang/include/clang/Basic/DiagnosticSemaKinds.td: "all paths through this function will call itself">,
出現在 DiagnosticSemaKinds.td
中的字串是 Clang 列印的字串。*.td
檔案定義表格 - 在這種情況下,它是 clang 可以發出的警告和錯誤及其訊息的列表。讓我們在您最喜歡的編輯器中更新訊息
$ vi ../clang/include/clang/Basic/DiagnosticSemaKinds.td
找到訊息(它應該在 warn_infinite_recursive_function
下)。將訊息變更為「in order to understand recursion, you must first understand recursion」。
再次測試¶
為了驗證我們的變更,我們可以建置 clang 並手動檢查它是否運作。
$ ninja clang
$ bin/clang -c -Wall ~/test.cc
test.cc:1:12: warning: in order to understand recursion, you must first understand recursion [-Winfinite-recursion]
我們也應該執行測試以確保我們沒有破壞任何東西。
$ ninja check-clang
請注意,這次建置速度快得多,但測試執行時間卻一樣長。Ninja 不知道哪些測試可能會受到影響,因此它會執行所有測試。
********************
Failing Tests (1):
Clang :: SemaCXX/warn-infinite-recursion.cpp
嗯,這很有道理…而且測試輸出表明它正在尋找舊字串「call itself」,但找到了我們的新訊息。請注意,隨著時間的推移新增更多測試,可能會以類似的方式導致更多測試失敗。
讓我們透過更新測試中的預期結果來修正它。
$ vi ../clang/test/SemaCXX/warn-infinite-recursion.cpp
在我們看到 // expected-warning{{call itself}}
的任何地方(或來自原始警告文字的類似內容),讓我們將其替換為 // expected-warning{{to understand recursion}}
。
現在我們可以再次執行所有測試,但這是一個緩慢地迭代變更的方式!相反,讓我們找到一種方法來重新執行特定的測試。LLVM 中有兩種主要類型的測試
lit 測試(例如
SemaCXX/warn-infinite-recursion.cpp
)。
這些是複雜的 shell 腳本,它們執行命令列工具並驗證輸出。它們位於諸如 clang/**test**/FixIt/dereference-addressof.c
之類的檔案中。像這樣重新執行
$ bin/llvm-lit -v ../clang/test/SemaCXX/warn-infinite-recursion.cpp
單元測試(例如
ToolingTests/ReplacementTest.CanDeleteAllText
)
這些是 C++ 程式,它們呼叫 LLVM 函式並驗證結果。它們位於諸如 ToolingTests 之類的套件中。像這樣重新執行
$ ninja ToolingTests && tools/clang/unittests/Tooling/ToolingTests --gtest_filter=ReplacementTest.CanDeleteAllText
在本機提交¶
我們將變更儲存到本機 git 分支。這讓我們可以在審查變更時處理其他事情。變更應具有標題和描述,以向審查者和程式碼的未來讀者解釋進行變更的原因。
目前,我們只新增標題。
$ git checkout -b myfirstpatch
$ git commit -am "[clang][Diagnostic] Clarify -Winfinite-recursion message"
現在我們準備好將此變更發送到世界各地!
[clang]
和 [Diagnostic]
前綴是我們所謂的標籤。這種寬鬆的慣例告訴 git 記錄的讀者,變更正在修改哪些區域。如果您不知道您已變更的模組的標籤,您可以查看儲存庫這些區域的提交歷史記錄。
$ git log --oneline ../clang/
或使用 GitHub,例如 https://github.com/llvm/llvm-project/commits/main/clang。
標籤是不精確的,因此如果您不確定要放什麼,請不要擔心。如果審查者認為需要標籤,他們會建議一些。
程式碼審查¶
上傳變更以供審查¶
LLVM 程式碼審查透過 GitHub 上的提取請求進行,請參閱 GitHub 文件,以了解如何在 GitHub 上開啟提取請求。
尋找審查者¶
LLVM 社群中的任何人都可以審查變更。對於較大和較複雜的變更,重要的是審查者具有 LLVM 領域的經驗,並且非常了解設計目標。變更的作者通常會指派特定的審查者。git blame
和 git log
可用於尋找可以審查的先前作者。
我們的 GitHub 機器人也會標記和通知 LLVM 周圍的各種「團隊」。團隊成員定期為這些特定領域貢獻和審查程式碼,因此如果您沒有選擇任何特定的人,他們中的一人會審查您的變更。
審查流程¶
當您開啟提取請求時,某些自動化功能會新增註解,並根據您已變更的部分通知子專案的不同成員。
在幾天之內,應該有人開始審查。他們可能會將自己新增為審查者,或只是開始留下評論。每次審查更新時,您都會收到另一封電子郵件。有關更多詳細資訊,請參閱 程式碼審查政策。
更新您的變更¶
如果您根據審查者的評論進行變更,只需使用更多提交更新您的分支,然後推送到您的 llvm-project
GitHub 分支。最好直接回覆審查者的評論,而不是期望他們再次閱讀所有變更。
例如,您可能會評論「我已完成此操作」或「我能夠完成此部分,但對…有疑問」。
審查期望¶
為了使 LLVM 成為一項長期可持續的努力,程式碼需要可維護且經過良好測試。程式碼審查有助於實現該目標。尤其是對於新的貢獻者而言,這通常意味著多輪審查和對不符合專案整體架構的設計決策的反駁。
對於您的第一個修補程式,這意味著
友善,並期望審查者友善地回報 - LLVM 有一個 行為準則,每個人都應該遵守;
要有耐心 - 了解新功能如何融入專案的架構通常需要耗費時間,而且人們必須將其與生活中的其他責任兼顧;每週 ping 一次審查,如果沒有回應;
如果您無法達成共識,通常最好的方法是按照審查者的要求去做;我們針對程式碼的可讀性進行最佳化,審查者更適合判斷;如果感覺這不是正確的選項,您可以透過評論詢問他們或新增另一位審查者以獲得第二意見。
接受提取請求¶
當審查者對變更感到滿意時,他們將核准提取請求。他們可能會留下一些更小的評論,您應該在合併之前處理這些評論,但此時審查已完成。是時候將其合併了!
提交權限¶
透過代理提交¶
由於這是您的第一個變更,因此您還沒有權限自行合併它。審查者不知道這一點,因此您需要告訴他們!在審查中留下評論,例如
感謝 @<審查者的使用者名稱>。我沒有提交權限,您可以為我合併此 PR 嗎?
提取請求將被關閉,您將收到 GitHub 的通知。
取得提交權限¶
一旦您為 LLVM 貢獻了一些修補程式,就可以開始考慮自行取得提交權限。如果符合以下條件,這可能是一個好主意
您已提交 3-5 個範圍比「修正錯字」更大的修補程式
您願意審查與您的變更密切相關的變更
您希望繼續為 LLVM 做出貢獻。
該流程在 開發人員政策文件 中有所描述。
能力越大¶
實際上,現在是閱讀 開發人員政策 其餘部分的好時機。
PR 提交後的問題¶
一旦您的變更被提交,它將被自動建置機器人拾取,這些機器人將在各種組態中建置和測試您的修補程式。
http://lab.llvm.org/buildbot/#/console 上的「主控台」檢視顯示特定提交的結果。如果您想追蹤您的變更如何影響建置機器人,這應該是第一個要查看的地方。
欄是建置組態,列是個別提交。沿著列是彩色氣泡。氣泡的顏色代表建置的狀態。綠色表示通過,紅色表示失敗,黃色表示正在建置中。
紅色建置可能在您的變更提交之前就已經失敗。這表示您沒有破壞建置,但您應該檢查您是否沒有透過新增新問題使其變得更糟。
注意
主控台檢視中僅顯示最近的變更。如果您的變更不在那裡,請依靠 PR 評論和建置機器人電子郵件來通知您任何問題。
如果包含您的變更的建置中存在問題,您可能會透過電子郵件或作為 PR 上的評論收到報告。請檢查問題是否是專門由您的變更引起的。由於建置包含來自許多作者的變更,並且有時會因不相關的基礎架構問題而失敗。
要查看建置的詳細資訊,請按一下主控台檢視中的氣泡,或問題報告中提供的連結。您將能夠查看和下載該建置每個階段的記錄。
如果您需要幫助理解問題,或有任何其他問題,您可以在您的 PR 上或在 Discord 上以評論的形式提出。
如果您沒有收到任何問題報告,則無需您採取任何行動。您的變更按預期運作,做得好!
還原¶
如果您的變更導致了問題,應盡快還原。這是 LLVM 開發 的正常部分,每個提交者(無論經驗多麼豐富)都會經歷。
如果您對您的變更是否可以快速修復有任何疑問,請還原它。然後您有充足的時間來調查並產生可靠的修復。
其他人可能會為您還原您的變更,或者您可以使用 GitHub 介面 建立還原提取請求。如果可能,請將您的原始審查者新增到這個新的提取請求中。
結論¶
現在您應該了解對 LLVM 專案的貢獻生命週期。
如果某些細節仍然不清楚,請不要擔心。LLVM 專案的流程確實與您在 GitHub 上其他地方可能習慣的流程有所不同。在專案內部,不同子專案的期望也可能有所不同。
因此,無論您貢獻什麼,要知道我們並不期望完美。如果您不確定,請隨時提出問題,並期望如果您遺漏了某些內容,有人會禮貌地指出並幫助您解決。
評論¶
審查者可以對變更留下評論,您可以回覆。有些評論附加到特定行,並與程式碼交錯顯示。您可以回覆這些評論。也許是為了澄清所要求的內容,或告訴審查者您已完成所要求的內容。