CMake 軟件打包準則

出自 Arch Linux 中文维基
Arch 打包準則

32 位CLRCMakeCrossDKMSEclipseElectronFontFree PascalGNOMEGoHaskellJavaKDEKernelLispMesonMinGWNode.jsNonfreeOCamlPerlPHPPythonRRubyRustVCSWebWine

本文檔涵蓋為使用 CMake 的軟件編寫 PKGBUILD 的標準和準則。

簡介[編輯 | 編輯原始碼]

CMake 網站

CMake is an open-source, cross-platform family of tools designed to build, test and package software. CMake is used to control the software compilation process using simple platform and compiler independent configuration files, and generate native makefiles and workspaces that can be used in the compiler environment of your choice.

典型用法[編輯 | 編輯原始碼]

典型用法是運行 cmake 命令,然後執行構建命令。該 cmake 命令通常會設置一些參數,檢查所需的依賴關係並創建構建文件,從而使該軟件可以通過諸如 makeninja 的其他工具進行構建。

CMake 的不良行為[編輯 | 編輯原始碼]

由於其自身的生成生成文件的內部特性,有時 CMake 可能會以不良方式運行。這樣,在為基於 CMake 的軟件編寫 PKGBUILD 時,應注意一些步驟。

CMake 可以自動覆蓋默認的編譯器優化標誌[編輯 | 編輯原始碼]

使用 -DCMAKE_BUILD_TYPE=Release 選項運行 CMake 是很常見的。一些上游項目甚至無意中在其構建指令中包含此選項,但這會產生不希望的行為。

每個構建類型都會導致 CMake 自動將一組標誌附加到 CFLAGSCXXFLAGS。當使用通用 Release build 類型時,它會自動附加-O3[1] 編譯器優化標誌,這將覆蓋當前為 -O2 (在 makepkg 配置文件[損壞的連結:無效的章節]中定義)的默認 Arch Linux 標誌。這是不希望的,因為它偏離了 Arch Linux 的目標優化級別。

關於 -O3 的注意事項[編輯 | 編輯原始碼]

使用 -O3 不能保證軟件的性能會更好,有時甚至會減慢程序的速度。在某些情況下,它也會破壞軟件。有一個很好的理由説明為什麼 Linux 開發人員選擇 -O2 作為目標優化級別,我們應該堅持使用它。除非您確切知道自己在做什麼,或者如果上游明確吿訴或暗示需要 -O3 ,否則我們應該避免在包中使用它。

修復自動優化標誌覆蓋[編輯 | 編輯原始碼]

由於 CMake 的靈活性,以 100% 有保證的方式解決這個問題不是一個簡單的問題。請注意,沒有標準的解決方案可適用於所有情況。本節將討論可能的解決方案和應遵守的一些要點。

默認的 CMake 構建類型是 None ,默認情況下它不會向 CFLAGSCXXFLAGS 附加任何標誌,因此只要省略 CMAKE_BUILD_TYPE 選項的使用,就可以像默認為 None一樣工作。但請注意,忽略此選項並不能保證解決問題,因為如果命令行中未設置 CMAKE_BUILD_TYPE ,則許多軟件項目會自動將 CMake 文件中的生成類型設置為Release (或其他類型)。

由於默認的 None build 類型在默認情況下不會向 CFLAGSCXXFLAGS 追加任何標誌,因此使用 -DCMAKE_BUILD_TYPE=None 選項也可以工作。一般來説,使用 -DCMAKE_BUILD_TYPE=None 選項比省略使用 CMAKE_BUILD_TYPE 要好。當上游自動將生成類型設置為 Release 時,它將覆蓋以下情況:省略 CMAKE_BUILD_TYPE 時,它默認不會附加任何標誌,並且很少看到軟件為 None 構建類型設置不需要的標誌。

但不幸的是,事情並沒有那麼簡單,比如只使用 -DCMAKE_BUILD_TYPE=None t來解決這個問題。當使用 None 構建類型修復 -O3 問題時,可能會遇到另一個問題。對於許多軟件項目來説,在 CMake文 件中為版本生成類型定義一些必需的編譯器標誌是一種常見的做法(例如,設置 CMAKE_C_FLAGS_RELEASE and CMAKE_CXX_FLAGS_RELEASE 變量)。如果使用 None 構建類型,在沒有這些上游定義標誌的情況下編譯時,此類軟件可能會中斷或出現錯誤行為。為了確定是否缺少某些標誌,您需要查看 CMake 文件,或者可以比較 make VERBOSE=1 對於 None Release 構建類型的輸出。如果 None 構建類型導致某些上游定義的標誌丟失,該怎麼辦?在這種情況下,您可能正處於兩種有問題的情況的中間,因為如果使用 Release 構建類型,您將丟失一些必需的上游定義的標誌。解決這種情況沒有標準的辦法,應該逐案分析。如果上游為 Release 構建類型定義了 -O2 ,則可以使用 -DCMAKE_BUILD_TYPE=Release (參見下文)。否則,修補C Make 文件可能是一個解決方案。

一些軟件項目在其 CMake 文件中為 Release 構建類型硬編碼為 -O2,因此,如果您確定 -O2 是正在使用的優化級別,那麼在這種情況下可以安全地設置 -DCMAKE_BUILD_TYPE=Release

警吿:
  • 使用 None 類型時,某些軟件可能會崩潰。當使用 None 構建類型檢查軟件是否會中斷或丟失功能時,請測試軟件。
  • 某些軟件可能只適用於 Release 構建類型。你需要實驗和測試軟件。

驗證修復[編輯 | 編輯原始碼]

通過啟用生成工具的詳細模式,可以驗證CMake是否正確使用了修復程序。例如,當使用 make (這是CMake的默認值)時,可以通過將 VERBOSE=1 添加到 make 中(比如 make VERBOSE=1)來完成。這將使 make 能夠輸出正在執行的編譯器命令。然後,您可以運行 makepkg 並檢查輸出,看看編譯器是否使用了 -D_FORTIFY_SOURCE=2-O2 標誌。如果在每個命令行中顯示多個優化標誌,則該行中的最後一個標誌將是編譯器使用的標誌(這意味着 -O2 需要是最後一個優化標誌才能生效)。

前綴和庫安裝目錄[編輯 | 編輯原始碼]

標準 Arch Linux /usr 前綴可以由 -DCMAKE_INSTALL_PREFIX=/usr CMake 選項指定。通常需要這樣做,因為許多軟件默認將文件安裝到 /usr/local 前綴中。

一些上游項目將 CMake 文件設置為將庫安裝到 /usr/lib64 目錄中。如果是這種情況,可以使用 -DCMAKE_INSTALL_LIBDIR=lib CMake選項將庫安裝目錄正確設置為 /usr/lib

提示和技巧[編輯 | 編輯原始碼]

指定目錄[編輯 | 編輯原始碼]

自從CMake 3.13版本以來,有一個 -B 選項可以自動創建構建目錄。這樣可以避免使用單獨的mkdir(或install)命令創建生成目錄。-S 選項指定源目錄(搜索 CMakeLists.txt 文件的位置),並避免在執行 cmake 之前將 cd 插入源樹。這兩個選項結合在一起,是指定生成目錄和源目錄的方便方法。例如,對於構建名為 foo 的程序:

PKGBUILD
build() {
    cmake -B build -S "foo-${pkgver}" [other_cmake_options]
    make -C build
}

減少可能不需要的輸出[編輯 | 編輯原始碼]

-Wno-dev 選項將抑制某些警吿的輸出,這些警吿僅適用於編寫 CMakeLists.txt 文件的上游項目開發人員。刪除這些警吿將使 CMake 輸出更好,並減少檢查它的負擔。一般來説,這些警吿通常可以被打包程序安全地忽略。

從二進制文件中刪除不安全的 RPATH 引用[編輯 | 編輯原始碼]

有時生成的二進制文件可能在 RPATH中包含不安全的引用。這可以通過在構建的包上運行 Namcap 來驗證,並且包含一個應該修復的安全問題。使用 CMAKE_SKIP_INSTALL_RPATH=YES CMAKE_SKIP_RPATH=YES CMake 選項很有可能解決此問題。您需要同時使用這兩個選項進行實驗,並查看在所討論的軟件中什麼可以工作(不需要同時使用這兩個選項)。

獲取所有可用的 CMake 選項[編輯 | 編輯原始碼]

要獲取軟件項目可用的所有「可見」CMake選項,請在源樹(主 CMakeLists.txt 文件所在)中執行 cmake -LAH

如果要保存輸出以供以後參考,可以將其重定向到文件:

$ cmake -LAH >options.txt 2>&1

模板[編輯 | 編輯原始碼]

下面是 build() 函數的通用模板,它是基於 CMake 的包的起點。假設包被命名為 foo,它是基於 C 和 C++ 的,並且它不為 CMake 文件中的 Release 構建類型定義任何必需的編譯器標誌:

PKGBUILD
build() {
    cmake -B build -S "foo-${pkgver}" \
        -DCMAKE_BUILD_TYPE='None' \
        -DCMAKE_INSTALL_PREFIX='/usr' \
        -Wno-dev
    make -C build
}

不要忘記將 cmake 放在 makedepends

範例包[編輯 | 編輯原始碼]

另請參見[編輯 | 編輯原始碼]