Как собрать статическую библиотеку со связанными зависимостями - CMake - PullRequest
0 голосов
/ 29 июня 2019

В настоящее время я использую CMake для создания статической библиотеки, которая использует несколько статических библиотек из OpenCV 4 (ядро imgcodecs video highgui imgproc).Мое намерение состоит в том, чтобы иметь возможность объединить все необходимые статические библиотеки OpenCV в мою собственную библиотеку, чтобы я мог распространять ее как одну библиотеку.Кроме того, я хочу, чтобы пользователю моей библиотеки не приходилось устанавливать OpenCV 4 в своей системе (но не против, если пользователь должен выполнить простую установку с помощью apt-get install).Я знаю, что есть инструменты для связывания статических библиотек (например, использование ar для Linux).Однако, где у меня действительно возникает проблема, так это со всеми зависимостями 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) и добавлю их в свою библиотеку (в настоящее время я еще не сделал этот шаг, которыйВот почему в приведенном ниже примере я связываю 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_ * libs и связывать их вручную?Еще раз, это предполагает, что человек, использующий libmyproject.a, не может использовать find_package(OpenCV REQUIRED), так как он не будет определен, так как он не установил OpenCV на своей машине.

1 Ответ

1 голос
/ 29 июня 2019

Прежде всего, не используйте супер старую и устаревшую версию 2.8 из CMake.
CMake 3.x гораздо более мощный и довольно простой в использовании.
Несколько советов для современного CMake .

  • Не используйте file(GLOB), см. здесь почему это так.
  • Не используйте инструкции для всего каталога , вместо этого используйте target инструкции, например. target_include_directories против include_directories.
  • Не используйте строковые переменные , как ${<PACKAGE_NAME>_LIBRARIES}, скорее используйте цели , например. <Package_NAME>::lib
  • При использовании целей вместо строковых переменных все свойства (включая LINK_INTERFACE ) этой цели будут заполнены для библиотека / исполняемый файл при вызове target_link_libraries, поэтому не более include_directories, link_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
)
...