Ubuntu22.04下如何通过CMake install打包项目所需OpenCV依赖
OpenCV可移植打包与依赖精简问题
问题背景
在Ubuntu22.04环境下通过sudo apt-get安装了OpenCV作为项目依赖,目标部署机器未安装OpenCV且无sudo权限,需要通过CMake的install命令将用到的OpenCV库打包为可移植版本,执行make install时自动复制所需库文件。
尝试过程与错误
使用的CMakeLists.txt片段:
find_package( OpenCV REQUIRED ) message("OpenCV_LIBS:") foreach(lib ${OpenCV_LIBS}) message("${lib}") endforeach() install(FILES ${OpenCV_LIBS} TYPE LIB)
执行cmake ..输出:
OpenCV_LIBS: opencv_calib3d opencv_core opencv_dnn opencv_features2d opencv_flann opencv_highgui //省略部分同类输出
执行make install时触发错误:
CMake Error at cmake_install.cmake:130 (file): file INSTALL cannot find "/home/john/myproject/opencv_calib3d": No such file or directory.
额外需求:如何只提供二进制程序实际依赖的OpenCV库,而非全部OpenCV组件?(目标机器为同版本Ubuntu)
问题分析
${OpenCV_LIBS}变量存储的是OpenCV库的逻辑名称(如opencv_core),而非库文件的绝对路径,因此CMake无法在当前项目目录下找到对应文件,导致安装失败。
解决方案
1. 正确获取OpenCV库路径并安装
修改CMake代码,通过get_target_property获取每个OpenCV库的实际文件路径,再执行安装:
find_package(OpenCV REQUIRED) # 收集所有OpenCV库的绝对路径 set(OPENCV_LIB_FILES "") foreach(lib ${OpenCV_LIBS}) get_target_property(lib_path ${lib} LOCATION) if(lib_path) list(APPEND OPENCV_LIB_FILES ${lib_path}) message("Found OpenCV library: ${lib_path}") endif() endforeach() # 安装OpenCV库到指定目录(默认CMAKE_INSTALL_PREFIX为/usr/local,可自定义) install(FILES ${OPENCV_LIB_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) # 可选:安装OpenCV头文件(若需在目标机器编译依赖代码则添加) install(DIRECTORY ${OpenCV_INCLUDE_DIRS}/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include/opencv)
执行cmake ..时会输出每个库的绝对路径,确认路径无误后执行make install即可完成库文件复制。
2. 仅打包实际依赖的OpenCV库
针对同系统部署场景,有两种高效方法:
方法一:用ldd手动分析依赖
编译完成项目二进制后,执行以下命令列出实际依赖的OpenCV库:
ldd ./your_project_binary | grep opencv
提取输出中的库文件绝对路径,替换CMake中OPENCV_LIB_FILES的内容,即可只安装这些必要库。
方法二:CMake自动收集运行时依赖
通过CMake的file(GET_RUNTIME_DEPENDENCIES)命令自动提取二进制的运行时依赖,仅安装涉及OpenCV的部分:
# 先安装项目二进制文件 install(TARGETS your_project_binary DESTINATION bin) # 自动收集并安装依赖的OpenCV库 install(CODE " file(GET_RUNTIME_DEPENDENCIES EXECUTABLES \$<TARGET_FILE:your_project_binary> RESOLVED_DEPENDENCIES_VAR RESOLVED_DEPS UNRESOLVED_DEPENDENCIES_VAR UNRESOLVED_DEPS ) foreach(dep \${RESOLVED_DEPS}) if(dep MATCHES \"opencv\") file(INSTALL DESTINATION \${CMAKE_INSTALL_PREFIX}/lib TYPE SHARED_LIBRARY FILES \"\${dep}\" ) endif() endforeach() ")
该方法会自动识别二进制实际需要的OpenCV库,无需手动筛选。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

