如何使用CMake生成包含所有依赖共享库的胖可执行文件
如何用CMake生成包含所有依赖的胖可执行文件
要解决你的问题,Linux下有几种可行方案,结合你的CMake配置,具体实现如下:
方案1:静态链接所有依赖库
静态链接会将依赖库的代码直接嵌入可执行文件,生成独立的单文件。但需要确保所有依赖都提供静态版本:
- 修改CMake配置,优先查找静态库:
在find_package(Boost ...)前添加:
# 优先查找静态库文件 set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") # 强制Boost使用静态链接 set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_RUNTIME ON)
- 修正原配置的不合理之处:将
CMAKE_CXX_FLAGS中的-lrados移至target_link_libraries(链接选项应统一管理):
# 移除原FLAGS中的-lrados,保留C++17标准设置 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") target_link_libraries ( ${PROJECT_NAME} ${Boost_LIBRARIES} rados rbd Threads::Threads # 静态链接时可能需要显式添加系统依赖,如libdl,根据实际报错补充 dl )
- 编译前确保开发机安装了依赖的静态开发包(例如
boost-static、librados-static等),否则会出现链接错误。
⚠️ 注意:部分开源库(如LGPL协议)静态链接后分发需遵守协议条款,请提前确认许可。
方案2:打包依赖库+修改运行路径(更灵活)
如果某些依赖只有动态库版本,或不想静态链接,可以将依赖的.so文件与可执行文件打包,通过修改rpath让程序优先加载本地库:
- 添加CMake自定义命令,自动复制依赖库到输出目录:
在add_executable块后添加:
# 编译完成后自动复制依赖的共享库到可执行文件所在目录的libs子文件夹 add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:${PROJECT_NAME}>/libs COMMAND bash -c "ldd $<TARGET_FILE:${PROJECT_NAME}> | grep -E '(/usr/local/lib|/usr/lib|/opt/lib)' | awk '{print $3}' | xargs -I {} cp -v {} $<TARGET_FILE_DIR:${PROJECT_NAME}>/libs/" )
- 使用
patchelf修改可执行文件的rpath为相对路径:
先在开发机安装patchelf(yum install patchelf),然后在上述自定义命令后追加:
COMMAND patchelf --set-rpath '$ORIGIN/libs' $<TARGET_FILE:${PROJECT_NAME}>
编译完成后,将可执行文件和libs目录一起复制到ComputerB,即可直接运行。
方案3:生成单文件打包(类似AppImage)
如果需要真正的单文件分发,可以用AppImage工具将可执行文件与依赖打包成自解压的单文件:
- 安装AppImageTool
- 按照AppImage规范创建目录结构,放入可执行文件和所有依赖
- 运行AppImageTool生成单文件包
该方案需要额外工具支持,适合正式分发场景。
内容的提问来源于stack exchange,提问作者TyeolRik
相关产品推荐
相关产品推荐

