IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 通过CPack将库打包为.sh可执行包 -> 正文阅读

[系统运维]通过CPack将库打包为.sh可执行包

????????软件开发完成后对外发布后,通常需要将生成的库文件和头文件进行打包发布,供其他人安装使用,使用CMake进行构建的项目中,通常使用CPack进行软件包的打包和发布,本文将介绍如何通过CPack将软件包打包为.sh包发布,并替换默认的脚本文件,定制安装操作。

一、CPack简介

????????CPack是一款优秀的跨平台软件打包发布工具,支持丰富的打包发布格式,包括NSIS、RPM、DEB、TGZ和STGZ等。不同的操作系统下,有多种对应的CPack打包器,其中Windows平台一下一般选择通过NSIS打包,生成.exe可执行文件进行交互式安装。Linux下Ubuntu系统一般通过DEB打包,生成.deb文件(Ubuntn不支持rpm包,需要将rpm包转换为deb后再安装)。而RedHat系统下,可通过RPM打包器打包为.rpm包。对应不同操作系统,也可以通过CPack将软件打包为与平台无关的TGZ和ZIP等压缩包。

????????Windows下打包为.exe可执行文件进行安装,是可以支持寻找软件包安装目录,并可通过添加安装后处理脚本,自动添加环境变量等操作的,比较友好。Linux的.rpm包也是可以修改默认安装路径的,而.deb包的默认安装路径是/usr/local或者/usr,对于开发环境下多用户的服务器,会有很多不友好的地方,因此通过STZG打包器生成.sh包,进行交互式安装是一个比较好的替代方式。

? ? ? ? CPack打包哪些文件是依赖于CMake中的install操作的,CPack只是打包工具,不指定打包文件,CMake install请参考其他博客。

二、STGZ包简介

? ? ? ? Linux下的STGZ包后缀通常是.sh和.run,其结构是一样的,都是一个sh脚本和压缩包文件拼接在一起后生成的,sh脚本中定义了软件包安装的一些操作,包括校验压缩包,解压压缩包,将文件拷贝到对应目录和设置环境变量等等,可以根据软件包安装需要进行定义。压缩包通常就是软件包对应的头文件和库文件了。

cat install.sh software.tag.gz > stgz_install.sh

?三、通过CPack生成.sh包

? ? ? ? 在指定了install内容之后,可通过设置CPACK_GENERATOR为STGZ来指定STGZ生成器将软件打包为.sh文件。打包的其他设置也可以通过对应CPack变量来进行设置,具体可设置的变量和对应功能可查阅官方文档(CPack官方文档),特别需要注意的是,只有CPack对应的变量才能在STGZ打包器的sh脚本中读取到,其他CMake变量在sh脚本中无法获取,因此如果想要传递一些设置到sh脚本里,只能通过CPack变量传递。

set(CPACK_GENERATOR "STGZ")
set(CPACK_PACKAGING_INSTALL_PREFIX "/")
set(CPACK_PACKAGE_VENDOR "test")
set(CPACK_PACKAGE_NAME "${CMAKE_PROJECT_NAME}")
set(CPACK_PACKAGE_VERSION "${CMAKE_PROJECT_VERSION}")
set(CPACK_PACKAGE_DESCRIPTION "${CMAKE_PROJECT_NAME} library")
set(CPACK_PACKAGE_MAINTAINER "test")
set(CPACK_PACKAGE_HOMEPAGE_URL "http://xxxx.com")

set (TAR_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_HOST_SYSTEM_NAME}-any")
if (DEFINED CUDA_VERSION)
	set (TAR_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_HOST_SYSTEM_NAME}-CUDA${CUDA_VERSION}")
elseif (DEFINED CUDAToolkit_VERSION)
	set (TAR_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_HOST_SYSTEM_NAME}-CUDA${CUDAToolkit_VERSION}")
endif ()
set(CPACK_PACKAGE_FILE_NAME "${TAR_FILE_NAME}")

set(CPACK_PACKAGE_DIRECTORY package)
include(CPack)

?????????CPack有默认的sh脚本,不过sh脚本功能比较简单,只支持展示license以及是否添加次文件夹操作,难以满足实际需要,如下图glog的.sh包安装所示。

?四、替换CPack默认的sh脚本,定制安装操作

? ? ? ?CPack默认的sh安装脚本,功能过于简单,如果想要添加额外的安装操作,就需要替换掉CPack默认的sh安装脚本,并定制安装操作。只需要自己写一个shell脚本,并命名为CPack.STGZ_Header.sh.in,.in文件是CMake中的模板文件,模板文件中的通过@包裹的@xxx@模板变量会在CMake阶段替换实际的内容,前面也说到,sh脚本中只能获取到CPack的对应变量,而无法获取到CMake中的其他变量,这是需要特别注意的。通过CMake的CMAKE_MODULE_PATH将包含CPack.STGZ_Header.sh.in的路径设置为CMake的模块路径,引入脚本文件就可以替换掉默认的sh脚本文件,CPack就会使用你的sh脚本来生成sh包。

set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules")

? ? ? ? 这里提供了一个安装脚本模板,可在此基础上进行修改,支持交互式选择安装目录,并自动添加环境变量,也可以通过命令行参数设置对应的参数。

#!/bin/bash
#
# NAME:  @CPACK_PACKAGE_NAME@
# VER:   @CPACK_PACKAGE_VERSION@
# PLAT:  linux-64
# LINES: 323

# check shell
if ! echo "$0" | grep '\.sh$' > /dev/null; then
    printf 'Please run using "bash" or "sh", but not "." or "source"\\n' >&2
    return 1
fi

# Determine RUNNING_SHELL; if SHELL is non-zero use that.
if [ -n "$SHELL" ]; then
    RUNNING_SHELL="$SHELL"
else
    if [ "$(uname)" = "Darwin" ]; then
        RUNNING_SHELL=/bin/bash
    else
        if [ -d /proc ] && [ -r /proc ] && [ -d /proc/$$ ] && [ -r /proc/$$ ] && [ -L /proc/$$/exe ] && [ -r /proc/$$/exe ]; then
            RUNNING_SHELL=$(readlink /proc/$$/exe)
        fi
        if [ -z "$RUNNING_SHELL" ] || [ ! -f "$RUNNING_SHELL" ]; then
            RUNNING_SHELL=$(ps -p $$ -o args= | sed 's|^-||')
            case "$RUNNING_SHELL" in
                */*)
                    ;;
                default)
                    RUNNING_SHELL=$(which "$RUNNING_SHELL")
                    ;;
            esac
        fi
    fi
fi

# Some final fallback locations
if [ -z "$RUNNING_SHELL" ] || [ ! -f "$RUNNING_SHELL" ]; then
    if [ -f /bin/bash ]; then
        RUNNING_SHELL=/bin/bash
    else
        if [ -f /bin/sh ]; then
            RUNNING_SHELL=/bin/sh
        fi
    fi
fi

if [ -z "$RUNNING_SHELL" ] || [ ! -f "$RUNNING_SHELL" ]; then
    printf 'Unable to determine your shell. Please set the SHELL env. var and re-run\\n' >&2
    exit 1
fi

THIS_DIR=$(DIRNAME=$(dirname "$0"); cd "$DIRNAME"; pwd)
THIS_FILE=$(basename "$0")
THIS_PATH="$THIS_DIR/$THIS_FILE"
PREFIX=$HOME/software
UPREFIX=0
SETENV=0
DSETENV=0
FORCE=0
USAGE="
usage: $0 [options]

Installs @CPACK_PACKAGE_NAME@ @CPACK_PACKAGE_VERSION@

-h|--help              print this help message and exit    
-p|--prefix=<path>     install prefix, defaults to $PREFIX, must not contain spaces
-e|--env               automatic setup of environment variables
-d|--disable-env       not automatic setup of environment variables
-f|--force             clear folder if install prefix folder already exists  
"

OPTS=$(getopt -o hp:edf -l help,prefix:,env,disable-env,force -- "$@" 2>/dev/null)
if [ ! $? ]; then
    printf "%s\\n" "$USAGE"
    exit 2
fi
eval set -- "$OPTS"

while true; do
    case "$1" in
        -h|--help)
            printf "%s\\n" "$USAGE"
            exit 2
            ;;
        -f|--force)
            FORCE=1
            shift
            ;;
        -p|--prefix)
            PREFIX="$2"
            UPREFIX=1
            shift
            shift
            ;;
        -e|--env)
            SETENV=1
            shift
            ;;
        -d|--disable-env)
            DSETENV=1
            shift
            ;;
        --)
            shift
            break
            ;;
        *)
            printf "ERROR: did not recognize option '%s', please try -h\\n" "$1"
            exit 1
            ;;
    esac
done

# check tar
if ! tar --help >/dev/null 2>&1; then
    printf "WARNING: tar does not appear to be installed this may cause problems below\\n" >&2
fi

# check system architecture type
if [ "$(uname -m)" != "x86_64" ]; then
    printf "WARNING:\\n"
    printf "    Your operating system appears not to be 64-bit, but you are trying to\\n"
    printf "    install a 64-bit version of @CPACK_PACKAGE_NAME@.\\n"
    printf "    Are sure you want to continue the installation? [yes|no]\\n"
    printf "[no] >>> "
    read -r ans
    if [ "$ans" != "yes" ] && [ "$ans" != "Yes" ] && [ "$ans" != "YES" ] && \
        [ "$ans" != "y" ]   && [ "$ans" != "Y" ]
    then
        printf "Aborting installation\\n"
        exit 2
    fi
fi

#check operating system type
if [ "$(uname)" != "Linux" ]; then
    printf "WARNING:\\n"
    printf "    Your operating system does not appear to be Linux, \\n"
    printf "    but you are trying to install a Linux version of @CPACK_PACKAGE_NAME@.\\n"
    printf "    Are sure you want to continue the installation? [yes|no]\\n"
    printf "[no] >>> "
    read -r ans
    if [ "$ans" != "yes" ] && [ "$ans" != "Yes" ] && [ "$ans" != "YES" ] && \
        [ "$ans" != "y" ]   && [ "$ans" != "Y" ]
    then
        printf "Aborting installation\\n"
        exit 2
    fi
fi

printf "\\n"
printf "Welcome to @CPACK_PACKAGE_NAME@ @CPACK_PACKAGE_VERSION@\\n"
printf "\\n"
printf "@CPACK_PACKAGE_NAME@ will now be installed into this location:\\n"
printf "%s\\n" "$PREFIX"
printf "\\n"

if [ "$UPREFIX" = "0" ]; then
    printf "  - Press ENTER to confirm the location\\n"
    printf "  - Press CTRL-C to abort the installation\\n"
    printf "  - Or specify a different location below\\n"
    printf "\\n"
    printf "[%s] >>> " "$PREFIX"
    read -r user_prefix
    if [ "$user_prefix" != "" ]; then
        case "$user_prefix" in
            *\ * )
                printf "ERROR: Cannot install into directories with spaces\\n" >&2
                exit 1
                ;;
            *)
                eval PREFIX="$user_prefix"
                ;;
        esac
    fi
fi

case "$PREFIX" in
    *\ * )
        printf "ERROR: Cannot install into directories with spaces\\n" >&2
        exit 1
        ;;
esac

PREFIX=$PREFIX/@CPACK_PACKAGE_NAME@

# confirm whether to overwrite
if [ "$FORCE" = "0" ] && [ -e "$PREFIX" ]; then
    if [ "$(ls -A $PREFIX)" ]; then
        printf "ERROR: File or directory is not empty: '%s'\\n" "$PREFIX" >&2
        printf "Or use -f/--force to force the installation which will clear the original directory.\n" >&2
        exit 1
    fi
fi

if [ "$FORCE" = "1" ] && [ -e "$PREFIX" ]; then
    if [ "$(ls -A $PREFIX)" ]; then
        force_ans=no
        printf "! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !\\n"
        printf "Do you wish to clear the installation directory: '%s' ? [yes|no]\\n" "$PREFIX"
        printf "\\n"
        printf "[default is %s] >>> " "$force_ans"
        read -r uans
        if [ "$uans" != "" ]; then
            force_ans=$uans
        fi

        if [ "$force_ans" = "yes" ] || [ "$force_ans" = "Yes" ] || [ "$force_ans" = "YES" ] || \
            [ "$force_ans" = "y" ] || [ "$force_ans" = "Y" ]; then
            rm -fr $PREFIX/*
            printf "\\n"
            printf "Finished to clear the installation directory: '%s'!\\n" "$PREFIX"
            printf "\\n"
        fi
    fi
fi

# creat install directory
if ! mkdir -p "$PREFIX"; then
    printf "ERROR: Could not create directory: '%s'\\n" "$PREFIX" >&2
    exit 1
fi

PREFIX=$(cd "$PREFIX"; pwd)
export PREFIX
printf "install prefix = %s\\n" "$PREFIX"

# extract the tarball appended to this header, this creates the *.tar.gz files
# for all the packages which get installed below
cd "$PREFIX"
printf "Extracting, please wait...\\n"

if ! tail -n +323 "$THIS_PATH" | tar xzvf -; then
    printf "ERROR: could not extract tar starting at line 323\\n" >&2
    exit 1
fi

printf "installation finished.\\n"

BASH_RC="$HOME"/.bashrc
eans=no
ask=yes

if [ "$SETENV" = "1" ]; then
    if [ "$DSETENV" = "1" ]; then
        eans=no
        ask=yes
    else
        eans=yes
        ask=no
    fi
else
    if [ "$DSETENV" = "1" ]; then
        eans=no
        ask=no
    else
        eans=no
        ask=yes
    fi
fi

if [ "$ask" = "yes" ]; then
    printf "Do you wish the installer to initialize @CPACK_PACKAGE_NAME@\\n"
    printf "in your %s ? [yes|no]\\n" "$BASH_RC"
    printf "[%s] >>> " "$eans"

    read -r ans
    if [ "$ans" != "" ]; then
        eans=$ans
    fi
fi

typeset -u PROJECT_UNAME
PROJECT_UNAME=@CPACK_PACKAGE_NAME@

if [ "$eans" != "yes" ] && [ "$eans" != "Yes" ] && [ "$eans" != "YES" ] && \
    [ "$eans" != "y" ]   && [ "$eans" != "Y" ]; then
    printf "\\n"
    printf "You may need to set it "$PROJECT_UNAME"_DIR manually in your $BASH_RC\\n"
    printf "\\n"
    printf "export "$PROJECT_UNAME"_DIR=\"$PREFIX/lib/cmake/@CPACK_PACKAGE_NAME@\"\\n"
    printf "\\n"
    printf "If it is a dynamic library, you also need to set LD_LIBRARY_PATH in your $BASH_RC\\n"
    printf "\\n"
    printf "export LD_LIBRARY_PATH=\"$PREFIX/lib:\$LD_LIBRARY_PATH\"\\n"
    printf "\\n"
    printf "Please source your $BASH_RC before include @CPACK_PACKAGE_NAME@ \\n"
    printf "\\n"
else
    printf "\\n"
    printf "Initializing @CPACK_PACKAGE_NAME@ in %s\\n" "$BASH_RC"
    printf "\\n"

    addDir="export "$PROJECT_UNAME"_DIR=\"$PREFIX/lib/cmake/@CPACK_PACKAGE_NAME@\""
    if ! grep "$addDir" $BASH_RC > /dev/null 2>&1; then
        echo "# @CPACK_PACKAGE_NAME@_DIR" >> $BASH_RC
        echo ${addDir} >> $BASH_RC
        printf "DIR of @CPACK_PACKAGE_NAME@ has been added in $BASH_RC\\n"
    else
        printf "DIR of @CPACK_PACKAGE_NAME@ already exists in $BASH_RC\\n"
    fi

    if [ ! "$(find $PREFIX/lib -name "*.a")" ]; then
        addLDPath="export LD_LIBRARY_PATH=\"$PREFIX/lib:\$LD_LIBRARY_PATH\""
        if ! grep "$addLDPath" $BASH_RC > /dev/null 2>&1; then
            echo "# @CPACK_PACKAGE_NAME@ LD_LIBRARY_PATH" >> $BASH_RC
            echo ${addLDPath} >> $BASH_RC
            printf "LD_LIBRARY_PATH of @CPACK_PACKAGE_NAME@ has been added in $BASH_RC\\n"
        else
            printf "LD_LIBRARY_PATH of @CPACK_PACKAGE_NAME@ already exists in $BASH_RC\\n"
        fi
    fi

    source $BASH_RC
    printf "\\n"
fi

printf "Thank you for installing @CPACK_PACKAGE_NAME@!\\n"
exit 0

### Start of TAR.GZ file ###;

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-05-18 18:01:17  更:2022-05-18 18:03:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 15:43:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码