cmake應用:安裝和打包

來源:公衆號【很酷的程序員/RealCoolEngineer】

爲了方便使用項目編譯的目標文件,快速部署到目標目錄,可以使用CMake的安裝功能;如果需要對外發布,提供頭文件、庫文件、或者demo的壓縮包則可以使用CMake的打包功能。

在本系列前序的文章中已經介紹了CMake很多內容,在CMake應用:CMakeLists.txt完全指南一文中簡略介紹了安裝和打包,本文會更加深入地介紹CMake的安裝和打包功能。本系列更多精彩文章敬請關注公衆號【很酷的程序員】的話題:CMake

本文主要介紹以下幾個方面的內容:

  1. 安裝庫文件、可執行文件和所需要對外提供的頭文件
  2. 將需要安裝的文件打包成壓縮包
  3. 編譯構建腳本編寫

本文會先介紹相關命令和知識點,如果想先實踐,可直接跳到最後一部分。

一 安裝

1 install命令

安裝使用install命令,用於指定一個項目的安裝規則。其命令格式如下:

install(TARGETS <target>... [...])
install({FILES | PROGRAMS} <file>... [...])
install(DIRECTORY <dir>... [...])
install(SCRIPT <file> [...])
install(CODE <code> [...])
install(EXPORT <export-name> [...])

以上命令概述顯示install命令可以安裝的目標類型:構建目標、文件、程序、目錄等,對應的關鍵字後面跟上對應要安裝的目標。

安裝不同的目標的時候,有一些通用的關鍵字,下面着重介紹幾個最常使用的。

DESTINATION

很好理解,就是安裝對象的目標安裝路徑,可以是絕對路徑,也可以是相對路徑,如果是相對路徑,則認爲是相對於CMAKE_INSTALL_PREFIX的,所以可以配置CMAKE_INSTALL_PREFIX指定安裝目錄。

因爲cpack並不支持絕對路徑,所以建議還是不要使用絕對路徑,當然,除非這是開發者自己確切的目的。

CONFIGURATIONS

爲不同的配置設置不同的安裝規則。假如對DebugRelease兩個配置不同的安裝路徑,代碼示例如下:

install(TARGETS target
        CONFIGURATIONS Debug
        RUNTIME DESTINATION Debug/bin)
install(TARGETS target
        CONFIGURATIONS Release
        RUNTIME DESTINATION Release/bin)

PERMISSIONS

設置安裝目標的權限,接受的參數是一個權限關鍵字列表,比如:

install(TARGETS target
        RUNTIME PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE)

2 安裝構建目標

安裝構建目標的命令格式爲:

install(TARGETS static_lib shared_lib exe
            RUNTIME DESTINATION bin
            LIBRARY DESTINATION lib
            ARCHIVE DESTINATION lib)

命令第一個參數TARGETS指定需要安裝的構建目標的列表,可以是靜態庫文件、動態庫文件、可執行文件;安裝時常常按照文件類型安裝到不同的子目錄,比如庫文件放在lib目錄,可執行文件放在bin目錄。

針對不同文件類型,比如(RUNTIME, ARCHIVE, LIBRARYPUBLIC_HEADER),可以分開進行配置,比如分別指定安裝路徑(DESTINATION)、設置文件權限(PERMISSIONS);如果不是在某個類別下的單獨配置,那麼就是針對所有類型。

值得一提的是,ARCHIVE一般是指靜態庫,LIBRARY則是指共享庫,在不同平臺上,略有差異,實際應用感覺不符合預期時查看一下官方文檔即可,問題不大。

3 安裝目錄

安裝一個目錄,一般用於將頭文件安裝到目標路徑。
在實際使用中,一般把需要安裝的頭文件放到一個特定目錄下,然後直接安裝整個目錄即可,比如:

install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/"
      DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")

更加完備的命令格式爲:

install(DIRECTORY dirs...
        TYPE <type> | DESTINATION <dir>
        [FILES_MATCHING]
        [[PATTERN <pattern> | REGEX <regex>]
         [EXCLUDE] [PERMISSIONS permissions...]]

TYPE/DESTINATION

安裝目錄必須執行安裝的目錄類型TYPE或者安裝的目標路徑DESTINATION,但是又不可以同時指定;可以使用TYPE指定安裝的目錄中的文件類型,然後CMake會自動按照類型分配安裝目錄,不同類型對應的安裝路徑如下圖:

當然,開發者也可以選擇只使用DESTINATION顯式指定安裝的目錄。

FILES_MATCHING

安裝目錄的時候默認會安裝所有的文件,如果使用FILES_MATCHING關鍵字(在第一個PATTERN或者REGEX之前),則表示必須要滿足對應的模式或者正則的文件才能被安裝。

比如,如果目錄下源文件和頭文件混在一起,但是隻想安裝其中的頭文件,則可以這樣寫:

install(DIRECTORY src/ DESTINATION include/
        FILES_MATCHING PATTERN "*.h")

PATTERN/REGEX

PATTERN表示文件名完全匹配纔會被安裝,而REGEX則是通過正則表達式匹配目標安裝文件(針對目標文件的全路徑);在這兩個表達式後面還可以加上EXCLUDE表示反選,或者使用PERMISSIONS指定匹配的目標文件的權限。

3 安裝文件

和安裝目錄類似,只不過是安裝的是文件列表,核心的參數也是類似的;需要使用TYPE指定文件類型,自行推斷安裝目錄,或者使用DESTINATION顯式指定安裝目錄。命令格式爲:

install(<FILES|PROGRAMS> files...
        TYPE <type> | DESTINATION <dir>

FILESPROGRAMS的不同之處在於文件的默認權限,前者是一般文件,而後者爲可執行文件,默認有可執行權限,包括:OWNER_EXECUTEGROUP_EXECUTEWORLD_EXECUTE

4 自定義安裝腳本

使用install命令還可以在安裝的時候執行自定義的腳本,使用的命令格式爲:

install([[SCRIPT <file>] [CODE <code>]]
        [COMPONENT <component>] [EXCLUDE_FROM_ALL] [...])

SCRIPT指定安裝時需要執行的腳本;CODE指定的是CMake的命令,也在安裝期間執行,比如:

install(CODE "MESSAGE(\"Sample install message.\")")

5 執行安裝

在構建編譯完成之後,可以使用命令以下執行安裝:

cmake --build . --target install
# 或者針對make構建工具
make install

更加優雅的方法是在cmake3.15版本往後,使用cmake --install命令:

cmake --install . --prefix "../output"

--install指定構建目錄;--preffix指定安裝路徑,覆蓋安裝路徑變量CMAKE_INSTALL_PREFIX

二 打包

1 CPack

要使用打包功能,需要執行include(CPack)啓用相關的功能。

include(CPack)會在構建路徑(Build tree)下生成兩個cpack的配置文件,CPackConfig.cmakeCPackSourceConfig.cmake,其實也就對應了兩個構建目標:packagepackage_source

配合cpack命令,使用-G參數指定生成器,常用的有ZIPTGZ7Z等,可以同時指定多個,格式也是CMake語法中的列表,例如其默認值"STGZ;TGZ"--config參數可以指定打包配置文件,比如:

cpack -G TGZ --config CPackConfig.cmake
cpack -G TGZ --config CPackSourceConfig.cmake

當然也可以使用cmake命令:

cmake --build . --target package
cmake --build . --target package_source

如果使用make作爲構建工具,可以簡單地執行:

make package
make package_source

2 CMake打包相關的內置變量

打包的內容就是install命令安裝的內容,以目標打包(CPackConfig.cmake)爲例,主要的相關變量有:

變量 含義
CPACK_GENERATOR 打包使用的壓縮工具,比如"ZIP";cpack命令的-G參數會覆蓋此設置
CPACK_OUTPUT_CONFIG_FILE 配置文件,默認爲CPackConfig.cmake
CPACK_OUTPUT_FILE_PREFIX 打包安裝的路徑前綴。如果是相對路徑,則是相對於構建目錄
CPACK_INSTALL_PREFIX 打包壓縮包的內部目錄前綴
CPACK_PACKAGE_FILE_NAME 打包壓縮包的名稱,由CPACK_PACKAGE_NAMECPACK_PACKAGE_VERSIONCPACK_SYSTEM_NAME三部分構成

需要特別注意的是:以上變量的設置需要在include(CPack)語句之前

Before including this CPack module in your CMakeLists.txt file, there are a variety of variables that can be set to customize the resulting installers.

其中CPACK_PACKAGE_NAME默認爲項目名稱,CPACK_PACKAGE_VERSION默認爲項目版本號,它們的默認值都是對應project命令所設置的值;但是如果沒有指定版本號,則會是CMake的默認值。

假如:
CPACK_OUTPUT_FILE_PREFIX設置爲/usr/local/package
CPACK_INSTALL_PREFIX設置爲RealCoolEngineer
CPACK_PACKAGE_FILE_NAME設置爲CMakeTemplate-1.0.0
那麼執行打包文件的生成路徑爲:

/usr/local/package/CMakeTemplate-1.0.0.zip

解壓這個包得到的目標文件則會位於路徑下:

/usr/local/package/CMakeTemplate-1.0.0/RealCoolEngineer/

對於源文件打包,相關的變量名基本是對應地以CPACK_SOURCE_開頭,細節可以查看官方文檔。

三 實踐

本文仍以開源項目:https://gitee.com/RealCoolEngineer/cmake-template爲例,本文對應的commit id爲:5713908

在項目根目錄中的CMakeLists.txt文件中,使用安裝和打包的語句爲:

# Install
install(TARGETS math demo
        RUNTIME DESTINATION bin
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib
        PUBLIC_HEADER DESTINATION include)
file(GLOB_RECURSE MATH_LIB_HEADERS src/c/math/*.h)
install(FILES ${MATH_LIB_HEADERS} DESTINATION include/math)

# Package
set(CPACK_GENERATOR "ZIP")
set(CPACK_SET_DESTDIR ON)  # 支持指定安裝目錄
set(CPACK_INSTALL_PREFIX "RealCoolEngineer")
include(CPack)

安裝打包的內容爲項目構建目標可執行文件demo,靜態庫math,以及math庫對應的頭文件。

1 構建腳本

爲了方便,筆者通常將構建的命令編寫爲腳本,在腳本內指定文件的安裝、打包的目標目錄(CMake參數)。

下面針對cmake-template的一個示範,將目標文件安裝並打包到項目根目錄下的output目錄:

#!/bin/bash

set -euf -o pipefail

BUILD_DIR="cmake-build"
INSTALL_DIR=$(pwd)/output
rm -rf "${BUILD_DIR}"

# Configure
BUILD_TYPE=Debug
cmake -B "${BUILD_DIR}" \
    -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \
    -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
    -DCPACK_OUTPUT_FILE_PREFIX="${INSTALL_DIR}"

# Build
cmake --build "${BUILD_DIR}"

cd "${BUILD_DIR}"
# Test
make test CTEST_OUTPUT_ON_FAILURE=TRUE GTEST_COLOR=TRUE
# GTEST_COLOR=TRUE ctest --output-on-failure

# Install
# cmake --build . --target install
make install

# Package
# cmake --build . --target package
make package

cd -

以上便是關於安裝和打包的介紹,關於構建腳本開頭set命令的幾個參數,可參看往期這篇文章:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章