如何构建具有捆绑依赖项的静态库-CMake

时间:2019-06-29 00:33:50

标签: c++ opencv cmake static-libraries

我目前正在使用CMake创建一个静态库,该库利用了OpenCV 4中的一些静态库(核心imgcodecs视频highgui imgproc)。我的意图是能够将所有必需的OpenCV静态库捆绑到我自己的库中,以便我可以将其作为一个库分发。另外,我希望我的图书馆用户不必在他们的系统上安装OpenCV 4(但不介意用户是否必须使用apt-get install进行简单安装)。我知道有一些用于捆绑静态库的工具(例如在Linux上使用ar)。 但是,我真正遇到问题的地方是OpenCV的所有依赖项(例如libjpeg,libpng等)。我不必介意这些库是与我的捆绑在一起的还是动态链接的,因为它们相对易于安装(可以使用sudo apt-get install进行安装,而opencv4需要从源代码构建)。

执行此操作的最佳方法是什么? 这是我当前的CMakeLists.txt 它当前正在工作,但是那是因为我使用的是find_package(OpenCV REQUIRED)(这违背了我试图做的目的)。当我删除该行时,链接器会抱怨无法找到OpenCV依赖项。

cmake_minimum_required(VERSION 2.8)
project(myproject)

set(CMAKE_CXX_STANDARD 14)
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
link_directories(${CMAKE_CURRENT_LIST_DIR}/lib)

find_package(OpenMP REQUIRED)
find_package(OpenCV REQUIRED)

set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(nlohmann_json)

list(APPEND LINKER_LIBS opencv_core opencv_highgui opencv_video opencv_imgcodecs libmxnet.so libncnn.a nlohmann_json::nlohmann_json)
file(GLOB SRC${CMAKE_CURRENT_LIST_DIR}/src/*.cpp${CMAKE_CURRENT_LIST_DIR}/main.cpp)

add_library(myproject ${SRC})
target_link_libraries(myproject ${LINKER_LIBS} ${OpenMP_CXX_FLAGS})

详细说明我的问题。我构建生成libmyproject.a的项目。然后,我使用该库,最终从OpenCV库(libopencv_core.a libopencv_highgui.a libopencv_imgcodecs.a libopencv_video.a)中提取符号,并将其添加到我的lib中(目前,我尚未完成此步骤,这就是为什么在下面的示例中我链接libopencv_ *)。然后,在新项目中使用我的库,该项目的CMakeLists.txt如下所示:

cmake_minimum_required(VERSION 2.8)
project(myproject-driver)

set(CMAKE_CXX_STANDARD 14)
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
link_directories(${CMAKE_CURRENT_LIST_DIR}/lib)
find_package(OpenMP REQUIRED)

add_executable(myproject-driver main.cpp)
target_link_libraries(myproject-driver myproject libncnn.a ${OpenMP_CXX_FLAGS} libmxnet.so libopencv_core.a  libopencv_highgui.a  libopencv_imgcodecs.a  libopencv_video.a)

为此构建会产生以下错误:

Linking CXX executable myproject-driver
/usr/bin/ld: /home/nchafni/Cyrus/myproject/lib/libopencv_imgcodecs.a(grfmt_jpeg.cpp.o): undefined reference to symbol 'jpeg_default_qtables@@LIBJPEG_8.0'
//usr/lib/x86_64-linux-gnu/libjpeg.so.8: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

我该如何解决。是否有一些CMake命令可以为我链接所有这些依赖项?我是否需要手动跟踪这些libopencv_ *库的每个依赖关系并手动链接它们?再一次,这是假设使用libmyproject.a的人不能使用find_package(OpenCV REQUIRED),因为由于他们尚未在计算机上安装OpenCV,因此无法定义test([5,4,1], [1,16,25]) // would return true ..

1 个答案:

答案 0 :(得分:1)

首先,请勿使用2.8的超旧和过时的版本CMake
CMake 3.x如此强大,而且使用起来非常简单。
现代CMake 的一些提示。

  • 请勿使用file(GLOB),请参阅here
  • 请勿使用目录范围指令,而应使用 target 指令,例如target_include_directoriesinclude_directories
  • 请勿使用${<PACKAGE_NAME>_LIBRARIES}之类的字符串变量,而应使用 targets ,例如<Package_NAME>::lib
  • 使用 targets 代替 string变量时,该目标的所有 properties (包括 LINK_INTERFACE )将在调用target_link_libraries时被填充到库/可执行文件中,因此不再有include_directorieslink_directories等。

myproject

cmake_minimum_required(VERSION 3.14)

project(myproject)

set(CMAKE_CXX_STANDARD 14)

find_package(OpenMP REQUIRED)
find_package(OpenCV REQUIRED)

set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(nlohmann_json)

set(SOURCES ...) # list all the source files here

add_library(myproject ${SOURCES})
target_include_directories(myproject PUBLIC # give it a scope
                           ${CMAKE_CURRENT_LIST_DIR}/include
)
target_link_libraries(myproject PUBLIC # give it a scope
                      opencv_core # using the target, you will get all LINK_LIBRARIES
                      opencv_highgui 
                      opencv_video 
                      opencv_imgcodecs 
                      libmxnet.so  # where is this coming from?
                      libncnn.a # where is this coming from?
                      nlohmann_json::nlohmann_json 
                      OpenMP::OpenMP_CXX ## linking against a target, CXX_FLAGS will be populated automatically
)

myprojec驱动程序

cmake_minimum_required(VERSION 3.14)
project(myproject-driver)

set(CMAKE_CXX_STANDARD 14)

add_executable(myproject-driver main.cpp)
target_link_libraries(myproject-driver PUBLIC # give it a scope
                      myproject # gets all dependencies through the LINK_INTERFACE
)