CMake之CPack

一、CPack

CPack 是 CMake 2.4.2 之后的一个内置工具,用于创建软件的二进制包和源代码包。
CPack 在整个 CMake 工具链的位置。
在这里插入图片描述
CPack,则是CMake下的一个打包工具,其支持将软件打包成 .deb, .zip, .7z 等各种各样的软件包;

1.用CPack打包成为deb包

使用CPack其实很简单,核心只有两步:

  • 设定软件包的属性(例如:包名称,包类型,版本号,作者等信息)
  • 指定需要打包的文件(例如:可执行文件,静态库,动态库)
cmake_minimum_required(VERSION 3.10)

# 设置项目名
project(CMakeTutorial VERSION 1.2)

# 添加头文件搜索路径
include_directories(
${PROJECT_SOURCE_DIR}/inc
)

# 生成库
add_library(PrinterChar STATIC src/printer_char.cpp)    # 静态库
add_library(PrinterInt SHARED src/printer_int.cpp)      # 动态库

# 添加需要构建的可执行文件
#------方法对比 1.1 - 不用库的写法
# add_executable(LinkLibraryDemo link_library_demo.cpp src/printer_char.cpp src/printer_int.cpp)
#------方法对比 1.2 - 用库的写法
add_executable(LinkLibraryDemo demo/link_library_demo.cpp)
target_link_libraries(LinkLibraryDemo PRIVATE PrinterChar)   # 为目标添加静态库
target_link_libraries(LinkLibraryDemo PRIVATE PrinterInt)    # 为目标添加动态库

##---------------- 以下为用CPack打包成deb包的内容 ----------------##
# 指定deb包的版本号
set(_VERSION_MAJOR 1)
set(_VERSION_MINOR 2)
set(_VERSION_PATCH 3)
set(CPACK_PACKAGE_VERSION_MAJOR "${_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${_VERSION_PATCH}")
# 指定CPack生成的是deb包(还可以是其他包如 <.7z> <.zip> 等)
set(CPACK_GENERATOR "DEB")
# 指定包名
set(CPACK_PACKAGE_NAME "mork_printer_package_demo")
# 指定程序名,就是程序安装后的名字
set(CPACK_DEBIAN_PACKAGE_NAME "mork_printer_project_demo")
# 指定运行的计算机架构
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
# 指定所需的依赖
# set(CPACK_DEBIAN_PACKAGE_DEPENDS "libgrpc++")
# 设置包作者的联系方式
set(CPACK_PACKAGE_CONTACT "[email protected]")
# 设置维护人
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "members of [email protected]")
# 指定需要安装的文件
INSTALL(TARGETS LinkLibraryDemo PrinterInt PrinterChar
        RUNTIME DESTINATION /tmp/cmake_demo
        #LIBRARY DESTINATION /tmp/cmake_demo    # 通常,编译器只会在 </usr/lib> 和 </lib> 中找头文件,如果
        #ARCHIVE DESTINATION /tmp/cmake_demo    # 将库文件放在其他目录,可能会引起找不到库文件错误
        )

include(CPack)
#include <iostream>
#include <string>

int Add(int t1, int t2)
{
    
    
    int result = t1 + t2;

    std::cout << t1 << " + " << t2 << " is: " << result << std::endl;

    return result;
}

int main()
{
    
    
    int ret_add;

    ret_add = Add(1, 2);
    std::cout << "Hello, this is my first cmake sample "  << ret_add << std::endl;

    return 0;
}
cmake_minimum_required (VERSION 3.0.0)

project (cmake_test VERSION 0.0.4)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${
    
    CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${
    
    CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${
    
    CMAKE_BINARY_DIR}/bin)

add_executable(demo main.cpp)

# package program
message(STATUS "CPack Configuration added.")

include(InstallRequiredSystemLibraries)

set(CPACK_PACKAGE_NAME ${
    
    PROJECT_NAME})

set(CPACK_PACKAGE_VERSION ${
    
    PROJECT_VERSION})
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
    "${CMAKE_CURRENT_SOURCE_DIR}/prerm;${CMAKE_CURRENT_SOURCE_DIR}/postrm")
set(CPACK_PACKAGE_DIRECTORY ${
    
    CMAKE_BINARY_DIR})
set(CPACK_SOURCE_IGNORE_FILES build)

set(CPACK_PACKAGE_CONTACT "[email protected]")
set(CPACK_PACKAGE_DESCRIPTION "cpack test program")

# set(CPACK_SET_DESTDIR ON)
# # 设置安装到的目录路径
# set(CMAKE_INSTALL_BINDIR "/home/raymond/install")

install(TARGETS demo
        RUNTIME DESTINATION ${
    
    CMAKE_INSTALL_BINDIR})


# according to CMake, CPack must be included LAST
# after all settings have been set
include(CPack)

在上面的CMakeLists.txt中,最重要的是INSTALL这个指令,上面的INSTALL指令所表达的意思是,需要将LinkLibraryDemo, PrinterInt, PrinterChar 这3个文件打包,其中可执行文件放在/tmp/cmake_demo,这个目录中,静态库和动态库文件则放在默认目录中。

如果你不赋值CPACK_DEBIAN_PACKAGE_DEPENDS这个变量,则在debian/control文件中,没有Depends这一行,虽然在你自己的机器上不影响打包构建。但是将deb包提供给他人安装后,可能无法运行。如果添加这一行,则可以在安装时就检查依赖是否满足。

include(InstallRequiredSystemLibraries):这个命令是CMake教程中建议使用的,该命令将包括当前平台项目所需的任何运行时库。
CPACK_PACKAGE_NAME: 包的名称,默认使用项目名称
CPACK_PACKAGE_VERSION : 包的版本,默认使用项目版本
CPACK_PACKAGE_DIRECTORY :cpack要打包的目录,如果没有设置,默认使用编译目录
CPACK_SOURCE_IGNORE_FILES :打包源代码时要排除的目录,默认情况下会将整个工程的目录都打包进源代码,但有些不属于代码的部分或者不想打包的部分可以通过这个变量排除,比如这里的build目录
CPACK_PACKAGE_CONTACT :程序的维护者信息,这是在打包成DEB文件时必须的一个变量
CPACK_PACKAGE_DESCRIPTION : 描述包的信息
install()命令 :描述了包内的文件安装的位置,如可执行文件和共享库等,这里只设置了一个demo的可执行文件。
include(CPack) : 所有的cpack命令需以这个结尾

编译

cmake -B build 
cmake --build build --target package(cmake --build build --target help) 打包install()的内容
cmake --build build --target package_source,打包源码

不用Cmake:Ubuntu Deb 安装包的内容可以 参考

更多例子请参考:

2.如何确定的Depends依赖包?

使用ldd查看可执行软件链接的动态库。

 ldd xweather | grep [Qq]t
        libQt5Widgets.so.5 => /lib/x86_64-linux-gnu/libQt5Widgets.so.5 (0x00007ff241739000)                
        libQt5Gui.so.5 => /lib/x86_64-linux-gnu/libQt5Gui.so.5 (0x00007ff2411ae000)                        
        libQt5Network.so.5 => /lib/x86_64-linux-gnu/libQt5Network.so.5 (0x00007ff24100d000)                
        libQt5Core.so.5 => /lib/x86_64-linux-gnu/libQt5Core.so.5 (0x00007ff240b12000)


需要确定这些动态库都在哪些软件包里。
$ dpkg -S libQt5Widgets.so.5 
libqt5widgets5:amd64: /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.11
libqt5widgets5:amd64: /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
libqt5widgets5:amd64: /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.11.3


通过上面的步骤,我们就可以得到libQt5Widgets.so.5这个动态库在libqt5widgets5这个包中
将这些软件包名赋值给CPACK_DEBIAN_PACKAGE_DEPENDS即可。
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5core5a, libqt5widgets5, libqt5network5, libqt5gui5")

3.如何确定编译Build-Depends?

The devscripts package provides a collection of scripts which may be of use to Debian developers and others wishing to build Debian packages.

sudo apt-get install devscripts

要找出编译你的软件所需的软件包可以使用这个命令

$ dpkg-depcheck -d your_build_exec_binary
Packages needed:
  fonts-lohit-deva

另一种方法可以执行

$ objdump -p your_build_exec_binary | grep NEEDED
  NEEDED               libQt5Widgets.so.5

通过上述两个办法获取到动态库后,执行下面的命令,获取开发包。

$ dpkg -S libQt5Network | grep dev
qtbase5-dev:amd64: /usr/lib/x86_64-linux-gnu/libQt5Network.so

填入到Build-Depends中即可。

4.Cpakc打包RPM包

参考:

二、deb的简单使用

查看一下这个deb软件包的信息和内容:

查看控制文件内容
dpkg-deb -I <deb包文件>

查看打包的内容
dpkg -c <deb包文件>

sudo dpkg -i <deb包文件>	# 安装deb包
sudo dpkg -l			# 显示已经安装的包
sudo dpkg -P <包名称>	# 卸载指定的软件包

dpkg-deb -R X.deb. X 解压包
dpkg-deb -X X.deb X 解压包

#安装(解包并配置) 
dpkg -i|--install <.deb file name>
#dpkg -i mydeb-1.deb

#强制安装
dpkg --force-depends -i mydeb-1.deb

#解包:该命令仅对 “mydeb-1.deb”进行解包操作,不会执行包配置工作
dpkg --unpack mydeb-1.deb

#卸载:删除包,但保留配置文件
dpkg -r|--remove <package> 
# dpkg -r my-deb 
#该命令删除包,且删除配置文件
dpkg -P|--purge my-deb         

#查看deb包是否安装/deb包的信息 
dpkg -s|--status <package>
# dpkg -s my-deb

#查看deb包文件内容 
dpkg -c mydeb-1.deb

#查看当前目录某个deb包的信息
dpkg --info mydeb-1.deb

#解压deb中所要安装的文件
#第一个参数为所要解压的deb包,第二个参数为将deb包解压到指定的目录
dpkg -x  mydeb-1.deb mydeb-1

#解压deb包中DEBIAN目录下的文件(至少包含control文件)
dpkg -e mydeb-1.deb mydeb-1/DEBIAN

#列出与该包关联的文件 dpkg -L|--listfiles <package>
dpkg -L my-deb 

#配置软件包 
dpkg --configure <package>
# dpkg --configure my-deb


#解压deb包中DEBIAN目录下的文件(至少包含control文件)
dpkg -e mydeb-1.deb mydeb-1/DEBIAN

#列出与该包关联的文件 dpkg -L|--listfiles <package>
dpkg -L my-deb 

#配置软件包 
dpkg --configure <package>
# dpkg --configure my-deb

三、deb包相关文件说明

1.control文件

control 文件字段解析
字段 用途 例子/其他
Package 程序名称 中间不能有空格
Version 软件版本
Description 程序说明
Section 软件类别 utils, net, mail, text, x11
Priority 软件对于系统的重要程度 required, standard, optional, extra等;
Essential 是否是系统最基本的软件包 yes/no,若为yes,则不允许卸载(除非强制性卸载)
Architecture 软件所支持的平台架构 i386, amd64, m68k, sparc, alpha, powerpc等
Source 软件包的源代码名称
Depends 软件所依赖的其他软件包和库文件 若依赖多个软件包和库文件,采用逗号隔开
Pre-Depends 软件安装前必须安装、配置依赖性的软件包和库文件 常用于必须的预运行脚本需求
Recommends 推荐安装的其他软件包和库文件
Suggests 建议安装的其他软件包和库文件

2.preinst文件

在Deb包文件解包之前(即软件安装前),将会运行该脚本。可以停止作用于待升级软件包的服务,直到软件包安装或升级完成

3.postinst文件

负责完成安装包时的配置工作。如新安装或升级的软件重启服务

#软件安装完后,执行该Shell脚本,一般用来配置软件执行环境,必须以“#!/bin/sh”为首行

#!/bin/sh
echo "my deb" > /root/mydeb.log

#!/bin/sh
if [ "$1" = "configure" ]; then
/Applications/MobileLog.app/MobileLog -install
/bin/launchctl load -wF /System/Library/LaunchDaemons/com.iXtension.MobileLogDaemon.plist 
fi

4.prerm文件

该脚本负责停止与软件包相关联的daemon服务。它在删除软件包关联文件之前执行

#!/bin/sh
if [[ $1 == remove ]]; then
/Applications/MobileLog.app/MobileLog -uninstall
/bin/launchctl unload -wF /System/Library/LaunchDaemons/com.iXtension.MobileLogDaemon.plist 
fi

5.postrm文件

#软件卸载后,执行该Shell脚本,一般作为清理收尾工作,必须以“#!/bin/sh”为首行

#!/bin/sh
rm -rf /root/mydeb.log

参考:

猜你喜欢

转载自blog.csdn.net/u011436427/article/details/131599481
今日推荐