使用 CPack 進行封裝

CPack 是一個功能強大、易於使用、跨平台的軟體封裝工具,隨 CMake 一同發行。它使用 CMake 的產生器概念來抽象特定平台上的套件產生。它可以與 CMake 一起使用或不使用,但它可能依賴於系統上安裝的某些軟體。透過簡單的組態檔或使用 CMake 模組,專案的作者可以將複雜的專案封裝成一個簡單的安裝程式。本章將描述如何將 CPack 應用於 CMake 專案。

CPack 基礎知識

您的軟體的使用者可能不總是想要或能夠為了安裝軟體而建置它。該軟體可能是封閉原始碼的,或者可能需要很長時間才能編譯,或者在終端使用者應用程式的情況下,使用者可能沒有建置應用程式的技能或工具。對於這些情況,需要一種方法在一台機器上建置軟體,然後將安裝樹移動到另一台機器。最基本的方法是使用 DESTDIR 環境變數將軟體安裝到臨時位置,然後將該目錄 tar 或 zip 起來並將其移動到另一台機器。但是,DESTDIR 方法在 Windows 上效果不佳,原因很簡單,因為路徑名稱通常以磁碟機代號 (C:/) 開頭,您不能簡單地將一個完整路徑加上另一個完整路徑作為前綴,並獲得有效的路徑名稱。另一種更強大的方法是使用 CMake 中包含的 CPack。

CPack 是 CMake 中包含的一個工具,可用於為專案建立安裝程式和套件。CPack 可以建立兩種基本類型的套件:原始碼和二進位。CPack 的運作方式與 CMake 建置軟體的方式非常相似。它並非旨在取代原生封裝工具,而是為各種工具提供單一介面。目前,CPack 支援使用 NullSoft 安裝程式 NSIS 或 WiX 建立 Windows 安裝程式、Mac OS X PackageMaker 工具、OS X 拖放、OS X X11 拖放、Cygwin 安裝套件、Debian 套件、RPM、.tar.gz、.sh (自我解壓縮的 .tar.gz 檔案) 和 .zip 壓縮檔案。CPack 的實作方式與 CMake 類似。對於支援的每種封裝工具類型,都有一個以 C++ 編寫的 CPack 產生器,用於執行原生工具並建立套件。對於簡單的基於 tar 的套件,CPack 包含一個 tar 的程式庫版本,並且不需要在系統上安裝 tar。對於許多其他安裝程式,必須存在原生工具才能使 CPack 運作。

使用原始碼套件,CPack 會複製原始碼樹並建立 zip 或 tar 檔案。對於二進位套件,CPack 的使用與專案的 install 命令是否正確運作有關。設定 install 命令時,第一步是確保檔案進入正確的目錄結構並具有正確的權限。下一步是確保軟體可以重新定位並可以在已安裝的樹中執行。這可能需要更改軟體本身,並且有許多針對不同環境執行此操作的技術,這超出了本書的範圍。基本上,可執行檔應該能夠使用相對於其安裝位置的路徑來找到資料或其他檔案。CPack 將軟體安裝到臨時目錄中,並將安裝樹複製到原生封裝工具的格式中。一旦將 install 命令新增到專案中,在最簡單的情況下,只需將 CPack.cmake 檔案包含到專案中即可啟用 CPack。

簡單範例

最基本的 CPack 專案如下所示

cmake_minimum_required(VERSION 3.20)
project(CoolStuff)
add_executable(coolstuff coolstuff.cxx)
install(TARGETS coolstuff RUNTIME DESTINATION bin)
include(CPack)

在 CoolStuff 專案中,會建立一個可執行檔並將其安裝到 bin 目錄中。然後專案會包含 CPack 檔案。此時,專案 CoolStuff 將啟用 CPack。要為 CoolStuff 執行 CPack,您首先需要像建置任何其他 CMake 專案一樣建置該專案。CPack 會向產生的專案新增數個目標。這些目標在 Makefiles 中是 package 和 package_source,而在 Visual Studio 和 Xcode 中是 PACKAGE。例如,要使用 Makefile 產生器為 CoolStuff 建置原始碼和二進位套件,您將執行以下命令

mkdir build
cd build
cmake ../CoolStuff
make
make package
make package_source

這將建立一個名為 CoolStuff-0.1.1-Source.zip 的原始碼 zip 檔案、一個名為 CoolStuff-0.1.1-win32.exe 的 NSIS 安裝程式,以及一個二進位 zip 檔案 CoolStuff-0.1.1-win32.zip。可以使用 CPack 命令列執行相同的操作。

cd build
cpack --config CPackConfig.cmake
cpack --config CPackSourceConfig.cmake

包含 CPack.cmake 時會發生什麼?

當執行 include(CPack) 命令時,CPack.cmake 檔案會包含到專案中。預設情況下,這將使用 configure_file 命令,以在專案的二進位樹中建立 CPackConfig.cmakeCPackSourceConfig.cmake。這些檔案包含一系列 set 命令,用於在封裝步驟中執行 CPack 時設定變數。由 CPack.cmake 檔案設定的檔案名稱可以使用這兩個變數自訂:CPACK_OUTPUT_CONFIG_FILE,預設值為 CPackConfig.cmake,以及 CPACK_SOURCE_OUTPUT_CONFIG_FILE,預設值為 CPackSourceConfig.cmake

這些檔案的原始碼可在 Templates/CPackConfig.cmake.in 中找到。此檔案包含一些註解和一個由 CPack.cmake 設定的單一變數。該檔案包含此 CMake 程式碼行

@_CPACK_OTHER_VARIABLES_@

如果專案在原始碼樹的頂層包含檔案 CPackConfig.cmake.in,則會使用該檔案而不是 Templates 目錄中的檔案。如果專案包含檔案 CPackSourceConfig.cmake.in,則會使用該檔案來建立 CPackSourceConfig.cmake

CPack.cmake 建立的組態檔將包含目前專案中所有以 “CPACK_" 開頭的變數。這是使用命令完成的

get_cmake_property(res VARIABLES)

上述命令會取得為目前 CMake 專案定義的所有變數。然後,某些 CMake 程式碼會尋找所有以 “CPACK_" 開頭的變數,並且找到的每個變數都會以 CMake 程式碼的形式設定到兩個組態檔中。例如,如果您的 CMake 專案中有一個像這樣設定的變數

set(CPACK_PACKAGE_NAME "CoolStuff")

CPackConfig.cmakeCPackSourceConfig.cmake 將包含相同的內容

set(CPACK_PACKAGE_NAME "CoolStuff")

請務必記住,CPack 是在專案上執行 CMake 之後執行的。CPack 使用與 CMake 相同的剖析器,但其變數值與 CMake 專案不同。它只會包含以 CPACK_ 開頭的變數,並且這些變數將由 CMake 設定到組態檔中。如果變數的值使用跳脫字元,這可能會導致一些錯誤和混淆。由於它們會被 CMake 語言剖析兩次,因此它們將需要雙倍層級的跳脫。例如,如果您的 CMake 專案中有以下內容

set(CPACK_PACKAGE_VENDOR "Cool \"Company\"")

產生的 CPack 檔案將包含此內容

set(CPACK_PACKAGE_VENDOR "Cool "Company"")

那不會完全是您想要或期望的。事實上,它根本不會運作。要解決這個問題,有兩種解決方案。第一種是在原始 set 命令中新增額外的跳脫層級,如下所示

set(CPACK_PACKAGE_VENDOR "Cool \\\"Company\\\"")

這將產生正確的 set 命令,如下所示

set(CPACK_PACKAGE_VENDOR "Cool \"Company\"")

跳脫問題的第二個解決方案是使用 CPack 專案組態檔,這會在下一節中說明。

新增自訂 CPack 選項

為了避免跳脫問題,可以指定專案特定的 CPack 組態檔。此檔案將在載入 CPackConfig.cmakeCPackSourceConfig.cmake 後由 CPack 載入,並且 CPACK_GENERATOR 將設定為正在執行的 CPack 產生器。在此檔案中設定的變數只需要一個層級的 CMake 跳脫。此檔案可以設定或不設定,並且包含常規的 CMake 程式碼。在上面的範例中,您可以將 CPACK_PACKAGE_VENDOR 移動到檔案 MyCPackOptions.cmake.in,並將該檔案設定到專案的建置樹中。然後設定如下的專案組態檔路徑

configure_file ("${PROJECT_SOURCE_DIR}/MyCPackOptions.cmake.in"
                "${PROJECT_BINARY_DIR}/MyCPackOptions.cmake"
                @ONLY)
set (CPACK_PROJECT_CONFIG_FILE
     "${PROJECT_BINARY_DIR}/MyCPackOptions.cmake")

其中 MyCPackOptions.cmake.in 包含

set(CPACK_PACKAGE_VENDOR "Cool \"Company\"")

CPACK_PROJECT_CONFIG_FILE 變數應包含專案的 CPack 組態檔的完整路徑,如以上範例所示。這還有一個額外的好處,就是 CMake 程式碼可以包含基於 CPACK_GENERATOR 值的 if 語句,以便可以為專案設定封裝器特定的值。例如,CMake 專案會在此檔案中設定安裝程式的圖示

set (CPACK_NSIS_MUI_ICON
     "@CMake_SOURCE_DIR@/Utilities/Release\\CMakeLogo.ico")

請注意,路徑使用正斜線,但最後一部分除外,該部分的路徑分隔符號已逸出。 在撰寫本書時,NSIS 需要路徑的最後一部分使用 Windows 樣式的斜線。 如果您不這樣做,可能會收到以下錯誤

File: ".../Release/CMakeLogo.ico" -> no files found.
Usage: File [/nonfatal] [/a] ([/r] [/x filespec [...]]
       filespec [...] | /oname=outfile one_file_only)

CPack 增加的選項

除了建立兩個組態檔案之外,CPack.cmake 還會為您的專案新增一些進階選項。 新增的選項取決於 CMake 執行的環境和作業系統,並控制 CPack 建立的預設套件。 這些選項的形式為 CPACK_<CPack 產生器 名稱>,每個平台上可用的產生器名稱可以在下表中找到

Windows

Cygwin

Linux/UNIX

Mac OS X

NSIS

CYGWIN_BINARY

DEB

PACKAGEMAKER

ZIP

SOURCE_CYGWIN

RPM

DRAGNDROP

SOURCE_ZIP

STGZ

BUNDLE

TBZ2

OSXX11

TGZ

TZ

SOURCE_TGZ

SOURCE_TZ

開啟或關閉這些選項會影響在不使用任何選項執行 CPack 時建立的套件。 如果專案的 CMakeCache.txt 檔案中關閉了選項,您仍然可以透過指定 CPack 命令列的 -G 選項來建置該套件類型。

CPack 原始碼套件

CPack 中的原始碼套件只是將專案的整個原始碼樹狀結構複製到套件檔案中,並且不使用安裝規則,就像二進位套件的情況一樣。 應使用外部建置,以避免額外的二進位檔案污染原始碼套件。 如果您的原始碼樹狀結構中有不希望包含在原始碼套件中的檔案或目錄,您可以使用變數 CPACK_SOURCE_IGNORE_FILES 從套件中排除這些項目。 此變數包含規則運算式的清單。 任何符合該清單中規則運算式的檔案或目錄都將從原始碼中排除。 預設設定如下

"/CVS/;/\\\\\\\\.svn/;\\\\\\\\.swp$;\\\\\\\\.#;/#"

預設值中使用了多個層級的逸出,因為此變數會由 CMake 解析一次,然後由 CPack 再次解析。 重要的是要了解,原始碼樹狀結構不會使用任何安裝命令,它只會將整個原始碼樹狀結構複製到套件中,減去它被告知要忽略的檔案。 為了避免多個層級的逸出,應使用 CPACK_PROJECT_CONFIG_FILE 參照的檔案來設定此變數。 該表示式是規則運算式,而不是萬用字元陳述式,請參閱第 4 章以取得有關 CMake 規則運算式的更多資訊。

CPack 安裝程式命令

由於二進位套件需要 CPack 與正在封裝的專案的安裝規則互動,因此本節將介紹 CPack 提供的一些選項,以便與專案的安裝規則互動。 CPack 可以與 CMake 的安裝腳本或外部安裝命令搭配使用。

CPack 和 CMake 安裝命令

在大多數 CMake 專案中,使用 CMake 安裝規則足以建立所需的套件。 預設情況下,CPack 會為目前專案執行安裝規則。 但是,如果您有更複雜的專案,您可以使用變數 CPACK_INSTALL_CMAKE_PROJECTS 指定子專案和安裝目錄。 此變數應保存安裝目錄、安裝專案名稱、安裝元件和安裝子目錄的四元組。 例如,如果您的專案有一個名為 MySub 的子專案,該子專案編譯到名為 SubProject 的目錄中,並且您想要安裝其所有元件,您將擁有以下內容

SET(CPACK_INSTALL_CMAKE_PROJECTS  "SubProject;MySub;ALL;/")

CPack 和 DESTDIR

預設情況下,CPack 在安裝階段不會使用 DESTDIR 選項。 相反地,它會將 CMAKE_INSTALL_PREFIX 設定為 CPack 用於暫存安裝套件的臨時目錄的完整路徑。 可以透過將 CPACK_SET_DESTDIR 設定為 on 來變更此設定。 如果 CPACK_SET_DESTDIR 選項為 on,則 CPack 將使用專案的快取值作為 CPACK_INSTALL_PREFIX,並將 DESTDIR 設定為暫存區域。 這允許將絕對路徑安裝在暫存目錄下。 相對路徑會安裝到 DESTDIR/${project's CMAKE_INSTALL_PREFIX} 中,其中 DESTDIR 設定為暫存區域。

如先前所述,當安裝規則透過以磁碟機代號 (C:/) 開頭的 Windows 完整路徑參照檔案時,DESTDIR 方法不起作用。

在執行非 DESTDIR 安裝以進行封裝時(這是預設值),任何絕對路徑都會安裝到絕對目錄中,而不是安裝到套件中。 因此,不使用 DESTDIR 選項的專案,不得在安裝規則中使用任何絕對路徑。 相反地,使用絕對路徑的專案,必須使用 DESTDIR 選項。

還有一個變數可用於控制專案安裝到的根路徑,即 CPACK_PACKAGING_INSTALL_PREFIX。 預設情況下,許多產生器會安裝到 /usr 目錄中。 可以使用該變數將其變更為任何目錄,包括僅 /。

CPack 和其他安裝的目錄

如果專案不是基於 CMake,則可以執行其他安裝規則。 可以透過使用變數 CPACK_INSTALL_COMMANDSCPACK_INSTALLED_DIRECTORIES 來完成此操作。CPACK_INSTALL_COMMANDS 是將在封裝的安裝階段執行的命令。 CPACK_INSTALLED_DIRECTORIES 應包含目錄和子目錄的配對。 子目錄可以是「.」,表示安裝在安裝的頂層目錄中。 每個目錄中的檔案將複製到 CPack 暫存目錄的對應子目錄,並與其餘檔案一起封裝。

適用於 Windows 安裝程式 NSIS 的 CPack

為了建立 Windows 風格的精靈式安裝程式,CPack 使用 NSIS (NullSoft Scriptable Install System)。關於 NSIS 的更多資訊,請參閱 NSIS 首頁:http://nsis.sourceforge.net/ NSIS 是一個強大的工具,具有腳本語言,可用於建立專業的 Windows 安裝程式。要使用 CPack 建立 Windows 安裝程式,您的電腦上需要安裝 NSIS。

CPack 使用設定好的範本檔案來控制 NSIS。在建立 NSIS 安裝程式期間,CPack 會設定兩個檔案。這兩個檔案都可以在 CMake 模組目錄中找到。Modules/NSIS.template.in 是 NSIS 腳本的範本,而 Modules/NSIS.InstallOptions.ini.in 則是 NSIS 使用的現代使用者介面或 MUI 的範本。安裝選項檔案包含安裝精靈中使用的頁面相關資訊。本節將說明如何設定 CPack 以建立 NSIS 安裝精靈。

CPack 用於 NSIS 的 CMake 變數

本節包含 CMake NSIS 安裝精靈的螢幕截圖。針對可以從 CPack 變更或控制的安裝程式每個部分,都會提供使用的變數和值。

使用者在 Windows 中看到安裝程式的第一件事是安裝程式可執行檔本身的圖示。預設情況下,安裝程式會具有 Null Soft 安裝程式圖示,如圖 1 中 20071023 CMake 安裝程式所示。可以透過設定變數 CPACK_NSIS_MUI_ICON 來變更此圖示。同一圖中的 20071025 安裝程式顯示安裝程式正在使用 CMake 圖示。

../_images/IconforinstallerinWindowsExplorer.png

圖 1:Windows 檔案總管中安裝程式的圖示

使用者在 Windows 中看到安裝程式的最後一件事是解除安裝可執行檔的圖示,如圖 2 所示。可以使用 CPACK_NSIS_MUI_UNIICON 變數來設定此選項。安裝和解除安裝圖示的大小和格式必須相同,也就是 Windows 檔案總管可使用的有效 windows .ico 檔案。圖示設定如下:

# set the install/uninstall icon used for the installer itself
set (CPACK_NSIS_MUI_ICON
     "${CMake_SOURCE_DIR}/Utilities/Release\\CMakeLogo.ico")
set (CPACK_NSIS_MUI_UNIICON
     "${CMake_SOURCE_DIR}/Utilities/Release\\CMakeLogo.ico")
../_images/UninstallIconforNSISinstaller.png

圖 2:NSIS 安裝程式的解除安裝圖示

在 Windows 上,也可以使用控制台中的 [新增或移除程式] 工具來移除程式,如圖 3 所示。此圖示應該內嵌在其中一個已安裝的可執行檔中。可以這樣設定:

# set the add/remove programs icon using an installed executable
SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\cmake-gui.exe")
../_images/AddorRemoveProgramsEntry.png

圖 3:新增或移除程式項目

../_images/FirstScreenofInstallWizard.png

圖 4:安裝精靈的第一個畫面

執行安裝程式時,精靈的第一個畫面會如圖 4 所示。在此畫面中,您可以控制顯示在畫面上兩個位置的專案名稱。專案使用的名稱由變數 CPACK_PACKAGE_INSTALL_DIRECTORYCPACK_NSIS_PACKAGE_NAME 控制。在此範例中,它設定為「CMake 2.5」,如下所示:

set (CPACK_PACKAGE_INSTALL_DIRECTORY "CMake
     ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}")

或這樣:

set (CPACK_NSIS_PACKAGE_NAME "CMake
     ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}")
../_images/SecondScreenofInstallWizard.png

圖 5:安裝精靈的第二個畫面

可以在圖 5 中看到安裝精靈的第二頁。此畫面包含授權合約,而且可以在此頁面上設定幾件事。在「授權合約」標籤左邊的橫幅點陣圖由變數 CPACK_PACKAGE_ICON 控制,如下所示:

set (CPACK_PACKAGE_ICON
     "${CMake_SOURCE_DIR}/Utilities/Release\\CMakeInstall.bmp")

CPACK_PACKAGE_INSTALL_DIRECTORY 會在此頁面上再次使用,凡是看到「CMake 2.5」文字的地方。授權合約的文字會設定為 CPACK_RESOURCE_FILE_LICENSE 變數中指定檔案的內容。CMake 會執行下列動作:

set (CPACK_RESOURCE_FILE_LICENSE
     "${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt")
../_images/Thirdpageofinstallerwizard.png

圖 6:安裝程式精靈的第三頁

可以在圖 6 中看到安裝程式的第三頁。只有在 CPACK_NSIS_MODIFY_PATH 設定為開啟時,才會顯示此頁面。如果您勾選 [建立「名稱」桌面圖示] 按鈕,並在變數 CPACK_CREATE_DESKTOP_LINKS 中輸入可執行檔名稱,則會為這些可執行檔建立桌面圖示。例如,若要為 CMake 的 cmake-gui 程式建立桌面圖示,請執行下列動作:

set (CPACK_CREATE_DESKTOP_LINKS cmake-gui)

如果您的應用程式包含多個可執行檔,則可以建立多個桌面連結。連結會建立到 [開始] 功能表項目,因此 CPACK_PACKAGE_EXECUTABLES(將在本節稍後說明)也必須包含應用程式,才能建立桌面連結。

../_images/Fourthpageofinstallerwizard.png

圖 7:安裝程式精靈的第四頁

7 中看到的安裝程式的第四頁會使用變數 CPACK_PACKAGE_INSTALL_DIRECTORY,以指定 [程式檔案] 中的預設目的地資料夾。下列 CMake 程式碼用於設定該預設值:

set (CPACK_PACKAGE_INSTALL_DIRECTORY "CMake
     ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}")

安裝程式精靈的其餘頁面不使用任何其他 CPack 變數,因此不包含在本節中。NSIS CPack 產生器可以設定的另一個重要選項是使用的登錄機碼。有幾個 CPack 變數可以控制使用的預設機碼。機碼在 NSIS.template.in 檔案中定義,如下所示:

!define MUI_STARTMENUPAGE_REGISTRY_KEY
    "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"

其中 CPACK_PACKAGE_VENDOR 值預設為 Kitware,而 CPACK_PACKAGE_INSTALL_REGISTRY_KEY 預設為 ${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION}

因此,對於 CMake 2.5.20071025,登錄機碼看起來會像這樣:

HKEY_LOCAL_MACHINE\SOFTWARE\Kitware\CMake 2.5.20071025

在 [開始] 功能表中建立 Windows 捷徑

有兩個變數可以控制 NSIS 在 Windows [開始] 功能表中建立的捷徑。這些變數包含成對的清單,而且必須具有偶數個元素才能正確運作。第一個是 CPACK_PACKAGE_EXECUTABLES,它應該包含可執行檔的名稱,後面接著捷徑文字的名稱。例如,在 CMake 的情況下,可執行檔稱為 cmake-gui,但捷徑命名為「CMake」。CMake 會執行下列動作來建立該捷徑:

set (CPACK_PACKAGE_EXECUTABLES "cmake-gui" "CMake" )

第二個是 CPACK_NSIS_MENU_LINKS。此變數包含安裝樹狀結構中或外部網頁的任意連結。成對的第一個永遠是現有的來源檔案或位置,第二個則是在 [開始] 功能表中顯示的名稱。若要新增 cmake-gui 說明檔的連結和 CMake 網頁的連結,請新增下列內容:

set (CPACK_NSIS_MENU_LINKS
     "doc/cmake-${VERSION_MAJOR}.${VERSION_MINOR}/cmake-gui.html"
     "cmake-gui Help" "http://www.cmake.org" "CMake Web Site")

進階 NSIS CPack 選項

除了已經討論的變數之外,CPack 還提供一些直接設定到 NSIS 腳本檔案中的額外變數。這些變數可用於將 NSIS 腳本片段新增至用於建立安裝程式的最終 NSIS 腳本。它們如下所示:

CPACK_NSIS_EXTRA_INSTALL_COMMANDS

在安裝期間使用的額外命令。

CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS

在解除安裝期間使用的額外命令。

CPACK_NSIS_CREATE_ICONS_EXTRA

腳本圖示區段中的額外 NSIS 命令。

CPACK_NSIS_DELETE_ICONS_EXTRA

腳本刪除圖示區段中的額外 NSIS 命令。

使用這些變數時,應該參考 NSIS 文件,而作者應該查看 NSIS.template.in 檔案,以了解變數的確切位置。

使用 NSIS 設定檔案副檔名關聯

可以使用額外安裝命令來執行的一項有用範例是,建立檔案副檔名與已安裝應用程式之間的關聯。例如,如果您有一個可以開啟副檔名為 .cool 的檔案的應用程式 CoolStuff,您應該設定下列額外安裝和解除安裝命令:

set (CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
     WriteRegStr HKCR '.cool' '' 'CoolFile'
     WriteRegStr HKCR 'CoolFile' '' 'Cool Stuff File'
     WriteRegStr HKCR 'CoolFile\\shell' '' 'open'
     WriteRegStr HKCR 'CoolFile\\DefaultIcon' \\
                      '' '$INSTDIR\\bin\\coolstuff.exe,0'
     WriteRegStr HKCR 'CoolFile\\shell\\open\\command' \\
                      '' '$INSTDIR\\bin\\coolstuff.exe \"%1\"'
     WriteRegStr HKCR \"CoolFile\\shell\\edit' \\
                      '' 'Edit Cool File'
     WriteRegStr HKCR 'CoolFile\\shell\\edit\\command' \\
                      '' '$INSTDIR\\bin\\coolstuff.exe \"%1\"'
     System::Call \\
       'Shell32::SHChangeNotify(i 0x8000000, i 0, i 0, i 0)'
     ")

set (CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "
     DeleteRegKey HKCR '.cool'
     DeleteRegKey HKCR 'CoolFile'
     ")

這會建立一個 Windows 檔案關聯,將所有以 .cool 結尾的檔案與之關聯,因此當使用者雙擊 .cool 檔案時,會執行 coolstuff.exe,並將該檔案的完整路徑作為引數傳遞。這也會設定一個關聯,讓使用者可以從 Windows 的右鍵選單編輯檔案,同樣使用 coolstuff.exe 程式。該檔案在 Windows 檔案總管中的圖示會設定為 coolstuff.exe 執行檔中的圖示。當解除安裝時,這些登錄機碼會被移除。由於雙引號和 Windows 路徑分隔符號必須跳脫,最好將此程式碼放入專案的 CPACK_PROJECT_CONFIG_FILE 中。

configure_file(
  ${CoolStuff_SOURCE_DIR}/CoolStuffCPackOptions.cmake.in
  ${CoolStuff_BINARY_DIR}/CoolStuffCPackOptions.cmake @ONLY)

set (CPACK_PROJECT_CONFIG_FILE
  ${CoolStuff_BINARY_DIR}/CoolStuffCPackOptions.cmake)
include (CPack)

安裝 Microsoft Run Time Libraries

雖然嚴格來說這不是 NSIS CPack 的命令,但如果你使用 Microsoft 編譯器在 Windows 上建立應用程式,你很可能希望將 Microsoft 的執行階段程式庫與你的專案一起發佈。在 CMake 中,你只需要執行以下操作:

include (InstallRequiredSystemLibraries)

這會將編譯器的執行階段程式庫新增為安裝檔案,這些檔案會放入你的應用程式的 bin 目錄中。如果你不希望這些程式庫放入 bin 目錄中,你可以這樣做:

set (CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
include (InstallRequiredSystemLibraries)
install (PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
        DESTINATION mydir)

重要的是要注意,執行階段程式庫必須與你的套件的執行檔放在一起,Windows 才能找到它們。對於 Visual Studio 2005 和 2008,當發佈執行階段程式庫時,也必須安裝 side by side 的資訊清單檔案。如果你想要打包除錯版本的軟體,你需要在 include 之前將 CMAKE_INSTALL_DEBUG_LIBRARIES 設定為 ON。但是請注意,授權條款可能會禁止你重新發佈除錯程式庫。在決定將 CMAKE_INSTALL_DEBUG_LIBRARIES 設定為 ON 之前,請仔細檢查你所使用的 Visual Studio 版本的授權條款。

CPack 元件安裝支援

預設情況下,CPack 的安裝程式會將專案安裝的所有檔案視為單一的整體:要么安裝整個檔案集,要么不安裝任何檔案。但是,對於許多專案來說,將安裝細分為不同的、使用者可選取的元件是有意義的。有些使用者可能只想安裝專案的命令列工具,而其他使用者可能想要 GUI 或標頭檔。

本節介紹如何設定 CPack 以產生基於元件的安裝程式,讓使用者可以選擇他們想要安裝的專案元件集。作為一個範例,將為一個具有三個元件的程式庫建立一個簡單的安裝程式:一個程式庫二進制檔、一個範例應用程式和一個 C++ 標頭檔。完成後,Windows 和 Mac OS X 的最終安裝程式看起來會像圖 8 中所示。

../_images/MacandWindowsComponentInstallers.png

圖 8:Mac 和 Windows 元件安裝程式

我們將使用的簡單範例如下所示;它有一個程式庫和一個執行檔。這裡使用了已經涵蓋過的 CPack 命令。

cmake_minimum_required(VERSION 3.20 FATAL_ERROR)
project(MyLib)

add_library(mylib mylib.cpp)

add_executable(mylibapp mylibapp.cpp)
target_link_libraries(mylibapp mylib)

install(TARGETS mylib ARCHIVE DESTINATION lib)
install(TARGETS mylibapp RUNTIME DESTINATION bin)
install(FILES mylib.h DESTINATION include)
# add CPack to project
set(CPACK_PACKAGE_NAME "MyLib")
set(CPACK_PACKAGE_VENDOR "CMake.org")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY
    "MyLib - CPack Component Installation Example")
set(CPACK_PACKAGE_VERSION "1.0.0")
set(CPACK_PACKAGE_VERSION_MAJOR "1")
set(CPACK_PACKAGE_VERSION_MINOR "0")
set(CPACK_PACKAGE_VERSION_PATCH "0")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "CPack Component Example")

# This must always be after all CPACK\_\* variables are defined
include(CPack)

指定元件

建立基於元件的安裝的第一步是識別可安裝元件的集合。在這個範例中,將建立三個元件:程式庫二進制檔、應用程式和標頭檔。這個決定是任意且專案特定的,但請務必識別與使用者重要的功能單位相對應的元件,而不是基於程式的內部結構來建立元件。

對於每個元件,我們需要識別每個已安裝的檔案屬於哪個元件。對於 CMakeLists.txt 中的每個 install 命令,加入適當的 COMPONENT 引數,說明已安裝的檔案將與哪個元件相關聯

install(TARGETS mylib
  ARCHIVE
  DESTINATION lib
  COMPONENT libraries)
install(TARGETS mylibapp
  RUNTIME
  DESTINATION bin
  COMPONENT applications)
install(FILES mylib.h
  DESTINATION include
  COMPONENT headers)

請注意,install 命令的 COMPONENT 引數並不是新的;它一直是 CMake 的 install 的一部分。如果使用任何較舊的安裝命令(install_targetsinstall_files 等),你需要將它們轉換為 install 命令,才能使用元件。

下一步是透過為套件的每個元件呼叫 cpack_add_component 函式,來通知 CPack 你的專案中所有元件的名稱

cpack_add_component(applications)
cpack_add_component(libraries)
cpack_add_component(headers)

此時,你可以使用 CPack 建置一個基於元件的安裝程式,讓使用者可以獨立安裝 MyLib 的應用程式、程式庫和標頭。Windows 和 Mac OS X 安裝程式看起來會像圖 9 中所示。

../_images/WindowsandMacOSXComponentInstallerFirstPage.png

圖 9:Windows 和 Mac OS X 元件安裝程式第一頁

命名元件

此時,你可能已經注意到安裝程式中實際元件的名稱並不是很具描述性:它們只會顯示元件名稱中指定的「applications」、「libraries」或「headers」。可以使用 cpack_add_component function 中的 DISPLAY_NAME 選項來改進這些名稱

cpack_add_component(applications DISPLAY_NAME
"MyLib Application")
cpack_add_component(libraries DISPLAY_NAME "Libraries")
cpack_add_component(headers DISPLAY_NAME "C++ Headers")

任何以 CPACK_COMPONENT_${COMPNAME} 為字首的巨集,其中 ${COMPNAME} 是元件的大寫名稱,用於設定安裝程式中該元件的特定屬性。在這裡,我們設定每個元件的 DISPLAY_NAME 屬性,以便我們獲得人類可讀的名稱。這些名稱將列在選取方塊中,而不是內部元件名稱「applications」、「libraries」、「headers」

../_images/WindowsandMacOSXInstallerswithnamedcomponents.png

圖 10:具有命名元件的 Windows 和 Mac OS X 安裝程式

加入元件描述

元件還有其他幾個屬性,包括能夠將元件隱藏、設為必要或預設為停用,這些屬性可以提供額外的描述性資訊。特別值得注意的是 DESCRIPTION 屬性,它為元件提供了一些描述性文字。此描述性文字會顯示在安裝程式中單獨的「描述」方塊中,並且會在使用者將滑鼠游標停留在相應元件的名稱上(Windows)時,或在使用者按一下元件(Mac OS X)時更新。我們將在下方為每個元件加入描述

 cpack_add_component(applications DISPLAY_NAME "MyLib Application"
  DESCRIPTION
  "An extremely useful application that makes use of MyLib"
  )
cpack_add_component(libraries DISPLAY_NAME "Libraries"
  DESCRIPTION
  "Static libraries used to build programs with MyLib"
  )
cpack_add_component(headers DISPLAY_NAME "C++ Headers"
  DESCRIPTION "C/C++ header files for use with MyLib"
  )

一般來說,描述應提供足夠的資訊讓使用者決定是否要安裝元件,但本身不應超過幾行(安裝程式中的「描述」方塊往往很小)。圖 11 顯示 Windows 和 Mac OS X 安裝程式的描述顯示。

../_images/ComponentInstallerswithdescriptions.png

圖 11:具有描述的元件安裝程式

元件相互依賴關係

對於大多數專案來說,各種元件並不是完全獨立的。例如,應用程式元件可能依賴於另一個元件中的共享程式庫才能正確執行,因此如果安裝應用程式元件而沒有相應的共享程式庫,將導致安裝無法使用。CPack 允許你表達元件之間的依賴關係,以便只有在安裝了它所依賴的所有其他元件時,才會安裝該元件。

為了說明元件依賴關係,我們將對基於元件的安裝程式施加一個簡單的限制。由於我們的安裝程式中沒有提供原始程式碼,因此只有在使用者也安裝了程式庫二進制檔來連結他們的程式時,我們發佈的 C++ 標頭檔才能真正被使用。因此,「headers」元件依賴於「libraries」元件的可用性。我們可以透過為 HEADERS 元件設定 DEPENDS 屬性來表達這個概念,如下所示

cpack_add_component(headers DISPLAY_NAME "C++ Headers"
  DESCRIPTION
  "C/C++ header files for use with MyLib"
  DEPENDS libraries
  )

元件的 DEPENDS 屬性實際上是一個列表,因此一個元件可以依賴於其他幾個元件。透過這種方式表達所有元件的依賴關係,你可以確保使用者在安裝時無法選取不完整的元件集。

元件分組

當你的專案中的元件數量變得龐大時,你可能需要為元件列表提供額外的組織。為了協助進行這種組織,CPack 包含元件群組的概念。元件群組只是提供一組相關元件名稱的一種方式。在使用者介面中,元件群組有自己的名稱,並且在該群組下方是該群組中所有元件的名稱。使用者可以選擇按一下以(取消)選取安裝群組中的所有元件,或展開群組以選取個別元件。

我們將擴展我們的範例,將其三個元件「applications」、「libraries」和「headers」分類為「Runtime」和「Development」群組。我們可以透過使用 cpack_add_component 函式的 GROUP 選項將元件放入群組,如下所示

 cpack_add_component(applications
  DISPLAY_NAME "MyLib Application"
  DESCRIPTION
   "An extremely useful application that makes use of MyLib"
  GROUP Runtime)
cpack_add_component(libraries
  DISPLAY_NAME "Libraries"
  DESCRIPTION
  "Static libraries used to build programs with MyLib"
  GROUP Development)
cpack_add_component(headers
  DISPLAY_NAME "C++ Headers"
  DESCRIPTION "C/C++ header files for use with MyLib"
  GROUP Development
  DEPENDS libraries
  )

如同元件一樣,元件群組也有各種可自訂的屬性,包括 DISPLAY_NAMEDESCRIPTION。例如,以下程式碼為「開發」群組新增了詳細說明

cpack_add_component_group(Development
 EXPANDED
 DESCRIPTION
"All of the tools you'll ever need to develop software")

當您將元件群組自訂成您喜歡的樣子後,重新建置二進位安裝程式,即可看到新的組織方式:MyLib 應用程式會顯示在新的「執行階段」群組下,而 MyLib 程式庫和 C++ 標頭檔會顯示在新的「開發」群組下。可以使用安裝程式的 GUI 輕鬆開啟/關閉群組中的所有元件。這可以在圖 12 中看到。

../_images/ComponentGrouping.png

圖 12:元件群組

安裝類型 (僅限 NSIS)

當專案包含大量元件時,Windows 安裝程式通常會根據特定使用者需求提供預先選取的元件組合。例如,想要針對程式庫開發軟體的使用者會需要一組元件,而終端使用者可能會使用完全不同的元件組合。CPack 透過安裝類型的概念支援這種預先選取的元件組合。安裝類型只是一組元件。當使用者選擇安裝類型時,系統會選取該組元件。然後,允許使用者根據需要進一步自訂其安裝。目前只有 NSIS 產生器支援此功能。

對於我們的簡單範例,我們將建立兩種安裝類型:包含所有元件的「完整」安裝類型,以及僅包含程式庫和標頭檔的「開發人員」安裝類型。為此,我們使用 cpack_add_install_type 函式來新增類型。

cpack_add_install_type(Full DISPLAY_NAME "Everything")
cpack_add_install_type(Developer)

接下來,我們設定每個元件的 INSTALL_TYPES 屬性,以聲明哪些安裝類型會包含該元件。這是使用 cpack_add_component 函式的 INSTALL_TYPES 選項來完成的。

 cpack_add_component(libraries DISPLAY_NAME "Libraries"
  DESCRIPTION
   "Static libraries used to build programs with MyLib"
  GROUP Development
  INSTALL_TYPES Developer Full)
cpack_add_component(applications
  DISPLAY_NAME "MyLib Application"
  DESCRIPTION
   "An extremely useful application that makes use of MyLib"
  GROUP Runtime
  INSTALL_TYPES Full)
cpack_add_component(headers
  DISPLAY_NAME "C++ Headers"
  DESCRIPTION "C/C++ header files for use with MyLib"
  GROUP Development
  DEPENDS libraries
  INSTALL_TYPES Developer Full)

元件可以列在任意數量的安裝類型下。如果您重建 Windows 安裝程式,元件頁面會包含一個組合方塊,讓您選取安裝類型,因此也會選取其對應的元件集,如圖 13 所示。

../_images/NSISInstallationTypes.png

圖 13:NSIS 安裝類型

控制 CPack 元件的變數

函式 cpack_add_install_typecpack_add_component_groupcpack_add_component 只是設定 CPACK_ 變數。這些變數在以下清單中說明

CPACK_COMPONENTS_ALL

這是一個包含 CPack 應安裝的所有元件名稱的清單。此巨集的存在表示 CPack 應建置以元件為基礎的安裝程式。不會安裝未在此列出的任何元件相關的檔案,或未與任何元件關聯的任何安裝命令。

CPACK_COMPONENT_${COMPNAME}_DISPLAY_NAME

元件 ${COMPNAME} 的顯示名稱,用於圖形安裝程式中顯示元件名稱。此值可以是任何字串。

CPACK_COMPONENT_${COMPNAME}_DESCRIPTION

元件 ${COMPNAME} 的延伸描述,用於圖形安裝程式中,以提供使用者有關元件的其他資訊。描述可以使用「\n」作為換行符號跨越多行。

CPACK_COMPONENT_${COMPNAME}_HIDDEN

一個旗標,指示此元件將在圖形安裝程式中隱藏,因此無法選取或安裝。僅適用於 NSIS。

CPACK_COMPONENT_${COMPNAME}_REQUIRED

一個旗標,指示此元件是必要的,因此將始終安裝。它將在圖形安裝程式中可見,但無法取消選取。

CPACK_COMPONENT_${COMPNAME}_DISABLED

一個旗標,指示此元件應該預設為停用(取消選取)。使用者可以自由選取此元件進行安裝。

CPACK_COMPONENT_${COMPNAME}_DEPENDS

列出此元件所依賴的元件。如果選取此元件,則還必須選取列出的每個元件。

CPACK_COMPONENT_${COMPNAME}_GROUP

命名此元件所屬的元件群組。如果未提供,則該元件將是獨立元件,不屬於任何元件群組。

CPACK_COMPONENT_${COMPNAME}_INSTALL_TYPES

列出此元件所屬的安裝類型。當選取其中一種安裝類型時,將會自動選取此元件。僅適用於 NSIS。

CPACK_COMPONENT_GROUP_${GROUPNAME}_DISPLAY_NAME

元件群組 ${GROUPNAME} 的顯示名稱,用於圖形安裝程式中顯示元件群組名稱。此值可以是任何字串。

CPACK_COMPONENT_GROUP_${GROUPNAME}_DESCRIPTION

元件群組 ${GROUPNAME} 的延伸描述,用於圖形安裝程式中,以提供使用者有關此群組中包含的元件的其他資訊。描述可以使用「\n」作為換行符號跨越多行。

CPACK_COMPONENT_GROUP_${GROUPNAME}_BOLD_TITLE

一個旗標,指示群組標題是否應為粗體。僅適用於 NSIS。

CPACK_COMPONENT_GROUP_${GROUPNAME}_EXPANDED

一個旗標,指示群組是否應以「展開」方式開始,顯示其元件。否則,只會顯示群組名稱本身,直到使用者按一下群組。僅適用於 NSIS。

CPACK_INSTALL_TYPE_${INSTNAME}_DISPLAY_NAME

安裝類型的顯示名稱。此值可以是任何字串。

用於 Cygwin 安裝的 CPack

Cygwin (http://www.cygwin.com/) 是一個類似於 Linux 的 Windows 環境,由執行階段 DLL 和工具集合組成。若要將工具新增至官方 Cygwin,請使用 Cygwin 安裝程式。安裝工具對於要包含的來源和二進位樹狀結構具有非常特定的配置。CPack 可以建立來源和二進位 tar 檔案,並正確地對其進行 bzip 壓縮,以便將其上傳到 Cygwin 鏡像站點。您當然必須在執行此操作之前,讓您的套件被 Cygwin 社群接受。由於套件的配置比其他封裝工具更具限制性,因此您可能必須變更專案的一些安裝選項。

Cygwin 安裝程式要求將所有檔案安裝到 /usr/bin/usr/share/package-version/usr/share/man/usr/share/doc/package-version。cygwin CPack 產生器會自動將 /usr 新增至專案的安裝目錄。專案必須將內容安裝到 sharebin 中,而 CPack 將自動新增 /usr 前置詞。

Cygwin 還要求您提供一個 shell 指令碼,可用於從來源建立套件。套件所需的任何 Cygwin 特定修補程式也必須在 diff 檔案中提供。CMake 的 configure_file 命令可用於為專案建立這兩個檔案。由於 CMake 是一個 Cygwin 套件,因此用於為 Cygwin CPack 產生器設定 CMake 的 CMake 程式碼如下

set (CPACK_PACKAGE_NAME CMake)

# setup the name of the package for cygwin
set (CPACK_PACKAGE_FILE_NAME
    "${CPACK_PACKAGE_NAME}-${CMake_VERSION}")

# the source has the same name as the binary
set (CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_FILE_NAME})

# Create a cygwin version number in case there are changes
# for cygwin that are not reflected upstream in CMake
set (CPACK_CYGWIN_PATCH_NUMBER 1)

# if we are on cygwin and have cpack, then force the
# doc, data and man dirs to conform to cygwin style directories
set (CMAKE_DOC_DIR "/share/doc/${CPACK_PACKAGE_FILE_NAME}")
set (CMAKE_DATA_DIR "/share/${CPACK_PACKAGE_FILE_NAME}")
set (CMAKE_MAN_DIR "/share/man")

# These files are required by the cmCPackCygwinSourceGenerator and
# the files put into the release tar files.
set (CPACK_CYGWIN_BUILD_SCRIPT
    "${CMake_BINARY_DIR}/@CPACK_PACKAGE_FILE_NAME@-
       @CPACK_CYGWIN_PATCH_NUMBER@.sh")
set (CPACK_CYGWIN_PATCH_FILE
     "${CMake_BINARY_DIR}/@CPACK_PACKAGE_FILE_NAME@-
        @CPACK_CYGWIN_PATCH_NUMBER@.patch")

# include the sub directory for cygwin releases
include (Utilities/Release/Cygwin/CMakeLists.txt)

# when packaging source make sure to exclude the .build directory
set (CPACK_SOURCE_IGNORE_FILES
 "/CVS/" "/\\\\.build/" "/\\\\.svn/" "\\\\.swp$" "\\\\.#" "/#" "~$")

Utilities/Release/Cygwin/CMakeLists.txt:

# create the setup.hint file for cygwin
configure_file (
 "${CMake_SOURCE_DIR}/Utilities/Release/Cygwin/cygwin-setup.hint.in"
 "${CMake_BINARY_DIR}/setup.hint")

configure_file (
 "${CMake_SOURCE_DIR}/Utilities/Release/Cygwin/README.cygwin.in"
 "${CMake_BINARY_DIR}/Docs/@CPACK_PACKAGE_FILE_NAME@-
    @CPACK_CYGWIN_PATCH_NUMBER@.README")

install_files (/share/doc/Cygwin FILES
   ${CMake_BINARY_DIR}/Docs/@CPACK_PACKAGE_FILE_NAME@-
       @CPACK_CYGWIN_PATCH_NUMBER@.README)

# create the shell script that can build the project
configure_file (
"${CMake_SOURCE_DIR}/Utilities/Release/Cygwin/cygwin-package.sh.in"
  ${CPACK_CYGWIN_BUILD_SCRIPT})

# Create the patch required for cygwin for the project
configure_file (
"${CMake_SOURCE_DIR}/Utilities/Release/Cygwin/cygwin-patch.diff.in"
  ${CPACK_CYGWIN_PATCH_FILE})

檔案 Utilities/Release/Cygwin/cygwin-package.sh.in 可以在 CMake 原始程式碼樹狀結構中找到。這是一個 shell 指令碼,可用於從來源重新建立 Cygwin 套件。對於其他專案,在 Templates/cygwin-package.sh.in 中可以找到範本安裝指令碼。此指令碼應該能夠設定和封裝任何基於 Cygwin 的 CPack 專案,並且是所有官方 Cygwin 套件的必要條件。

Cygwin 二進位的另一個重要檔案是 share/doc/Cygwin/package-version.README。此檔案應包含 Cygwin 要求的有關專案的資訊。就 CMake 而言,此檔案會經過設定,因此可以包含正確的版本資訊。例如,CMake 的檔案部分內容如下所示

Build instructions:
  unpack CMake-2.5.20071029-1-src.tar.bz2
    if you use setup to install this src package, it will be
         unpacked under /usr/src automatically
  cd /usr/src
  ./CMake-2.5.20071029-1.sh all
This will create:
  /usr/src/CMake-2.5.20071029.tar.bz2
  /usr/src/CMake-2.5.20071029-1-src.tar.bz2

用於 Mac OS X PackageMaker 的 CPack

在 Apple Mac OS X 作業系統上,CPack 提供了使用系統 PackageMaker 工具的功能。本節將說明使用者在 OS X 上安裝 CMake 套件時將看到的 CMake 應用程式安裝畫面。將為安裝程式的每個畫面提供設定以變更安裝程式中文字的 CPack 變數。

../_images/MacPackageinsidedmg.png

圖 14:.dmg 內部的 Mac 套件

在圖 14 中,可以看到由適用於 Mac OS X 的 CPack 套件製作工具建立的 .dmg 磁碟映像檔中找到的 .pkg 檔案。此檔案的名稱由 CPACK_PACKAGE_FILE_NAME 變數控制。如果未設定此變數,CPack 將使用基於套件名稱和版本設定的預設名稱。

../_images/IntroductionScreenMacPackageMaker.png

圖 15:Mac PackageMaker 的簡介畫面

當執行 .pkg 檔案時,套件精靈會以圖 15 中看到的畫面開始。此視窗中的文字由 CPACK_RESOURCE_FILE_WELCOME 變數指向的檔案控制。

../_images/ReadmesectionofMacpackagewizard.png

圖 16:Mac 套件精靈的讀我部分

上圖顯示了封裝精靈的讀我部分。此視窗的文字可透過使用 CPACK_RESOURCE_FILE_README 變數進行自訂。它應該包含一個指向檔案的路徑,該檔案包含應在此螢幕上顯示的文字。

../_images/LicensescreenMacpackager.png

圖 17:Mac 封裝程式的授權畫面

此圖包含封裝的授權文字。使用者必須接受授權才能繼續安裝程序。授權文字來自 CPACK_RESOURCE_FILE_LICENSE 變數指向的檔案。

安裝過程中的其他畫面無法從 CPack 自訂。若要變更此安裝程式的更進階功能,您可以修改兩個 CPack 範本:Modules/CPack.Info.plist.inModules/CPack.Description.plist.in。這些檔案可透過使用 CMAKE_MODULE_PATH 變數指向您專案中包含任一或兩個修改副本的目錄來取代。

用於 Mac OS X 拖放功能的 CPack

CPack 也支援為 Mac 建立拖放安裝程式。在此情況下,會建立 .dmg 磁碟映像檔。該映像檔包含指向 /Applications 目錄的符號連結,以及專案安裝樹狀結構的複本。在此情況下,最好使用 Mac 應用程式套件或包含您可重定位安裝的單一資料夾,作為專案的唯一安裝目標。變數 CPACK_PACKAGE_EXECUTABLES 用於指向專案的應用程式套件。

../_images/DragandDropLicensedialog.png

圖 18:拖放授權對話方塊

../_images/ResultingDragandDropfolders.png

圖 19:產生的拖放資料夾

用於 Mac OS X X11 應用程式的 CPack

CPack 還包含一個 OS X X11 封裝製作器產生器。這可用於封裝基於 X11 的應用程式,並透過使用腳本將其包裝起來,讓它們更像原生 OS X 應用程式,該腳本允許使用者像執行任何原生 OS X 應用程式一樣執行它們。與 OS X PackageMaker 產生器非常相似,OS X X11 產生器會建立一個磁碟映像檔 .dmg 檔案。在此範例中,名為 KWPolygonalObjectViewerExample 的 X11 應用程式會與 OS X X11 CPack 產生器封裝在一起。

../_images/MacOSXX11packagediskimage.png

圖 20:Mac OS X X11 封裝磁碟映像檔

此圖顯示了建立的磁碟映像檔。在此情況下,CPACK_PACKAGE_NAME 已設定為 KWPolygonalObjectViewerExample,且版本資訊保留 CPack 預設值 0.1.1。變數 CPACK_PACKAGE_EXECUTABLES 已設定為配對 KWPolygonalObjectViewerExample 和 KWPolygonalObjectViewerExample,安裝的 X11 應用程式稱為 KWPolygonalObjectViewerExample。

../_images/OpeningOSXX11diskimage.png

圖 21:開啟 OS X X11 磁碟映像檔

上圖顯示了使用者在按一下 CPack 建立的 .dmg 檔案後會看到的內容。Mac OS X 將此磁碟映像檔掛載為磁碟

../_images/Mounteddmgdiskimage.png

圖 22:已掛載的 .dmg 磁碟映像檔

此圖顯示已掛載的磁碟映像檔。它將包含系統 /Applications 目錄的符號連結,並且它將包含 CPACK_PACKAGE_EXECUTABLES 中找到的每個可執行檔的應用程式套件。然後,使用者可以將應用程式拖放到應用程式資料夾中,如下圖所示。

../_images/DraganddropapplicationtoApplications.png

圖 23:將應用程式拖放到「應用程式」

CPack 實際上提供了一個基於 C++ 的可執行檔,該檔案可以透過 Apple 指令碼語言執行 X11 應用程式。安裝的應用程式套件會在使用者按兩下 KWPolygonalObjectViewerExample 時執行該轉送應用程式。此指令碼將確保啟動 X11 伺服器。執行的指令碼可以在 CMake/Modules/CPack.RuntimeScript.in 中找到。指令碼啟動器 C++ 程式的原始碼可以在 Source/CPack/OSXScriptLauncher.cxx 中找到。

用於 Debian 封裝的 CPack

Debian 封裝 .deb 僅僅是一個「ar」封存檔。CPack 包含 Debian 封裝所需的 BSD 樣式 ar 的程式碼。Debian 封裝程式使用標準的 CPack 變數集來初始化一組 Debian 特定的變數。這些可以在 CPACK_PROJECT_CONFIG_FILE 中覆寫;產生器的名稱為「DEB」。DEB 產生器使用的變數如下

CPACK_DEBIAN_PACKAGE_NAME

預設為 CPACK_PACKAGE_NAME 的小寫形式。

CPACK_DEBIAN_PACKAGE_ARCHITECTURE

預設為 i386

CPACK_DEBIAN_PACKAGE_DEPENDS

必須將其設定為此封裝所依賴的其他封裝,如果為空,則會發出警告。

CPACK_DEBIAN_PACKAGE_MAINTAINER

預設為 CPACK_PACKAGE_CONTACT 的值

CPACK_DEBIAN_PACKAGE_DESCRIPTION

預設為 CPACK_PACKAGE_DESCRIPTION_SUMMARY 的值

CPACK_DEBIAN_PACKAGE_SECTION

預設為 devl

CPACK_DEBIAN_PACKAGE_PRIORITY

預設為 optional

用於 RPM 的 CPack

CPack 支援建立 Linux RPM 檔案。在 CPACK_GENERATOR 中設定的產生器名稱為「RPM」。RPM 封裝功能需要 rpmbuild 安裝在機器上並位於 PATH 中。RPM 封裝程式使用標準的 CPack 變數集來初始化 RPM 特定的變數。RPM 特定變數如下

CPACK_RPM_PACKAGE_SUMMARY

預設為 CPACK_PACKAGE_DESCRIPTION_SUMMARY 的值

CPACK_RPM_PACKAGE_NAME

預設為 CPACK_PACKAGE_NAME 的小寫形式

CPACK_RPM_PACKAGE_VERSION

預設為 CPACK_PACKAGE_VERSION 的值。

CPACK_RPM_PACKAGE_ARCHITECTURE

預設為 i386

CPACK_RPM_PACKAGE_RELEASE

預設為 1。這是 RPM 檔案的版本,而不是封裝軟體的版本。

CPACK_RPM_PACKAGE_GROUP

預設為 none

CPACK_RPM_PACKAGE_VENDOR

預設為 CPACK_PACKAGE_VENDOR 的值

CPack 檔案

CPack 使用許多檔案,這些檔案可用於了解有關 CPack 如何運作以及您可以設定哪些選項的更多資訊。這些檔案也可用作 CPack 其他產生器的起點。這些檔案大多可以在 CMake 的 Modules 和 Templates 目錄中找到,並且通常以字首 CPack 開頭。從 2.8.8 版開始,您也可以參考 cpack --help-variable-listcpack --help-variable 以取得完整的文件化 CPACK_* 變數集。