目录

1 静态依赖打包

1.1 依赖库的打包

1.2 依赖库的过滤

2 动态依赖打包

2.1 gdb查看程序依赖库

2.2 依赖库的打包

2.3 依赖库的过滤

3 Qt程序的打包说明

3.1 Qt的运行依赖库目录调整

3.2 Qt工程的依赖库、插件的设置


1 静态依赖打包

        若执行程序不涉及到库的动态加载,则可以使用ldd命令查看其依赖库,并将依赖库进行打包。

1.1 依赖库的打包

        使用pack_static.sh即可完成打包。

        使用命令:./pack_static.sh ./TestApp ./depend

        参数1:待打包的执行程序;

        参数2:依赖库存放的目录;

        pack_static.sh的实现如下:

#!/bin/bash  
basepath=$(cd `dirname $0`; pwd)

#不需要打包的目录
filter_folder_list=(
    "/lib" 
    "/usr/lib"
)

case $# in
    "0")
    echo "\033[31m error param \033[0m"
    echo "\033[32m [exe_name] [pack_dir] eg:./pack.sh TestApp usr/local/depend \033[0m"
    exit 0
;;
    "1")
    echo "use default pack_dir"
;;
esac

#程序名称
exe_name=$1

#打包目录
pack_dir=${basepath}/depend

if [ $# -ge 2 ];then
    pack_dir=$2
fi

echo "pack_dir=${pack_dir}"

if [ ! -d ${pack_dir} ];then
    mkdir ${pack_dir}
fi

#处理打包
function process_depend()
{
    #过滤不需要打包的目录
    for _folder in ${filter_folder_list[@]}
    do
        result=$(echo $1 | grep "^${_folder}")  
        
        if [ -n "${result}" ];then
            return
        fi
    done
    
    cp $1 $pack_dir
}

#打包动态库
deplist=$(ldd $exe_name | awk  '{if (match($3,"/")){ printf("%s "),$3 } }')  

#过滤不需要打包的目录
for dep_file in $deplist
do   
    process_depend "${dep_file}"
done

1.2 依赖库的过滤

        若不想打包某些系统目录下的依赖库,则需要对pack_static.sh中的参数进行调整。

       如上图,在filter_folder_list中添加需要过滤的目录即可,这样在打包时就可以过滤对应目录下的库文件。

        注:一般情况下是不能够打包系统目录下面的库,尤其是系统库(如libc.so.6之类)。这些库需要实际运行环境下的版本,若进行了打包反而会导致运行异常。

2 动态依赖打包

        若执行程序的运行涉及到库的动态加载(如插件),则需要使用gdb运行,并在gdb的输出日志中提取待打包的依赖库。

2.1 gdb查看程序依赖库

         以TestApp为例,执行流程如下:

a) 启用gdb运行,开启并输出gdb信息;

    gdb ./TestApp

    set logging file ./1.txt

    set logging on

    run

 b) 待程序正常启动且运行一段时间后,使用ctrl+c打断运行,并输入命令查看依赖的动态库;

     info shared

 

c) 一直敲回车,待依赖库的内容不再更新为止;

 d) 退出gdb;

     quit

这样在输出文件1.txt中就可以看到刚才的调试信息,其中红色方框部分就是该程序依赖的库。

2.2 依赖库的打包

       使用pack_dynamic.sh即可完成打包。

       使用命令:./pack_dynamic.sh ./1.txt ./depend

       参数1:章节2.1中的gdb输出信息;

       参数2:依赖库存放的目录;

       pack_dynamic.sh的实现如下:

#!/bin/bash  
basepath=$(cd `dirname $0`; pwd)

#标记找到动态库对应的位置
s_tag="From To Syms Read Shared Object Library"
shared_flag=0

#记录Qt的安装目录
QT_PATH="/opt/Qt5.5.1/5.5/gcc_64/"

#不需要打包的目录
filter_folder_list=(
    "/lib" 
    "/usr/lib"
)

#提示信息
case $# in
    "0")
    echo "\033[31m error param \033[0m"
    echo "\033[32m [exe_name] [pack_dir] eg:./3_simple_pack_dynamic.sh ./1.txt usr/local/depend \033[0m"
    exit 0
;;
    "1")
    echo "use default pack_dir"
;;
esac

#gdb文件名称
gdb_output_file=$1

#打包目录
pack_dir=${basepath}/depend

if [ $# -ge 2 ];then
    pack_dir=$2
fi

echo "pack_dir=${pack_dir}"

if [ ! -d ${pack_dir} ];then
    mkdir ${pack_dir}
fi

#处理Qt的依赖库(Qt库对存放目录有要求)
function process_qt_depend()
{
    folder_name=${1#*$QT_PATH}
    folder_name=${folder_name%/*}
    folder_name=${pack_dir}/${folder_name}

    if [ ! -d ${folder_name} ];then
        mkdir -p ${folder_name}
    fi

    cp $1 $folder_name
}

#处理依赖库
function process_depend()
{
    if [ -z $1 ];then    
        return
    fi

    #转换为绝对路径
    real_dll_file=$(readlink -f $1)

    #过滤不需要打包的目录
    for _folder in ${filter_folder_list[@]}
    do
        result=$(echo $real_dll_file | grep "^${_folder}")  
        
        if [ -n "${result}" ];then
            return
        fi
    done

    #处理Qt的依赖库
    result=$(echo $real_dll_file | grep "^${QT_PATH}")

    if [ -z "${result}" ];then
        cp $real_dll_file $pack_dir
    else
        process_qt_depend "${real_dll_file}"
    fi    
}

#分析gdb输出日志中的动态库
cat $gdb_output_file | while read line;
do
    result=$(echo $line | grep "${s_tag}")
    
    if [ -n "${result}" ];then
        shared_flag=1
    fi

    if [ ${shared_flag} -eq 1 ];then
        #提取最后一列
        dll_file=$(echo $line | awk  '{if (match($NF,"^/")){ printf("%s "),$NF } }')
        process_depend $dll_file
    fi
done


2.3 依赖库的过滤

        若不想打包某些系统目录下的依赖库,则需要对pack_dynamic中的参数进行调整。

        如上图,在filter_folder_list中添加需要过滤的目录即可,这样在打包时就可以过滤对应目录下的库文件。 

3 Qt程序的打包说明

       Qt程序对库的目录以及工程的设置有要求,具体的说明如下。

3.1 Qt的运行依赖库目录调整

       Qt的运行依赖插件和其核心库有目录上的要求。

 

       类似于libQt5Core.so.5.5.1,需要放到lib文件夹下,插件则需要放在plugins下对应的目录中。

       上述脚本可以按照该目录将qt的依赖库进行打包,若Qt的安装目录和示例中不一样,请安装实际的路径进行调整。

3.2 Qt工程的依赖库、插件的设置

  •        rpath的设置

       在CMakeLists.txt中,增加以下设置就可以设置执行程序的依赖库路径。

       set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,-rpath=./:./depend/:./depend/plugins/:./depend/lib")

       插件依赖目录的设置

       在main.cpp中,增加以下代码可以设置qt插件的依赖路径。

   

Logo

更多推荐