patch
是一個用于將差異文件(補丁)應用到源代碼的工具,常用于修復 bug、添加功能或調整代碼結構。在您提供的代碼中,patch
命令通過一系列補丁文件(.patch
)修改了 open-amp
庫的源代碼。
patch
命令的核心作用
- 應用補丁:根據補丁文件(
.patch
)中的差異描述,修改目標文件的代碼。 - 自動化代碼修改:在構建流程中自動修改第三方庫的代碼,無需手動編輯。
關鍵參數解析
在您的代碼中,patch
命令的格式如下:
patch -p0 -d ${CMAKE_CURRENT_LIST_DIR} < ${PATCH_FILE}
-
-p0
:- 指定“路徑剝離級別”,
-p0
表示保留補丁文件中的完整路徑。 - 例如,如果補丁文件中的路徑是
a/src/file.c
,且當前目錄是/project
,則實際路徑為/project/a/src/file.c
。 - 如果使用
-p1
,則會剝離第一級路徑,變為src/file.c
。
- 指定“路徑剝離級別”,
-
-d ${CMAKE_CURRENT_LIST_DIR}
:- 指定補丁應用的工作目錄,即在此目錄下執行補丁操作。
-
< ${PATCH_FILE}
:- 將補丁文件內容作為輸入傳遞給
patch
命令。
- 將補丁文件內容作為輸入傳遞給
補丁文件的生成
補丁文件通常通過 diff
命令生成,例如:
diff -u original_file.c modified_file.c > my_patch.patch
生成的 .patch
文件會描述兩個文件的差異。
在您的代碼中的具體行為
- 下載
open-amp
庫:通過FetchContent_Declare
下載指定版本的代碼。 - 應用補丁:通過
PATCH_COMMAND
依次應用多個補丁文件(0001-*.patch
到0014-*.patch
),每個補丁對應一個代碼修改。- 例如,
0001-ns-acknowledge-the-received-creation-message.patch
可能修復了某個協議問題。
- 例如,
- 不執行構建:
CONFIGURE_COMMAND
、BUILD_COMMAND
等被設為空,表示只下載代碼并打補丁,不立即構建。
常見問題
- 補丁順序:補丁文件通常需要按順序應用(如
0001
、0002
),否則可能因依賴關系失敗。 - 路徑問題:若補丁文件中的路徑與目標代碼路徑不匹配,需調整
-p
參數。 - 兼容性:補丁可能因代碼版本更新而失效(例如原文件被修改)。
調試補丁
- 手動測試補丁:
cd ${CMAKE_CURRENT_LIST_DIR} patch -p0 --dry-run < 0001-*.patch # 模擬應用補丁(不實際修改文件) patch -p0 < 0001-*.patch # 實際應用補丁
- 若失敗,檢查:
- 補丁文件路徑是否正確。
- 目標代碼是否已更新導致沖突。
總結
在您的代碼中,patch
命令用于在下載 open-amp
庫后自動修改其源代碼。每個補丁文件對應一個代碼變更,通過 -p0
和 -d
參數確保路徑正確。這是管理第三方依賴時常見的自定義代碼行為的方法。
-p
參數決定了 補丁文件中的路徑如何被解析,直接關系到補丁能否正確應用到目標文件。它的核心作用是 “剝離補丁文件中路徑的前綴層級”,具體行為通過以下對比可以清晰理解:
場景對比:-p0
vs -p1
假設補丁文件 (my_patch.patch
) 中的路徑描述如下:
--- a/src/main.c # 原始文件路徑
+++ b/src/main.c # 修改后的文件路徑
@@ -10,7 +10,7 @@
- printf("Hello World");
+ printf("Hello OpenAMP");
1. 使用 -p0
- 行為:保留補丁文件中的完整路徑,直接按路徑尋找文件。
- 應用命令:
patch -p0 < my_patch.patch
- 路徑解析:
- 補丁中的路徑:
a/src/main.c
- 實際尋找的路徑:
當前目錄/a/src/main.c
- 補丁中的路徑:
- 適用場景:
- 補丁文件中的路徑是 絕對路徑 或 相對于當前目錄的完整路徑。
- 例如:你的代碼目錄結構完全匹配補丁中的路徑層級(如存在
a/src/main.c
)。
2. 使用 -p1
- 行為:剝離補丁文件中路徑的第一級目錄(即
a/
和b/
)。 - 應用命令:
patch -p1 < my_patch.patch
- 路徑解析:
- 補丁中的路徑:
a/src/main.c
- 實際尋找的路徑:
當前目錄/src/main.c
- 補丁中的路徑:
- 適用場景:
- 補丁文件中的路徑包含冗余的根目錄(如
a/
是臨時目錄,實際代碼位于src/
下)。 - 例如:補丁是從 Git 倉庫生成的(Git 默認生成包含
a/
和b/
的路徑)。
- 補丁文件中的路徑包含冗余的根目錄(如
實際應用場景示例
場景 1:補丁來自 Git 倉庫
- 生成補丁:
git diff > my_patch.patch
- 補丁內容:
--- a/src/main.c +++ b/src/main.c
- 應用補丁:
# 進入項目根目錄(包含 `src/` 目錄) cd /path/to/project patch -p1 < my_patch.patch # 剝離 `a/`,實際路徑變為 `src/main.c`
場景 2:手動生成的補丁
- 生成補丁:
diff -u old_file.c new_file.c > my_patch.patch
- 補丁內容:
--- old_file.c +++ new_file.c
- 應用補丁:
# 假設當前目錄下直接有 old_file.c patch -p0 < my_patch.patch # 不剝離任何路徑
調試技巧
-
檢查補丁中的路徑:
head -n 3 my_patch.patch # 查看補丁文件的路徑描述
輸出示例:
--- a/src/main.c +++ b/src/main.c
此時需要決定是否剝離
a/
和b/
。 -
試運行(不實際修改文件):
patch -p1 --dry-run < my_patch.patch
-
路徑不匹配時的表現:
- 如果
-p
參數錯誤,會看到類似錯誤:can't find file to patch at input line 3
- 如果
經驗法則
- 從 Git 生成的補丁:通常用
-p1
(剝離a/
和b/
)。 - 手動生成的補丁:
- 如果補丁路徑是相對當前目錄的完整路徑,用
-p0
。 - 如果補丁路徑包含多余的前綴(如臨時目錄名),用
-p1
或更高。
- 如果補丁路徑是相對當前目錄的完整路徑,用
- Linux 內核補丁:慣例使用
-p1
(剝離根目錄)。
回到你的代碼
在示例中,補丁文件路徑是直接相對于 ${CMAKE_CURRENT_LIST_DIR}
的,例如:
0001-ns-acknowledge-the-received-creation-message.patch
補丁中的路徑可能類似:
--- open-amp-main/lib/remoteproc.c
+++ open-amp-main/lib/remoteproc.c
此時:
- 如果代碼解壓后位于
${CMAKE_CURRENT_LIST_DIR}/open-amp-main
,則用-p0
(保留完整路徑)。 - 如果代碼解壓后直接展開到
${CMAKE_CURRENT_LIST_DIR}/lib/remoteproc.c
,則可能需要-p1
(剝離open-amp-main/
)。
總結
-p0
:保留補丁文件中的完整路徑,適合路徑完全匹配的場景。-p1
:剝離補丁路徑的第一級目錄,適合處理 Git 補丁或冗余前綴。
實際使用時,觀察補丁文件中的路徑層級和目標代碼的位置關系即可快速判斷。