cmake使用教程(十一)-使用cpack打包原始碼並編寫自動化指令碼上傳到倉庫

saka發表於2018-07-20

【cmake系列使用教程】

cmake使用教程(一)-起步

cmake使用教程(二)-新增庫

cmake使用教程(三)-安裝、測試、系統自檢

cmake使用教程(四)-檔案生成器

cmake使用教程(五)-cpack生成安裝包

cmake使用教程(六)-蛋疼的語法

cmake使用教程(七)-流程和迴圈

cmake使用教程(八)-macro和function

cmake使用教程(九)-關於安卓的交叉編譯

cmake使用教程(十)-關於file

在前邊的文章中已經講過了如何使用cpack,但是那只是一個官方的簡版教程,這次講解的是我在實際開發Linux c中遇到的一些cpakc的問題。

簡介

CPack是作為一個模組出現在cmake構建系統中的,它是一個非常強大的打包工具,可以用來打包二進位制檔案或者原始碼。打包好的二進位制檔案中包含了所有的cmake install命令需要的安裝檔案。在打包原始碼時,也可以生成對應的壓縮包。 cpack可以依賴cmake構建生成的config檔案,也可以自己編寫配置檔案。我屬於比較懶的型別,直接使用cmake生成的config檔案吧。generator是一個比較重要的東西,它算是你要生成的打包檔案的型別,cpack預設提供了一個列表來指定這個東西。

主要工作流程:

  1. cpack執行
  2. 尋找CPackConfig.cmake檔案
  3. 遍歷命令列 -G傳入的generator引數,假如沒有傳入引數,則檢查CPackConfig.cmake檔案或者CPackSourceConfig.cmake檔案中的CPAKC_GENERATOR變數,注意這個優先順序的問題,命令列引數會覆蓋配置檔案的引數。
  4. 為每一個generator來生成對應的打包檔案

流程就是如此簡單。

具體配置

這裡以我自己的一個開源專案為例子來講解--Sweather,這是個c語言的獲取天氣的命令列工具。地址:github.com/rangaofei/S…

首先看一下工程目錄結構:

.
├── CMakeLists.txt
├── License.txt
├── PIC
├── README.md
├── assets
├── build
├── cmake-build-debug
├── logfile
├── pack
├── sakabrew.sh
└── src
複製程式碼
  1. CMakeLists.txt是cmake執行的入口檔案
  2. License.txt是協議資訊
  3. PIC是我自己截的圖
  4. README.md是說明檔案
  5. assets是資原始檔件
  6. build是外部構建的資料夾
  7. cmake-build-debug這個是CLion自動生成的資料夾
  8. src是主要的c檔案目錄
  9. pack是打包檔案的資料夾
  10. sakabrew.sh是我自己編寫的自動化檔案
  11. logfile是sakabrew.sh檔案生成的日誌。

主要的CMakeLists.txt配置如下:

CMAKE_MINIMUM_REQUIRED(VERSION 3.8)

set(CMAKE_C_STANDARD 99)
project(SWeather C)

set(VERSION_MAJOR 1)
set(VERSION_MINOR 3)
set(VERSION_PATCH 1)

#採用debug模式時啟用'ENABLE_DEBUG'
IF (CMAKE_BUILD_TYPE STREQUAL Debug)
    ADD_DEFINITIONS(-DENABLE_DEBUG)
ENDIF (CMAKE_BUILD_TYPE STREQUAL Debug)

add_subdirectory(src)

include(InstallRequiredSystemLibraries)
set(CPACK_PACKAGE_DIRECTORY ${PROJECT_SOURCE_DIR}/pack)
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/License.txt")
set(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${VERSION_PATCH}")
set(PROJECT_VERSION_FULL ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(CPACK_SOURCE_IGNORE_FILES
        ${PROJECT_SOURCE_DIR}/build
        ${PROJECT_SOURCE_DIR}/cmake-build-debug
        ${PROJECT_SOURCE_DIR}/pack
        ${PROJECT_SOURCE_DIR}//.idea
        ${PROJECT_SOURCE_DIR}/.DS_Store
        ${PROJECT_SOURCE_DIR}/.git
        ${PROJECT_SOURCE_DIR}/.gitignore
        ${PROJECT_SOURCE_DIR}/.vscode
        ${PROJECT_SOURCE_DIR}/.PIC
        ${PROJECT_SOURCE_DIR}/assets/city.txt)

set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_PACKAGE_FILE_NAME sweather-${PROJECT_VERSION_FULL})


include(CPack)
複製程式碼

設定打包檔案生成位置和協議資訊

set(CPACK_PACKAGE_DIRECTORY ${PROJECT_SOURCE_DIR}/pack)

set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/License.txt")

可以通過CPACK_PACKAGE_DIRECTORY變數配置,我設定的是根目錄下的pack資料夾,這樣生成的所有檔案都會在這裡,不會汙染其他資料夾。

CPACK_RESOURCE_FILE_LICENSE可以用來指定協議資訊

設定版本資訊

set(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${VERSION_PATCH}")
複製程式碼

這個也比較簡單,版本資訊採用cmake中設定的版本資訊,後邊將會用來生成檔名字。

設定忽略檔案

set(CPACK_SOURCE_IGNORE_FILES
        ${PROJECT_SOURCE_DIR}/build
        ${PROJECT_SOURCE_DIR}/cmake-build-debug
        ${PROJECT_SOURCE_DIR}/pack
        ${PROJECT_SOURCE_DIR}/.idea
        ${PROJECT_SOURCE_DIR}/.DS_Store
        ${PROJECT_SOURCE_DIR}/.git
        ${PROJECT_SOURCE_DIR}/.gitignore
        ${PROJECT_SOURCE_DIR}/.vscode
        ${PROJECT_SOURCE_DIR}/.PIC
        ${PROJECT_SOURCE_DIR}/assets/city.txt)
複製程式碼

這個地方需要注意,最好不要用正規表示式,容易發生錯誤,這裡吧所有不需要的檔案都排除在了外邊,當然這種簡潔的方式是簡歷在外部構建的基礎上的。在構建的時候進入buid資料夾執行build命令,就可以不汙染原始檔。

設定生成器

set(CPACK_SOURCE_GENERATOR "TGZ")

這裡有一個對應的關係:

  1. 7Z-7Zzip-(.7z)
  2. TBZ2(tar.bz2)
  3. TGZ(.tar.gz)
  4. TXZ(.tar.xz)
  5. TZ(.tar.Z)
  6. ZIP(.zip)

我選擇的是TGZ,所以生成的檔案的副檔名稱將會是.tar.gz,這個字尾將會在下邊介紹的打包名稱後新增。

設定檔案打包檔名稱

set(PROJECT_VERSION_FULL ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(CPACK_SOURCE_PACKAGE_FILE_NAME sweather-${PROJECT_VERSION_FULL})
複製程式碼

打包檔名稱不需要設定字尾,系統會自動根據generator來生成字尾。 在我這個檔案中生成的打包檔名稱將會是sweather-1.3.1.tar.gz

這樣我們就完成了主要的配置,然後進入build資料夾,執行cmake ..即可生成cpack需要的配置檔案,此處我要打包原始檔,所以繼續執行cpack --config CPackSourceConfig.cmake,這樣就在pack資料夾下生成了上邊設定好的檔案。

自動化構建上傳到brew倉庫

上傳到github不難,但是修改rb檔案上傳至自己的homebrew-saka倉庫是比較麻煩的,需要修改下載地址和SHA256碼。所以我自己寫了一個自動化構建上傳的shell指令碼,主要流程:

  1. 尋找build資料夾,沒有就生成
  2. 進入build資料夾,清空該資料夾下的所有檔案
  3. 執行cmake ..外部構建程式
  4. 執行打包命令並寫入日誌檔案
  5. 讀取日誌檔案中最後一行生成的檔名稱,版本名稱,校驗碼存入變數
  6. 自動生成的檔案需要新增值git倉庫,上傳至遠端倉庫
  7. 進入homebrew --repo rangaofei/saka目錄,進入程式指令碼資料夾
  8. 替換對應的ruby指令碼(sweather.rb)中的下載地址和SHA256.
  9. 新增檔案,上傳至遠端倉庫

主要程式碼如下:

#!/usr/bin/env bash
# 尋找build資料夾,不存在就建立
function findBuild(){
    if [ ! -d "./build" ];then
        mkdir ./build
    else
        echo "build資料夾已經存在"
    fi
}

# 進入build資料夾,清除所有的快取檔案
function cmakeOutBuild(){
    cd ./build
    echo "進入build資料夾,即將清除檔案快取"
    rm -rf ./*
    echo "build資料夾快取清理完畢,即將執行外部構建"
    cmake ..
    echo "外部構建執行完成"
}
# 打包檔案
function cmakePackage(){
    cpack --config CPackSourceConfig.cmake
}

# 讀取日誌檔案,讀入檔名稱
function readLogFile(){
    if [ -e "logfile" ];then
        tmp_path=`echo $(pwd) | sed -n "s#/#\\\\\/#gp"`
        echo "$tmp_path"
        package_name=`sed -n '$p' logfile |sed -n "s/.*CPack:.*\($tmp_path.*tar\.gz\).*generated./\1/gp"`
        package_version=`echo "${package_name}" | sed -n 's/.*pack\/\(.*\)\.tar\.gz/\1/gp'|sed -n 's/\./\\\\./gp'`
        echo "---name:${package_name}\n---version:${package_version}\n"
    else
        echo "file not found"
    fi
}

# 本地提交git倉庫,然後推送至遠端倉庫
function commitToGitHub(){
    if [ ! -n "$package_name" ];then
        echo "不能提交"
    else
        git add ${package_name}
        git commit -m "new version"
        git push
    fi
}

# 本地提交至brew倉庫,遠端提交
function commitToBrew(){
    if [ ! -n "$package_name" ];then
        echo "不能提交到brew"
    else
        fileSHA256=`openssl dgst -sha256 ${package_name}|sed -n "s/.*= \(.*\)/\1/gp"`
        echo "$fileSHA256"
        cd $(brew --repo rangaofei/saka)/Formula
        sed -i -n "s/sweather-[0-9]\.[0-9]\.[0-9]/sweather-1\.3\.1/g" sweather.rb
        sed -i -n "s/sha256 \".*\"/sha256 \"$fileSHA256\"/g" sweather.rb
        git add sweather.rb
        git commit -m "new version:$package_version"
        git push
        cd -

    fi

}
findBuild
cmakeOutBuild

if [ ! -e "CPackSourceConfig.cmake" ];then
    echo "未找到打包檔案,請重新執行此指令碼"
else
    echo "已生成打包檔案,即將開始打包"
    name=`cmakePackage`
    echo "------------------------------"
    echo "$name"| tee -a ../logfile
fi
cd ..
readLogFile
#commitToGitHub
commitToBrew

複製程式碼

這樣就完成了所有的工作,下次只需要執行. ./sakabrew.sh即可自動構建檔案並上傳至倉庫了。

最後,附上以前的文章地址和github地址

github地址:github.com/rangaofei/S…

HomeBrew常規使用教程:juejin.im/post/5a559b…

最後的最後,再寫一點我最近的感想,否極不一定會泰來。我這條鹹魚應該翻身無望了,備受打擊之後我感覺只能做一條最鹹的鹹魚。

相關文章