文章目录
- 背景
- 动态库
- 打包方案
- 动态库转静态库
- 动态库打到软件包中
- 运行
背景
使用C++编写的一个小项目,需要打包成ubuntu下的可执行文件,方便分发给其他ubuntu执行,因为docker镜像方案过于臃肿,所以需要把项目的动态库都打在软件包中,分发之后可以直接运行,而不需要再重复安装。
动态库
经过依赖精简和梳理,项目最终必须依赖的动态库包括:pcl, yaml, rosbag(用于读取rosbag包)
打包方案
第一步尝试将所有动态库转为静态库安装,发现 pcl 和 rosbag 间接依赖太多,只好暂时先将yaml库转为静态库,这里使用的方式是直接把yaml的源码包含进来。
动态库转静态库
这里把yaml的源码下载到 项目目录/thirdparty/yaml-cpp
目录结构如下:
在CMakeLists.txt中, 相关改动如下:
...
# 添加子目录编译 yaml-cpp 库
add_subdirectory(thirdparty/yaml-cpp)
...
target_include_directories(ExeFileName PUBLIC ...${CMAKE_SOURCE_DIR}/thirdparty/yaml-cpp/include
)
target_link_libraries(ExeFileName PUBLIC ...yaml-cpp...
)
...
动态库打到软件包中
这里用到了linuxdeploy-x86_64.AppImage
工具,安装方式为:
wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage -O /usr/local/bin/linuxdeploy
chmod +x /usr/local/bin/linuxdeploy
我们以pcl库为例,实际依赖库链接方式保持不变,只是需要在CMakeLists.txt
最后加上对应的用于linuxdeploy
的内容即可:
...
find_package(PCL REQUIRED COMPONENTS io)
...
target_include_directories(ExeFileName PUBLIC ${PCL_INCLUDE_DIRS}...
)# 链接库
target_link_libraries(ExeFileName PUBLIC ${PCL_LIBRARIES} ...
)# 设置安装路径为 AppDir 结构
install(TARGETS ExeFileName DESTINATION usr/bin)# 设置 RPATH(确保运行时库加载正确)
set_target_properties(ExeFileName PROPERTIESINSTALL_RPATH "$ORIGIN/../lib" # 相对路径指向 ../libBUILD_WITH_INSTALL_RPATH TRUEINSTALL_RPATH_USE_LINK_PATH TRUE
)# 修改原有的打包命令,确保在 Ubuntu 18.04 中兼容
add_custom_target(bundle_appimage_all_in_oneCOMMAND mkdir -p AppDir/usr/libCOMMAND linuxdeploy --appdir AppDir -e $<TARGET_FILE:ExeFileName> --output appimage --plugin none --executable $<TARGET_FILE:ExeFileName> # 显式指定可执行文件WORKING_DIRECTORY ${CMAKE_BINARY_DIR}DEPENDS ExeFileName
)
注意: 尽量在ubuntu低版本比如18.04上进行打包,以确保高版本ubuntu能向下兼容运行
在编译打包脚本中需要增加linuxdeploy
指令进行打包:
linuxdeploy --appdir AppDir -e ./ExeFileName \--library /lib/x86_64-linux-gnu/libusb-1.0.so.0 \--library /lib/x86_64-linux-gnu/libexpat.so.1
因为在运行时发现还是报错,缺少依赖库,所以在linuxdeploy
打包时把缺少的动态库显式指定出来。
运行
运行命令为:
LD_LIBRARY_PATH=./AppDir/usr/lib ./AppDir/usr/bin/ExeFileName ...
这里要强制带上LD_LIBRARY_PATH
,这个问题有待解决,不过不影响使用。