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 默认提供了一个列表来指定这个东西.
主要工作流程:
cpack 执行
寻找 CPackConfig.cmake 文件
遍历命令行 -G 传入的 generator 参数, 假如没有传入参数, 则检查 CPackConfig.cmake 文件或者 CPackSourceConfig.cmake 文件中的 CPAKC_GENERATOR 变量, 注意这个优先级的问题, 命令行参数会覆盖配置文件的参数.
为每一个 generator 来生成对应的打包文件
流程就是如此简单.
具体配置
这里以我自己的一个开源项目为例子来讲解 --Sweather, 这是个 c 语言的获取天气的命令行工具. 地址: https://github.com/rangaofei/SWeather
首先看一下工程目录结构:
- .
- 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 地址: https://github.com/rangaofei/SWeather
HomeBrew 常规使用教程: juejin.im/post/5a559b...
最后的最后, 再写一点我最近的感想, 否极不一定会泰来. 我这条咸鱼应该翻身无望了, 备受打击之后我感觉只能做一条最咸的咸鱼.
来源: https://juejin.im/post/5b51b3e76fb9a04fc34c0c7b