【cmake系列使用教程】
在前邊的文章中已經講過了如何使用cpack,但是那只是一個官方的簡版教程,這次講解的是我在實際開發Linux c中遇到的一些cpakc的問題。
簡介
CPack是作為一個模組出現在cmake構建系統中的,它是一個非常強大的打包工具,可以用來打包二進位制檔案或者原始碼。打包好的二進位制檔案中包含了所有的cmake install命令需要的安裝檔案。在打包原始碼時,也可以生成對應的壓縮包。 cpack可以依賴cmake構建生成的config檔案,也可以自己編寫配置檔案。我屬於比較懶的型別,直接使用cmake生成的config檔案吧。generator是一個比較重要的東西,它算是你要生成的打包檔案的型別,cpack預設提供了一個列表來指定這個東西。
主要工作流程:
- cpack執行
- 尋找CPackConfig.cmake檔案
- 遍歷命令列 -G傳入的generator引數,假如沒有傳入引數,則檢查CPackConfig.cmake檔案或者CPackSourceConfig.cmake檔案中的CPAKC_GENERATOR變數,注意這個優先順序的問題,命令列引數會覆蓋配置檔案的引數。
- 為每一個generator來生成對應的打包檔案
流程就是如此簡單。
具體配置
這裡以我自己的一個開源專案為例子來講解--Sweather,這是個c語言的獲取天氣的命令列工具。地址:github.com/rangaofei/S…
首先看一下工程目錄結構:
.
├── CMakeLists.txt
├── License.txt
├── PIC
├── README.md
├── assets
├── build
├── cmake-build-debug
├── logfile
├── pack
├── sakabrew.sh
└── src
複製程式碼
- CMakeLists.txt是cmake執行的入口檔案
- License.txt是協議資訊
- PIC是我自己截的圖
- README.md是說明檔案
- assets是資原始檔件
- build是外部構建的資料夾
- cmake-build-debug這個是CLion自動生成的資料夾
- src是主要的c檔案目錄
- pack是打包檔案的資料夾
- sakabrew.sh是我自己編寫的自動化檔案
- 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")
這裡有一個對應的關係:
- 7Z-7Zzip-(.7z)
- TBZ2(tar.bz2)
- TGZ(.tar.gz)
- TXZ(.tar.xz)
- TZ(.tar.Z)
- 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指令碼,主要流程:
- 尋找build資料夾,沒有就生成
- 進入build資料夾,清空該資料夾下的所有檔案
- 執行cmake ..外部構建程式
- 執行打包命令並寫入日誌檔案
- 讀取日誌檔案中最後一行生成的檔名稱,版本名稱,校驗碼存入變數
- 自動生成的檔案需要新增值git倉庫,上傳至遠端倉庫
- 進入homebrew --repo rangaofei/saka目錄,進入程式指令碼資料夾
- 替換對應的ruby指令碼(sweather.rb)中的下載地址和SHA256.
- 新增檔案,上傳至遠端倉庫
主要程式碼如下:
#!/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…
最後的最後,再寫一點我最近的感想,否極不一定會泰來。我這條鹹魚應該翻身無望了,備受打擊之後我感覺只能做一條最鹹的鹹魚。