文章目錄
- 背景
- 動態庫
- 打包方案
- 動態庫轉靜態庫
- 動態庫打到軟件包中
- 運行
背景
使用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
,這個問題有待解決,不過不影響使用。